/// <summary> /// 綁定特性群組到所有人物件(所有人>場景,由所有者綁定,除此之外勿使用此函數) /// </summary> /// <param name="owner">所有人</param> /// <param name="bindingLock">綁定後是否鎖定綁定功能</param> public void Binding(ObjectBase owner, bool bindingLock = false) { if (_Owner == owner) { return; } if (BindingLock) { throw new Exception("特性群組已被鎖定無法綁定"); } if (owner != null && owner.Propertys != this) { throw new Exception("所有者的特性群組物件不符"); } if (_Owner != null) { AllBreak(); } Owner = owner; Scene = null; BindingLock = bindingLock; OnBindingChanged(); }
/// <summary> /// 判斷指定活動物件是否存在集合內 /// </summary> /// <param name="item">活動物件</param> /// <returns>如果活動物件在集合中則為 true,否則為 false。</returns> public bool Contains(ObjectBase item) { return(_Collection.Contains(item)); }
/// <summary> /// 技能生效 /// </summary> public override void DoBeforeAction() { switch (Status) { case SkillStatus.Enabled: { if (Owner == null || Owner.MoveObject.Target.TargetType == TargetType.None) { Break(); return; } // 新增誘餌物件 double angle = Function.GetAngle(Owner.Layout.CenterX, Owner.Layout.CenterY, Owner.MoveObject.Target.X, Owner.MoveObject.Target.Y); MoveStraight move = new MoveStraight(null, Owner.MoveObject.Resistance, BaitSpeed, 1, 0, 1F); move.Target.SetOffsetByAngle(angle, 1000); DrawBase draw = Owner.DrawObject.Copy(); draw.Colors.Opacity = 0.6F; ObjectActive bait = new ObjectActive(Owner.Layout, BaitLife, Owner.League, draw, move); move.Target.SetObject(bait); bait.Propertys.Add(new PropertySpeeded(-1, -(BaitSpeed / (float)BaitLife * 800))); bait.Propertys.Add(new PropertyCollision(0)); // 強度碰撞 // 新增雜訊物件 int noiseWidth = Owner.Layout.Width + 2; int noiseHeight = (int)(Owner.Layout.Height * 1.3F + 0.5F) + 5; DrawNoise drawNoise = new DrawNoise(Owner.DrawObject.MainColor, Color.White, 1); ObjectWave noise = new ObjectWave(0, 0, noiseWidth, noiseHeight, noiseWidth * 3, noiseHeight * 3, -1, 0, drawNoise, MoveNull.Value); noise.DiffusionOpacity = 0; noise.Layout.Depend.SetObject(bait); Owner.Container.Add(bait); Owner.Container.Add(noise); // 將目標設為誘餌 for (int i = 0; i < Owner.Container.Count; i++) { ObjectBase objectBase = Owner.Container[i]; if (objectBase.Status != ObjectStatus.Alive || Function.IsFriendly(objectBase.League, Owner.League)) { continue; } if (objectBase.MoveObject.Target.Object == Owner) { objectBase.MoveObject.Target.SetObject(bait); } } bait.Dead += (s, e, t) => { noise.DiffusionTime.Limit = Scene.Sec(0.2F); noise.DiffusionTime.Value = 0; if (Owner == null) { return; } for (int i = 0; i < Owner.Container.Count; i++) { ObjectBase objectBase = Owner.Container[i]; if (objectBase.Status != ObjectStatus.Alive) { continue; } if (objectBase.MoveObject.Target.Object == s) { objectBase.MoveObject.Target.SetObject(Owner); } } SceneGaming scene = Scene as SceneGaming; if (t == ObjectDeadType.LifeEnd && scene != null) { scene.AddScoreToPlayer("誘餌生還", 300); } }; Status = SkillStatus.Cooldown; } break; } base.DoBeforeAction(); }
public override void DoAfterDead(ObjectBase killer, ObjectDeadType deadType) { if ((DeadType & deadType) != deadType) { return; } if (SharkPower > 0) { Scene.EffectObjects.Add(new EffectShark(Scene.Sec(0.2F), SharkPower)); } int explosionSize = (int)(RangeMultiple * (Owner.Layout.RectWidth + Owner.Layout.RectHeight) / 2) + RangeConstant; ObjectSmoke explosionObject = new ObjectSmoke(Owner.Layout.CenterX, Owner.Layout.CenterY, explosionSize, explosionSize, Scene.Sec(0.6F), 0.9F, 0, Color, MoveNull.Value); Owner.Container.Add(explosionObject); for (int i = 0; i < Owner.Container.Count; i++) { ObjectBase objectBase = Owner.Container[i]; if (objectBase.Status != ObjectStatus.Alive || Function.IsFriendly(objectBase.League, CollisionLeague)) { continue; } // 特殊狀態判定 具碰撞 非鬼魂 if ((objectBase.Propertys.Affix & SpecialStatus.Collision) != SpecialStatus.Collision || (objectBase.Propertys.Affix & SpecialStatus.Ghost) == SpecialStatus.Ghost) { continue; } // 碰撞判定 if (!Function.IsCollison(objectBase.Layout, explosionObject.Layout)) { continue; } // 檢查目標有無碰撞特性 int colliderPower = -1; for (int j = 0; j < objectBase.Propertys.Count; j++) { PropertyCollision checkCollision = objectBase.Propertys[j] as PropertyCollision; if (checkCollision != null && checkCollision.Status == PropertyStatus.Enabled) { colliderPower = Math.Max(colliderPower, checkCollision.CollisionPower); } } if (colliderPower < 0) { continue; } if (colliderPower <= CollisionPower) { objectBase.Kill(Owner, ObjectDeadType.Collision); } } base.DoAfterDead(killer, deadType); }
/// <summary> /// 增加活動物件到活動集合內 /// </summary> /// <param name="item">活動物件</param> public void Add(ObjectBase item) { _Collection.Add(item); item.Binding(this, true); item.Dead += OnObjectDead; }
public override void DoActionMoving() { if (Owner.Status == ObjectStatus.Alive && Status == PropertyStatus.Enabled) { for (int i = 0; i < Owner.Container.Count; i++) { ObjectBase objectActive = Owner.Container[i]; if (objectActive.Status != ObjectStatus.Alive || Function.IsFriendly(objectActive.League, Owner.League)) { continue; } // 限定目標 if (Target.TargetType == TargetType.GameObejct) { if (objectActive == Target.Object) { i = Owner.Container.Count; } else { continue; } } // 特殊狀態判定 具碰撞 非鬼魂 if ((objectActive.Propertys.Affix & SpecialStatus.Collision) != SpecialStatus.Collision || (objectActive.Propertys.Affix & SpecialStatus.Ghost) == SpecialStatus.Ghost) { continue; } // 碰撞判定 if (!Function.IsCollison(Owner.Layout, objectActive.Layout)) { continue; } int colliderPower = -1; for (int j = 0; j < objectActive.Propertys.Count; j++) { PropertyCollision checkCollision = objectActive.Propertys[j] as PropertyCollision; if (checkCollision != null && checkCollision.Status == PropertyStatus.Enabled) { if (checkCollision.Target.TargetType != TargetType.GameObejct || checkCollision.Target.Object == Owner) { colliderPower = Math.Max(colliderPower, checkCollision.CollisionPower); } } } if (colliderPower < 0) { continue; } if (colliderPower >= CollisionPower) { Owner.Kill(objectActive, ObjectDeadType.Collision); } if (CollisionPower >= colliderPower) { objectActive.Kill(Owner, ObjectDeadType.Collision); } } } base.DoActionMoving(); }
public override void DoAfterDead(ObjectBase killer, ObjectDeadType deadType) { if (Owner.DrawObject == DrawNull.Value || (DeadType & deadType) != deadType) { return; } double angle = Function.GetAngle(0, 0, Owner.MoveObject.MoveX, Owner.MoveObject.MoveY); DrawBase drawObject = Owner.DrawObject; Rectangle baseRectangle = Owner.Layout.Rectangle; Rectangle drawRectangle; if (drawObject.Scale > 1) { drawRectangle = drawObject.GetScaleRectangle(baseRectangle); baseRectangle.Location.Offset(-drawRectangle.Location.X, -drawRectangle.Location.Y); drawRectangle.Location = new Point(0, 0); } else { baseRectangle.Location = new Point(0, 0); drawRectangle = baseRectangle; } List <Point> getPoints = new List <Point>(); using (Bitmap image = new Bitmap(drawRectangle.Width, drawRectangle.Height)) using (Graphics g = Graphics.FromImage(image)) { Owner.DrawObject.Draw(g, baseRectangle); BitmapData bitData = image.LockBits(drawRectangle, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); IntPtr scan0 = bitData.Scan0; unsafe { byte *p = (byte *)scan0.ToPointer(); for (int y = 0; y < drawRectangle.Height; y++) { for (int x = 0; x < drawRectangle.Width; x++) { if (p[3] > 0) { getPoints.Add(new Point(x, y)); } p += 4; } } } image.UnlockBits(bitData); if (getPoints.Count == 0) { return; } int idxPlus = ((getPoints.Count - 1) / ScrapCount) + 1; int idx = Global.Rand.Next(idxPlus); for (int i = 0; i < ScrapCount; i++) { Point point = getPoints[idx]; PointF putPoint = new PointF(Owner.Layout.CenterX - (drawRectangle.Width / 2) + point.X, Owner.Layout.CenterY - (drawRectangle.Height / 2) + point.Y); int speed = Global.Rand.Next(ScrapSpeedMin, Math.Max(ScrapSpeedMin, ScrapSpeedMax)); int fadeTime = Global.Rand.Next(ScrapLifeMin, Math.Max(ScrapLifeMin, ScrapLifeMax)); double scrapDirection = angle + (Global.Rand.NextDouble() - 0.5) * Radiation; MoveStraight moveObject = new MoveStraight(null, 1, speed, 1, 0, 1); moveObject.Target.SetOffsetByAngle(scrapDirection, 1000); ObjectSmoke newObject; if (ScrapDrawObject == null) { Color drawColor = image.GetPixel(point.X, point.Y); newObject = new ObjectSmoke(putPoint.X, putPoint.Y, ScrapWidth, ScrapHeight, fadeTime, 1, 0, drawColor, moveObject); } else { DrawBase scrapDraw = ScrapDrawObject.Copy(); scrapDraw.Angle = Global.Rand.Next(360); newObject = new ObjectSmoke(putPoint.X, putPoint.Y, ScrapWidth, ScrapHeight, fadeTime, 1, 0, scrapDraw, moveObject); newObject.Propertys.Add(new PropertyRotate(-1, Global.Rand.Next(280, 520), false, true)); } moveObject.Target.SetObject(newObject); Owner.Container.Add(newObject); idx += idxPlus; if (idx >= getPoints.Count) { idx = Global.Rand.Next(idxPlus); } } } base.DoAfterDead(killer, deadType); }
/// <summary> /// 新增碰撞特性,兩個具碰撞屬性的物件接觸時,強度小的會被消滅,如果強度相同則兩者都會消滅 /// </summary> /// <param name="collisionPower">碰撞強度</param> public PropertyCollision(int collisionPower, ObjectBase target = null) { Affix = SpecialStatus.Collision | SpecialStatus.Movesplit; Target.SetObject(target); CollisionPower = collisionPower; }
/// <summary> /// 新增指定物件的目標管理物件 /// </summary> /// <param name="objectBase">物件</param> public TargetSet(ObjectBase objectBase) { SetObject(objectBase); }
public override void Binding(ObjectBase owner, bool bindingLock) { }
public override void DoBeforeActionMove() { switch (Status) { case SkillStatus.Enabled: { if (Owner == null) { Break(); return; } Status = SkillStatus.Channeled; _MiniBar = new PropertyUI(-1, new Size(30, 6), new DrawUICounterBar(Color.FromArgb(160, 210, 100), Color.Black, Color.White, 1, true, Channeled)); Owner.Propertys.Add(_MiniBar); PushSycle.Value = Scene.SceneIntervalOfRound; break; } case SkillStatus.Channeled: if (PushSycle.IsFull) { LayoutSet checkRange = new LayoutSet() { CollisonShape = ShapeType.Ellipse, Anchor = DirectionType.Center, X = Owner.Layout.X, Y = Owner.Layout.Y, Width = Range, Height = Range }; int hitCount = 0; for (int i = 0; i < Owner.Container.Count; i++) { ObjectBase objectActive = Owner.Container[i]; if (objectActive == Owner) { continue; } // 範圍判定 if (!Function.IsCollison(objectActive.Layout, checkRange)) { continue; } double angle = Function.GetAngle(checkRange.CenterX, checkRange.CenterY, objectActive.Layout.CenterX, objectActive.Layout.CenterY); double pushPower = PushPower * Function.GetDistance(checkRange.CenterX, checkRange.CenterY, objectActive.Layout.CenterX, objectActive.Layout.CenterY) / Range; objectActive.MoveObject.AddToNextOffset(objectActive.MoveObject.GetOffsetByAngle(angle, PushPower)); hitCount++; } if (hitCount > 0) { if (hitCount > 4) { hitCount = 4; } SceneGaming scene = Scene as SceneGaming; if (scene != null) { scene.AddScoreToPlayer("震盪衝擊", hitCount * 15); } } Color waveColor = Color.FromArgb(150, Owner.DrawObject.MainColor); ObjectWave wave = new ObjectWave(0, 0, 0, 0, Range, Range, Scene.Sec(0.15F), Scene.Sec(0.1F), new DrawPen(waveColor, ShapeType.Ellipse, 1), MoveNull.Value); wave.Layout.Depend.SetObject(Owner); wave.DiffusionOpacity = 0.1F; wave.FadeOpacity = 0.5F; Owner.Container.Add(wave); PushSycle.Value = 0; } else { PushSycle.Value += Scene.SceneIntervalOfRound; } break; } base.DoBeforeActionMove(); }
/// <summary> /// 死亡後執行動作 /// </summary> public virtual void DoAfterDead(ObjectBase killer, ObjectDeadType deadType) { Break(); }