public override void Process(DelayedAction action) { switch (action.Type) { case DelayedType.Damage: CompleteAttack(action.Params); break; case DelayedType.Recall: PetRecall(); break; } }
public abstract void Process(DelayedAction action);
private void CompleteMagic(IList<object> data) { bool train = false; PlayerObject player = (PlayerObject)data[0]; UserMagic magic = (UserMagic)data[1]; int value, value2; Point location; Cell cell; MirDirection dir; MonsterObject monster; Point front; switch (magic.Spell) { #region HellFire case Spell.HellFire: value = (int)data[2]; dir = (MirDirection)data[4]; location = Functions.PointMove((Point)data[3], dir, 1); int count = (int)data[5] - 1; if (!ValidPoint(location)) return; if (count > 0) { DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + 100, player, magic, value, location, dir, count); ActionList.Add(action); } cell = GetCell(location); if (cell.Objects == null) return; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (target.IsAttackTarget(player)) { if (target.Attacked(player, value, DefenceType.MAC, false) > 0) player.LevelMagic(magic); return; } break; } } break; #endregion #region SummonSkeleton case Spell.SummonSkeleton: monster = (MonsterObject)data[2]; front = (Point)data[3]; if (ValidPoint(front)) monster.Spawn(this, front); else monster.Spawn(player.CurrentMap, player.CurrentLocation); break; #endregion #region FireBang, IceStorm case Spell.IceStorm: case Spell.FireBang: value = (int)data[2]; location = (Point)data[3]; for (int y = location.Y - 1; y <= location.Y + 1; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 1; x <= location.X + 1; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (target.IsAttackTarget(player)) { if (target.Attacked(player, value, DefenceType.MAC, false) > 0) train = true; } break; } } } } break; #endregion #region MassHiding case Spell.MassHiding: value = (int)data[2]; location = (Point)data[3]; for (int y = location.Y - 1; y <= location.Y + 1; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 1; x <= location.X + 1; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (target.IsFriendlyTarget(player)) { for (int b = 0; b < target.Buffs.Count; b++) if (target.Buffs[b].Type == BuffType.Hiding) return; target.AddBuff(new Buff { Type = BuffType.Hiding, Caster = player, ExpireTime = Envir.Time + value * 1000 }); target.OperateTime = 0; train = true; } break; } } } } break; #endregion #region SoulShield, BlessedArmour case Spell.SoulShield: case Spell.BlessedArmour: value = (int)data[2]; location = (Point)data[3]; BuffType type = magic.Spell == Spell.SoulShield ? BuffType.SoulShield : BuffType.BlessedArmour; for (int y = location.Y - 3; y <= location.Y + 3; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 3; x <= location.X + 3; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (target.IsFriendlyTarget(player)) { target.AddBuff(new Buff { Type = type, Caster = player, ExpireTime = Envir.Time + value * 1000, Values = new int[]{ target.Level / 7 + 4 } }); target.OperateTime = 0; train = true; } break; } } } } break; #endregion #region FireWall case Spell.FireWall: value = (int)data[2]; location = (Point)data[3]; player.LevelMagic(magic); if (ValidPoint(location)) { cell = GetCell(location); bool cast = true; if (cell.Objects != null) for (int o = 0; o < cell.Objects.Count; o++) { MapObject target = cell.Objects[o]; if (target.Race != ObjectType.Spell || ((SpellObject)target).Spell != Spell.FireWall) continue; cast = false; break; } if (cast) { SpellObject ob = new SpellObject { Spell = Spell.FireWall, Value = value, ExpireTime = Envir.Time + (10 + value / 2) * 1000, TickSpeed = 2000, Caster = player, CurrentLocation = location, CurrentMap = this, }; AddObject(ob); ob.Spawned(); } } dir = MirDirection.Up; for (int i = 0; i < 4; i++) { location = Functions.PointMove((Point)data[3], dir, 1); dir += 2; if (!ValidPoint(location)) continue; cell = GetCell(location); bool cast = true; if (cell.Objects != null) for (int o = 0; o < cell.Objects.Count; o++) { MapObject target = cell.Objects[o]; if (target.Race != ObjectType.Spell || ((SpellObject)target).Spell != Spell.FireWall) continue; cast = false; break; } if (!cast) continue; SpellObject ob = new SpellObject { Spell = Spell.FireWall, Value = value, ExpireTime = Envir.Time + (10 + value / 2) * 1000, TickSpeed = 2000, Caster = player, CurrentLocation = location, CurrentMap = this, }; AddObject(ob); ob.Spawned(); } break; #endregion #region Lightning case Spell.Lightning: value = (int)data[2]; location = (Point)data[3]; dir = (MirDirection)data[4]; for (int i = 0; i < 6; i++) { location = Functions.PointMove(location, dir, 1); if (!ValidPoint(location)) continue; cell = GetCell(location); if (cell.Objects == null) continue; for (int o = 0; o < cell.Objects.Count; o++) { MapObject target = cell.Objects[o]; if (target.Race != ObjectType.Player && target.Race != ObjectType.Monster) continue; if (!target.IsAttackTarget(player)) continue; if (target.Attacked(player, value, DefenceType.MAC, false) > 0) train = true; break; } } break; #endregion #region HeavenlySword case Spell.HeavenlySword: value = (int)data[2]; location = (Point)data[3]; dir = (MirDirection)data[4]; for (int i = 0; i < 3; i++) { location = Functions.PointMove(location, dir, 1); if (!ValidPoint(location)) continue; cell = GetCell(location); if (cell.Objects == null) continue; for (int o = 0; o < cell.Objects.Count; o++) { MapObject target = cell.Objects[o]; if (target.Race != ObjectType.Player && target.Race != ObjectType.Monster) continue; if (!target.IsAttackTarget(player)) continue; if (target.Attacked(player, value, DefenceType.MAC, false) > 0) train = true; break; } } break; #endregion #region MassHealing case Spell.MassHealing: value = (int)data[2]; location = (Point)data[3]; for (int y = location.Y - 1; y <= location.Y + 1; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 1; x <= location.X + 1; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (target.IsFriendlyTarget(player)) { if (target.Health >= target.MaxHealth) continue; target.HealAmount = (ushort)Math.Min(ushort.MaxValue, target.HealAmount + value); target.OperateTime = 0; train = true; } break; } } } } break; #endregion #region ThunderStorm case Spell.ThunderStorm: case Spell.FlameField: case Spell.NapalmShot: value = (int)data[2]; location = (Point)data[3]; for (int y = location.Y - 2; y <= location.Y + 2; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 2; x <= location.X + 2; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (!target.IsAttackTarget(player)) break; if (target.Attacked(player, magic.Spell == Spell.ThunderStorm && !target.Undead ? value / 10 : value , DefenceType.MAC, false) <= 0) break; train = true; break; } } } } break; #endregion #region SummonShinsu case Spell.SummonShinsu: monster = (MonsterObject)data[2]; front = (Point)data[3]; if (ValidPoint(front)) monster.Spawn(this, front); else monster.Spawn(player.CurrentMap, player.CurrentLocation); break; #endregion #region LionRoar case Spell.LionRoar: location = (Point)data[2]; for (int y = location.Y - 2; y <= location.Y + 2; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 2; x <= location.X + 2; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; if (target.Race != ObjectType.Monster) continue; //Only targets if (!target.IsAttackTarget(player) || player.Level + 10 < target.Level) continue; target.ApplyPoison(new Poison { PType = PoisonType.Paralysis, Duration = magic.Level + 2, TickSpeed = 1000 }, player); target.OperateTime = 0; train = true; } } } break; #endregion #region PoisonCloud case Spell.PoisonCloud: value = (int)data[2]; location = (Point)data[3]; byte bonusdmg = (byte)data[4]; train = true; bool show = true; for (int y = location.Y - 1; y <= location.Y + 1; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 1; x <= location.X + 1; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid) continue; bool cast = true; if (cell.Objects != null) for (int o = 0; o < cell.Objects.Count; o++) { MapObject target = cell.Objects[o]; if (target.Race != ObjectType.Spell || ((SpellObject)target).Spell != Spell.PoisonCloud) continue; cast = false; break; } if (!cast) continue; SpellObject ob = new SpellObject { Spell = Spell.PoisonCloud, Value = value + bonusdmg, ExpireTime = Envir.Time + 6000, TickSpeed = 1000, Caster = player, CurrentLocation = new Point(x, y), CastLocation = location, Show = show, CurrentMap = this, }; show = false; AddObject(ob); ob.Spawned(); } } break; #endregion #region IceThrust case Spell.IceThrust: { location = (Point)data[2]; MirDirection direction = (MirDirection)data[3]; int criticalDamage = (int)data[4]; int nearDamage = (int)data[5]; int farDamage = (int)data[6]; int col = 3; int row = 3; Point[] loc = new Point[col]; //0 = left 1 = center 2 = right loc[0] = Functions.PointMove(location, Functions.PreviousDir(direction), 1); loc[1] = Functions.PointMove(location, direction, 1); loc[2] = Functions.PointMove(location, Functions.NextDir(direction), 1); for (int i = 0; i < col; i++) { Point startPoint = loc[i]; for (int j = 0; j < row; j++) { Point hitPoint = Functions.PointMove(startPoint, direction, j); if (!ValidPoint(hitPoint)) continue; cell = GetCell(hitPoint); if (cell.Objects == null) continue; for (int k = 0; k < cell.Objects.Count; k++) { MapObject target = cell.Objects[k]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: if (target.IsAttackTarget(player)) { //Only targets if (target.Attacked(player, j <= 1 ? nearDamage : farDamage, DefenceType.MAC, false) > 0) { if (player.Level + (target.Race == ObjectType.Player ? 2 : 10) >= target.Level && Envir.Random.Next(target.Race == ObjectType.Player ? 100 : 20) <= magic.Level) { target.ApplyPoison(new Poison { Owner = player, Duration = target.Race == ObjectType.Player ? 4 : 5 + Envir.Random.Next(5), PType = PoisonType.Slow, TickSpeed = 1000, }, player); target.OperateTime = 0; } if (player.Level + (target.Race == ObjectType.Player ? 2 : 10) >= target.Level && Envir.Random.Next(target.Race == ObjectType.Player ? 100 : 40) <= magic.Level) { target.ApplyPoison(new Poison { Owner = player, Duration = target.Race == ObjectType.Player ? 2 : 5 + Envir.Random.Next(player.Freezing), PType = PoisonType.Frozen, TickSpeed = 1000, }, player); target.OperateTime = 0; } train = true; } } break; } } } } } break; #endregion #region SlashingBurst case Spell.SlashingBurst: value = (int)data[2]; location = (Point)data[3]; dir = (MirDirection)data[4]; count = (int)data[5]; for (int i = 0; i < count; i++) { location = Functions.PointMove(location, dir, 1); if (!ValidPoint(location)) continue; cell = GetCell(location); if (cell.Objects == null) continue; for (int o = 0; o < cell.Objects.Count; o++) { MapObject target = cell.Objects[o]; if (target.Race != ObjectType.Player && target.Race != ObjectType.Monster) continue; if (!target.IsAttackTarget(player)) continue; if (target.Attacked(player, value, DefenceType.AC, false) > 0) train = true; break; } } break; #endregion #region Mirroring case Spell.Mirroring: monster = (MonsterObject)data[2]; front = (Point)data[3]; bool finish = (bool)data[4]; if (finish) { monster.Die(); return; }; if (ValidPoint(front)) monster.Spawn(this, front); else monster.Spawn(player.CurrentMap, player.CurrentLocation); break; #endregion #region Blizzard case Spell.Blizzard: value = (int)data[2]; location = (Point)data[3]; train = true; show = true; for (int y = location.Y - 2; y <= location.Y + 2; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 2; x <= location.X + 2; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid) continue; bool cast = true; if (cell.Objects != null) for (int o = 0; o < cell.Objects.Count; o++) { MapObject target = cell.Objects[o]; if (target.Race != ObjectType.Spell || ((SpellObject) target).Spell != Spell.Blizzard) continue; cast = false; break; } if (!cast) continue; SpellObject ob = new SpellObject { Spell = Spell.Blizzard, Value = value, ExpireTime = Envir.Time + 3000, TickSpeed = 440, Caster = player, CurrentLocation = new Point(x, y), CastLocation = location, Show = show, CurrentMap = this, StartTime = Envir.Time + 800, }; show = false; AddObject(ob); ob.Spawned(); } } break; #endregion #region MeteorStrike case Spell.MeteorStrike: value = (int)data[2]; location = (Point)data[3]; train = true; show = true; for (int y = location.Y - 2; y <= location.Y + 2; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 2; x <= location.X + 2; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid) continue; bool cast = true; if (cell.Objects != null) for (int o = 0; o < cell.Objects.Count; o++) { MapObject target = cell.Objects[o]; if (target.Race != ObjectType.Spell || ((SpellObject)target).Spell != Spell.MeteorStrike) continue; cast = false; break; } if (!cast) continue; SpellObject ob = new SpellObject { Spell = Spell.MeteorStrike, Value = value, ExpireTime = Envir.Time + 3000, TickSpeed = 440, Caster = player, CurrentLocation = new Point(x, y), CastLocation = location, Show = show, CurrentMap = this, StartTime = Envir.Time + 800, }; show = false; AddObject(ob); ob.Spawned(); } } break; #endregion #region TrapHexagon case Spell.TrapHexagon: value = (int)data[2]; location = (Point)data[3]; MonsterObject centerTarget = null; for (int y = location.Y - 1; y <= location.Y + 1; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 1; x <= location.X + 1; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; if (y == location.Y && x == location.X && target.Race == ObjectType.Monster) { centerTarget = (MonsterObject)target; } switch (target.Race) { case ObjectType.Monster: if (target == null || !target.IsAttackTarget(player) || target.Node == null || target.Level > player.Level + 2) continue; MonsterObject mobTarget = (MonsterObject)target; if (centerTarget == null) centerTarget = mobTarget; mobTarget.ShockTime = Envir.Time + value; mobTarget.Target = null; break; } } } } if (centerTarget == null) return; for (byte i = 0; i < 8; i += 2) { Point startpoint = Functions.PointMove(location, (MirDirection)i, 2); for (byte j = 0; j <= 4; j += 4) { MirDirection spawndirection = i == 0 || i == 4 ? MirDirection.Right : MirDirection.Up; Point spawnpoint = Functions.PointMove(startpoint, spawndirection + j, 1); if (spawnpoint.X <= 0 || spawnpoint.X > centerTarget.CurrentMap.Width) continue; if (spawnpoint.Y <= 0 || spawnpoint.Y > centerTarget.CurrentMap.Height) continue; SpellObject ob = new SpellObject { Spell = Spell.TrapHexagon, ExpireTime = Envir.Time + value, TickSpeed = 100, Caster = player, CurrentLocation = spawnpoint, CastLocation = location, CurrentMap = centerTarget.CurrentMap, Target = centerTarget, }; centerTarget.CurrentMap.AddObject(ob); ob.Spawned(); } } train = true; break; #endregion #region SummonHolyDeva case Spell.SummonHolyDeva: monster = (MonsterObject)data[2]; front = (Point)data[3]; if (ValidPoint(front)) monster.Spawn(this, front); else monster.Spawn(player.CurrentMap, player.CurrentLocation); break; #endregion #region Curse case Spell.Curse: value = (int)data[2]; location = (Point)data[3]; value2 = (int)data[4]; type = BuffType.Curse; for (int y = location.Y - 3; y <= location.Y + 3; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 3; x <= location.X + 3; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: if (Envir.Random.Next(10) >= 4) continue; //Only targets if (target.IsAttackTarget(player)) { target.ApplyPoison(new Poison { PType = PoisonType.Slow, Duration = value, TickSpeed = 1000, Value = value2 }, player); target.AddBuff(new Buff { Type = type, Caster = player, ExpireTime = Envir.Time + value * 1000, Values = new int[]{ value2 } }); target.OperateTime = 0; train = true; } break; } } } } break; #endregion #region ExplosiveTrap case Spell.ExplosiveTrap: value = (int)data[2]; front = (Point)data[3]; int trapID = (int)data[4]; if (ValidPoint(front)) { cell = GetCell(front); bool cast = true; if (cell.Objects != null) for (int o = 0; o < cell.Objects.Count; o++) { MapObject target = cell.Objects[o]; if (target.Race != ObjectType.Spell || (((SpellObject)target).Spell != Spell.FireWall && ((SpellObject)target).Spell != Spell.ExplosiveTrap)) continue; cast = false; break; } if (cast) { player.LevelMagic(magic); System.Drawing.Point[] Traps = new Point[3]; Traps[0] = front; Traps[1] = Functions.Left(front, player.Direction); Traps[2] = Functions.Right(front, player.Direction); for (int i = 0; i <= 2; i++) { SpellObject ob = new SpellObject { Spell = Spell.ExplosiveTrap, Value = value, ExpireTime = Envir.Time + (10 + value / 2) * 1000, TickSpeed = 500, Caster = player, CurrentLocation = Traps[i], CurrentMap = this, ExplosiveTrapID = trapID, ExplosiveTrapCount = i }; AddObject(ob); ob.Spawned(); player.ArcherTrapObjectsArray[trapID, i] = ob; } } } break; #endregion #region Plague case Spell.Plague: value = (int)data[2]; location = (Point)data[3]; for (int y = location.Y - 3; y <= location.Y + 3; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 3; x <= location.X + 3; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (target.IsAttackTarget(player)) { int chance = Envir.Random.Next(6); PoisonType poison; switch (chance) { case 0: poison = PoisonType.Slow; break; case 1: poison = PoisonType.Frozen; break; case 2: poison = (PoisonType)data[4]; break; default: poison = PoisonType.None; break; } int tempValue = 0; if (poison == PoisonType.Green) { tempValue = value / 15 + magic.Level + 1; } else { tempValue = value + (magic.Level + 1) * 2; } if (poison != PoisonType.None) { target.ApplyPoison(new Poison { PType = poison, Duration = (2 * (magic.Level + 1)) + (value / 10), TickSpeed = 1000, Value = tempValue, Owner = player }, player); } if (target.Race == ObjectType.Player) { PlayerObject tempOb = (PlayerObject)target; tempOb.ChangeMP(-tempValue); } train = true; } break; } } } } break; #endregion #region Trap case Spell.Trap: value = (int)data[2]; location = (Point)data[3]; MonsterObject selectTarget = null; if (!ValidPoint(location)) break; cell = GetCell(location); if (!cell.Valid || cell.Objects == null) break; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; if (target.Race == ObjectType.Monster) { selectTarget = (MonsterObject)target; if (selectTarget == null || !selectTarget.IsAttackTarget(player) || selectTarget.Node == null || selectTarget.Level >= player.Level + 2) continue; selectTarget.ShockTime = Envir.Time + value; selectTarget.Target = null; break; } } if (selectTarget == null) return; if (location.X <= 0 || location.X > selectTarget.CurrentMap.Width) break; if (location.Y <= 0 || location.Y > selectTarget.CurrentMap.Height) break; SpellObject spellOb = new SpellObject { Spell = Spell.Trap, ExpireTime = Envir.Time + value, TickSpeed = 100, Caster = player, CurrentLocation = location, CastLocation = location, CurrentMap = selectTarget.CurrentMap, Target = selectTarget, }; selectTarget.CurrentMap.AddObject(spellOb); spellOb.Spawned(); train = true; break; #endregion #region OneWithNature case Spell.OneWithNature: value = (int)data[2]; location = (Point)data[3]; bool hasVampBuff = (player.Buffs.Where(ex => ex.Type == BuffType.VampireShot).ToList().Count() > 0); bool hasPoisonBuff = (player.Buffs.Where(ex => ex.Type == BuffType.PoisonShot).ToList().Count() > 0); for (int y = location.Y - 2; y <= location.Y + 2; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 2; x <= location.X + 2; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (!target.IsAttackTarget(player) || target.Dead) break; //knockback //int distance = 1 + Math.Max(0, magic.Level - 1) + Envir.Random.Next(2); //dir = Functions.DirectionFromPoint(location, target.CurrentLocation); //if(target.Level < player.Level) // target.Pushed(player, dir, distance);// <--crashes server somehow? if (target.Attacked(player, value, DefenceType.MAC, false) <= 0) break; if (hasVampBuff)//Vampire Effect { if (player.VampAmount == 0) player.VampTime = Envir.Time + 1000; player.VampAmount += (ushort)(value * (magic.Level + 1) * 0.25F); } if (hasPoisonBuff)//Poison Effect { target.ApplyPoison(new Poison { Duration = (value * 2) + (magic.Level + 1) * 7, Owner = player, PType = PoisonType.Green, TickSpeed = 2000, Value = value / 15 + magic.Level + 1 + Envir.Random.Next(player.PoisonAttack) }, player); target.OperateTime = 0; } train = true; break; } } } } if (hasVampBuff)//Vampire Effect { //cancel out buff player.AddBuff(new Buff { Type = BuffType.VampireShot, Caster = player, ExpireTime = Envir.Time + 1000, Values = new int[]{ value }, Visible = true, ObjectID = player.ObjectID }); } if (hasPoisonBuff)//Poison Effect { //cancel out buff player.AddBuff(new Buff { Type = BuffType.PoisonShot, Caster = player, ExpireTime = Envir.Time + 1000, Values = new int[]{ value }, Visible = true, ObjectID = player.ObjectID }); } break; #endregion #region ArcherSummons case Spell.SummonVampire: case Spell.SummonToad: case Spell.SummonSnakes: monster = (MonsterObject)data[2]; front = (Point)data[3]; if (ValidPoint(front)) monster.Spawn(this, front); else monster.Spawn(player.CurrentMap, player.CurrentLocation); break; #endregion #region Portal case Spell.Portal: value = (int)data[2]; location = (Point)data[3]; spellOb = new SpellObject { Spell = Spell.Portal, Value = 0, ExpireTime = Envir.Time + value * 1000, TickSpeed = 2000, Caster = player, CurrentLocation = location, CurrentMap = this, }; if (player.PortalObjectsArray[0] == null) { player.PortalObjectsArray[0] = spellOb; } else { player.PortalObjectsArray[1] = spellOb; player.PortalObjectsArray[1].ExitMap = player.PortalObjectsArray[0].CurrentMap; player.PortalObjectsArray[1].ExitCoord = player.PortalObjectsArray[0].CurrentLocation; player.PortalObjectsArray[0].ExitMap = player.PortalObjectsArray[1].CurrentMap; player.PortalObjectsArray[0].ExitCoord = player.PortalObjectsArray[1].CurrentLocation; } AddObject(spellOb); spellOb.Spawned(); train = true; break; #endregion #region DelayedExplosion case Spell.DelayedExplosion: value = (int)data[2]; location = (Point)data[3]; for (int y = location.Y - 1; y <= location.Y + 1; y++) { if (y < 0) continue; if (y >= Height) break; for (int x = location.X - 1; x <= location.X + 1; x++) { if (x < 0) continue; if (x >= Width) break; cell = GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject target = cell.Objects[i]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (target.IsAttackTarget(player)) { if (target.Attacked(player, value, DefenceType.MAC, false) > 0) train = false;//wouldnt want to make the skill give twice the points } break; } } } } break; #endregion } if (train) player.LevelMagic(magic); }
private void CompleteMagic(IList<object> data) { UserMagic magic = (UserMagic)data[0]; int value; MapObject target; Point location; MonsterObject monster; switch (magic.Spell) { #region FireBall, GreatFireBall, ThunderBolt, SoulFireBall, FlameDisruptor case Spell.FireBall: case Spell.GreatFireBall: case Spell.ThunderBolt: case Spell.SoulFireBall: case Spell.FlameDisruptor: case Spell.StraightShot: case Spell.DoubleShot: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; if (target.Attacked(this, value, DefenceType.MAC, false) > 0) LevelMagic(magic); break; #endregion #region FrostCrunch case Spell.FrostCrunch: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; if (target.Attacked(this, value, DefenceType.MAC, false) > 0) { if (Level + (target.Race == ObjectType.Player ? 2 : 10) >= target.Level && Envir.Random.Next(target.Race == ObjectType.Player ? 100 : 20) <= magic.Level) { target.ApplyPoison(new Poison { Owner = this, Duration = target.Race == ObjectType.Player ? 4 : 5 + Envir.Random.Next(5), PType = PoisonType.Slow, TickSpeed = 1000, }, this); target.OperateTime = 0; } if (Level + (target.Race == ObjectType.Player ? 2 : 10) >= target.Level && Envir.Random.Next(target.Race == ObjectType.Player ? 100 : 40) <= magic.Level) { target.ApplyPoison(new Poison { Owner = this, Duration = target.Race == ObjectType.Player ? 2 : 5 + Envir.Random.Next(Freezing), PType = PoisonType.Frozen, TickSpeed = 1000, }, this); target.OperateTime = 0; } LevelMagic(magic); } break; #endregion #region Vampirism case Spell.Vampirism: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; value = target.Attacked(this, value, DefenceType.MAC, false); if (value == 0) return; LevelMagic(magic); if (VampAmount == 0) VampTime = Envir.Time + 1000; VampAmount += (ushort)(value * (magic.Level + 1) * 0.25F); break; #endregion #region Healing case Spell.Healing: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || !target.IsFriendlyTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; if (target.Health >= target.MaxHealth) return; target.HealAmount = (ushort)Math.Min(ushort.MaxValue, target.HealAmount + value); target.OperateTime = 0; LevelMagic(magic); break; #endregion #region ElectricShock case Spell.ElectricShock: monster = (MonsterObject)data[1]; if (monster == null || !monster.IsAttackTarget(this) || monster.CurrentMap != CurrentMap || monster.Node == null) return; ElectricShock(monster, magic); break; #endregion #region Poisoning case Spell.Poisoning: value = (int)data[1]; target = (MapObject)data[2]; UserItem item = (UserItem)data[3]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; switch (item.Info.Shape) { case 1: target.ApplyPoison(new Poison { Duration = (value * 2) + ((magic.Level + 1) * 7), Owner = this, PType = PoisonType.Green, TickSpeed = 2000, Value = value / 15 + magic.Level + 1 + Envir.Random.Next(PoisonAttack) }, this); break; case 2: target.ApplyPoison(new Poison { Duration = (value * 2) + (magic.Level + 1) * 7, Owner = this, PType = PoisonType.Red, TickSpeed = 2000, }, this); break; } target.OperateTime = 0; LevelMagic(magic); break; #endregion #region StormEscape case Spell.StormEscape: location = (Point) data[1]; if (CurrentMap.Info.NoTeleport) { ReceiveChat(("You cannot teleport on this map"), ChatType.System); return; } if (!CurrentMap.ValidPoint(location) || Envir.Random.Next(4) >= magic.Level + 1 || !Teleport(CurrentMap, location, false)) return; CurrentMap.Broadcast(new S.ObjectEffect { ObjectID = ObjectID, Effect = SpellEffect.StormEscape }, CurrentLocation); AddBuff(new Buff { Type = BuffType.TemporalFlux, Caster = this, ExpireTime = Envir.Time + 30000 }); LevelMagic(magic); break; #endregion #region Teleport case Spell.Teleport: Map temp = Envir.GetMap(BindMapIndex); int mapSizeX = temp.Width / (magic.Level + 1); int mapSizeY = temp.Height / (magic.Level + 1); if (CurrentMap.Info.NoTeleport) { ReceiveChat(("You cannot teleport on this map"), ChatType.System); return; } for (int i = 0; i < 200; i++) { location = new Point(BindLocation.X + Envir.Random.Next(-mapSizeX, mapSizeX), BindLocation.Y + Envir.Random.Next(-mapSizeY, mapSizeY)); if (Teleport(temp, location)) break; } AddBuff(new Buff { Type = BuffType.TemporalFlux, Caster = this, ExpireTime = Envir.Time + 30000 }); LevelMagic(magic); break; #endregion #region Blink case Spell.Blink: { location = (Point)data[1]; if (CurrentMap.Info.NoTeleport) { ReceiveChat(("You cannot teleport on this map"), ChatType.System); return; } if (Functions.InRange(CurrentLocation, location, magic.Info.Range) == false) return; if (!CurrentMap.ValidPoint(location) || Envir.Random.Next(4) >= magic.Level + 1 || !Teleport(CurrentMap, location, false)) return; CurrentMap.Broadcast(new S.ObjectEffect { ObjectID = ObjectID, Effect = SpellEffect.Teleport }, CurrentLocation); LevelMagic(magic); AddBuff(new Buff { Type = BuffType.TemporalFlux, Caster = this, ExpireTime = Envir.Time + 30000 }); } break; #endregion #region Hiding case Spell.Hiding: for (int i = 0; i < Buffs.Count; i++) if (Buffs[i].Type == BuffType.Hiding) return; value = (int)data[1]; AddBuff(new Buff { Type = BuffType.Hiding, Caster = this, ExpireTime = Envir.Time + value * 1000 }); LevelMagic(magic); break; #endregion #region Haste case Spell.Haste: AddBuff(new Buff { Type = BuffType.Haste, Caster = this, ExpireTime = Envir.Time + (magic.Level + 1) * 30000, Values = new int[] { (magic.Level + 1) * 2 } }); LevelMagic(magic); break; #endregion #region Fury case Spell.Fury: AddBuff(new Buff { Type = BuffType.Fury, Caster = this, ExpireTime = Envir.Time + 60000 + magic.Level * 10000, Values = new int[] { 4 }, Visible = true }); LevelMagic(magic); break; #endregion #region ImmortalSkin case Spell.ImmortalSkin: int ACvalue = (int)Math.Round(MaxAC * (0.10 + (0.07 * magic.Level))); int DCValue = (int)Math.Round(MaxDC * (0.05 + (0.01 * magic.Level))); AddBuff(new Buff { Type = BuffType.ImmortalSkin, Caster = this, ExpireTime = Envir.Time + 60000 + magic.Level * 1000, Values = new int[] { ACvalue, DCValue }, Visible = true }); LevelMagic(magic); break; #endregion #region LightBody case Spell.LightBody: AddBuff(new Buff { Type = BuffType.LightBody, Caster = this, ExpireTime = Envir.Time + (magic.Level + 1) * 30000, Values = new int[] { (magic.Level + 1) * 2 } }); LevelMagic(magic); break; #endregion #region MagicShield case Spell.MagicShield: if (MagicShield) return; MagicShield = true; MagicShieldLv = magic.Level; MagicShieldTime = Envir.Time + (int)data[1] * 1000; CurrentMap.Broadcast(new S.ObjectEffect { ObjectID = ObjectID, Effect = SpellEffect.MagicShieldUp }, CurrentLocation); AddBuff(new Buff { Type = BuffType.MagicShield, Caster = this, ExpireTime = MagicShieldTime }); LevelMagic(magic); break; #endregion #region TurnUndead case Spell.TurnUndead: monster = (MonsterObject)data[1]; if (monster == null || !monster.IsAttackTarget(this) || monster.CurrentMap != CurrentMap || monster.Node == null) return; monster.LastHitter = this; monster.LastHitTime = Envir.Time + 5000; monster.EXPOwner = this; monster.EXPOwnerTime = Envir.Time + 5000; monster.Die(); LevelMagic(magic); break; #endregion #region MagicBooster case Spell.MagicBooster: value = (int)data[1]; AddBuff(new Buff { Type = BuffType.MagicBooster, Caster = this, ExpireTime = Envir.Time + 60000, Values = new int[] { value, 6 + magic.Level }, Visible = true }); LevelMagic(magic); break; #endregion #region Purification case Spell.Purification: target = (MapObject)data[1]; if (target == null || !target.IsFriendlyTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; if (Envir.Random.Next(4) > magic.Level || target.PoisonList.Count == 0) return; target.ExplosionInflictedTime = 0; target.ExplosionInflictedStage = 0; for (int i = 0; i < target.Buffs.Count; i++) { if (target.Buffs[i].Type == BuffType.Curse) { target.Buffs.RemoveAt(i); break; } } target.PoisonList.Clear(); target.OperateTime = 0; if (target.ObjectID == ObjectID) Enqueue(new S.RemoveDelayedExplosion { ObjectID = target.ObjectID }); target.Broadcast(new S.RemoveDelayedExplosion { ObjectID = target.ObjectID }); LevelMagic(magic); break; #endregion #region Revelation case Spell.Revelation: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || target.CurrentMap != CurrentMap || target.Node == null) return; if (target.Race != ObjectType.Player && target.Race != ObjectType.Monster) return; if (Envir.Random.Next(4) > magic.Level || Envir.Time < target.RevTime) return; target.RevTime = Envir.Time + value * 1000; target.OperateTime = 0; target.BroadcastHealthChange(); LevelMagic(magic); break; #endregion #region Reincarnation case Spell.Reincarnation: if (ReincarnationReady) { ReincarnationTarget.Enqueue(new S.RequestReincarnation { }); LevelMagic(magic); ReincarnationReady = false; } break; #endregion #region Entrapment case Spell.Entrapment: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null || target.Race != ObjectType.Monster || Functions.MaxDistance(CurrentLocation, target.CurrentLocation) > 7 || target.Level >= Level + 5 + Envir.Random.Next(8)) return; MirDirection pulldirection = (MirDirection)((byte)(Direction - 4) % 8); int pulldistance = 0; if ((byte)pulldirection % 2 > 0) pulldistance = Math.Max(0, Math.Min(Math.Abs(CurrentLocation.X - target.CurrentLocation.X), Math.Abs(CurrentLocation.Y - target.CurrentLocation.Y))); else pulldistance = pulldirection == MirDirection.Up || pulldirection == MirDirection.Down ? Math.Abs(CurrentLocation.Y - target.CurrentLocation.Y) - 2 : Math.Abs(CurrentLocation.X - target.CurrentLocation.X) - 2; int levelgap = target.Race == ObjectType.Player ? Level - target.Level + 4 : Level - target.Level + 9; if (Envir.Random.Next(30) >= ((magic.Level + 1) * 3) + levelgap) return; int duration = target.Race == ObjectType.Player ? (int)Math.Round((magic.Level + 1) * 1.6) : (int)Math.Round((magic.Level + 1) * 0.8); if (duration > 0) target.ApplyPoison(new Poison { PType = PoisonType.Paralysis, Duration = duration, TickSpeed = 1000 }, this); CurrentMap.Broadcast(new S.ObjectEffect { ObjectID = target.ObjectID, Effect = SpellEffect.Entrapment }, target.CurrentLocation); if (target.Pushed(this, pulldirection, pulldistance) > 0) LevelMagic(magic); break; #endregion #region Hallucination case Spell.Hallucination: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null || Functions.MaxDistance(CurrentLocation, target.CurrentLocation) > 7 || Envir.Random.Next(Level + 20 + magic.Level * 5) <= target.Level + 10) return; item = GetAmulet(1); if (item == null) return; ((MonsterObject)target).HallucinationTime = Envir.Time + (Envir.Random.Next(20) + 10) * 1000; target.Target = null; ConsumeItem(item, 1); LevelMagic(magic); break; #endregion #region PetEnhancer case Spell.PetEnhancer: value = (int)data[1]; target = (MonsterObject)data[2]; int dcInc = 2 + target.Level * 2; int acInc = 4 + target.Level; target.AddBuff(new Buff { Type = BuffType.PetEnhancer, Caster = this, ExpireTime = Envir.Time + value * 1000, Values = new int[] { dcInc, acInc }, Visible = true }); LevelMagic(magic); break; #endregion #region ElementalBarrier, ElementalShot case Spell.ElementalBarrier: if (ElementalBarrier) return; if (!HasElemental) { ObtainElement(true);//gather orb through casting LevelMagic(magic); return; } int barrierPower = GetElementalOrbPower(true);//defensive orbpower //destroy orbs ElementsLevel = 0; ObtainElement(false); LevelMagic(magic); // ElementalBarrier = true; ElementalBarrierLv = (byte)((int)magic.Level);//compensate for lower mc then wizard ElementalBarrierTime = Envir.Time + ((int)data[1] + barrierPower) * 1000; CurrentMap.Broadcast(new S.ObjectEffect { ObjectID = ObjectID, Effect = SpellEffect.ElementalBarrierUp }, CurrentLocation); break; case Spell.ElementalShot: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) { //destroy orbs ElementsLevel = 0; ObtainElement(false);//update and send to client return; } if (target.Attacked(this, value, DefenceType.MAC, false) > 0) LevelMagic(magic); DoKnockback(target, magic);//ElementalShot - Knockback //destroy orbs ElementsLevel = 0; ObtainElement(false);//update and send to client break; #endregion #region DelayedExplosion case Spell.DelayedExplosion: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; if (target.Attacked(this, value, DefenceType.MAC, false) > 0) LevelMagic(magic); target.ApplyPoison(new Poison { Duration = (value * 2) + (magic.Level + 1) * 7, Owner = this, PType = PoisonType.DelayedExplosion, TickSpeed = 2000, Value = value }, this); target.OperateTime = 0; LevelMagic(magic); break; #endregion #region BindingShot case Spell.BindingShot: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; if (((MonsterObject)target).ShockTime >= Envir.Time) return;//Already shocked Point place = target.CurrentLocation; MonsterObject centerTarget = null; for (int y = place.Y - 1; y <= place.Y + 1; y++) { if (y < 0) continue; if (y >= CurrentMap.Height) break; for (int x = place.X - 1; x <= place.X + 1; x++) { if (x < 0) continue; if (x >= CurrentMap.Width) break; Cell cell = CurrentMap.GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject targetob = cell.Objects[i]; if (y == place.Y && x == place.X && targetob.Race == ObjectType.Monster) { centerTarget = (MonsterObject)targetob; } switch (targetob.Race) { case ObjectType.Monster: if (targetob == null || !targetob.IsAttackTarget(this) || targetob.Node == null || targetob.Level > this.Level + 2) continue; MonsterObject mobTarget = (MonsterObject)targetob; if (centerTarget == null) centerTarget = mobTarget; mobTarget.ShockTime = Envir.Time + value; mobTarget.Target = null; break; } } } } if (centerTarget == null) return; //only the centertarget holds the effect centerTarget.BindingShotCenter = true; centerTarget.Broadcast(new S.SetBindingShot { ObjectID = centerTarget.ObjectID, Enabled = true, Value = value }); LevelMagic(magic); break; #endregion #region VampireShot, PoisonShot, CrippleShot case Spell.VampireShot: case Spell.PoisonShot: case Spell.CrippleShot: value = (int)data[1]; target = (MapObject)data[2]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; if (target.Attacked(this, value, DefenceType.MAC, false) == 0) return; int buffTime = 5 + (5 * magic.Level); bool hasVampBuff = (Buffs.Where(x => x.Type == BuffType.VampireShot).ToList().Count() > 0); bool hasPoisonBuff = (Buffs.Where(x => x.Type == BuffType.PoisonShot).ToList().Count() > 0); bool doVamp = false, doPoison = false; if (magic.Spell == Spell.VampireShot) { doVamp = true; if (!hasVampBuff && !hasPoisonBuff && (Envir.Random.Next(20) >= 8))//40% chance { AddBuff(new Buff { Type = BuffType.VampireShot, Caster = this, ExpireTime = Envir.Time + (buffTime * 1000), Values = new int[] { value }, Visible = true, ObjectID = this.ObjectID }); BroadcastInfo(); } } if (magic.Spell == Spell.PoisonShot) { doPoison = true; if (!hasPoisonBuff && !hasVampBuff && (Envir.Random.Next(20) >= 8))//40% chance { AddBuff(new Buff { Type = BuffType.PoisonShot, Caster = this, ExpireTime = Envir.Time + (buffTime * 1000), Values = new int[] { value }, Visible = true, ObjectID = this.ObjectID }); BroadcastInfo(); } } if (magic.Spell == Spell.CrippleShot) { if (hasVampBuff || hasPoisonBuff) { place = target.CurrentLocation; for (int y = place.Y - 1; y <= place.Y + 1; y++) { if (y < 0) continue; if (y >= CurrentMap.Height) break; for (int x = place.X - 1; x <= place.X + 1; x++) { if (x < 0) continue; if (x >= CurrentMap.Width) break; Cell cell = CurrentMap.GetCell(x, y); if (!cell.Valid || cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject targetob = cell.Objects[i]; if (targetob.Race != ObjectType.Monster && targetob.Race != ObjectType.Player) continue; if (targetob == null || !targetob.IsAttackTarget(this) || targetob.Node == null) continue; if (targetob.Dead) continue; if (hasVampBuff)//Vampire Effect { //cancel out buff AddBuff(new Buff { Type = BuffType.VampireShot, Caster = this, ExpireTime = Envir.Time + 1000, Values = new int[] { value }, Visible = true, ObjectID = this.ObjectID }); target.Attacked(this, value, DefenceType.MAC, false); if (VampAmount == 0) VampTime = Envir.Time + 1000; VampAmount += (ushort)(value * (magic.Level + 1) * 0.25F); } if (hasPoisonBuff)//Poison Effect { //cancel out buff AddBuff(new Buff { Type = BuffType.PoisonShot, Caster = this, ExpireTime = Envir.Time + 1000, Values = new int[] { value }, Visible = true, ObjectID = this.ObjectID }); targetob.ApplyPoison(new Poison { Duration = (value * 2) + (magic.Level + 1) * 7, Owner = this, PType = PoisonType.Green, TickSpeed = 2000, Value = value / 25 + magic.Level + 1 + Envir.Random.Next(PoisonAttack) }, this); targetob.OperateTime = 0; } } } } } } else { if (doVamp)//Vampire Effect { if (VampAmount == 0) VampTime = Envir.Time + 1000; VampAmount += (ushort)(value * (magic.Level + 1) * 0.25F); } if (doPoison)//Poison Effect { target.ApplyPoison(new Poison { Duration = (value * 2) + (magic.Level + 1) * 7, Owner = this, PType = PoisonType.Green, TickSpeed = 2000, Value = value / 25 + magic.Level + 1 + Envir.Random.Next(PoisonAttack) }, this); target.OperateTime = 0; } } LevelMagic(magic); break; #endregion #region ArcherSummons case Spell.SummonVampire: case Spell.SummonToad: case Spell.SummonSnakes: value = (int)data[1]; location = (Point)data[2]; target = (MapObject)data[3]; int SummonType = 0; switch (magic.Spell) { case Spell.SummonVampire: SummonType = 1; break; case Spell.SummonToad: SummonType = 2; break; case Spell.SummonSnakes: SummonType = 3; break; } if (SummonType == 0) return; for (int i = 0; i < Pets.Count; i++) { monster = Pets[i]; if ((monster.Info.Name != (SummonType == 1 ? Settings.VampireName : (SummonType == 2 ? Settings.ToadName : Settings.SnakeTotemName))) || monster.Dead) continue; if (monster.Node == null) continue; monster.ActionList.Add(new DelayedAction(DelayedType.Recall, Envir.Time + 500, target)); monster.Target = target; return; } if (Pets.Where(x => x.Race == ObjectType.Monster).Count() > 1) return; //left it in for future summon amulets //UserItem item = GetAmulet(5); //if (item == null) return; MonsterInfo info = Envir.GetMonsterInfo((SummonType == 1 ? Settings.VampireName : (SummonType == 2 ? Settings.ToadName : Settings.SnakeTotemName))); if (info == null) return; LevelMagic(magic); //ConsumeItem(item, 5); monster = MonsterObject.GetMonster(info); monster.PetLevel = magic.Level; monster.Master = this; monster.MaxPetLevel = (byte)(1 + magic.Level * 2); monster.Direction = Direction; monster.ActionTime = Envir.Time + 1000; monster.Target = target; if (SummonType == 1) ((Monsters.VampireSpider)monster).AliveTime = Envir.Time + ((magic.Level * 1500) + 15000); if (SummonType == 2) ((Monsters.SpittingToad)monster).AliveTime = Envir.Time + ((magic.Level * 2000) + 25000); if (SummonType == 3) ((Monsters.SnakeTotem)monster).AliveTime = Envir.Time + ((magic.Level * 1500) + 20000); //Pets.Add(monster); DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + 500, this, magic, monster, location); CurrentMap.ActionList.Add(action); break; #endregion } }
public void MagicAttack(MonsterObject _target) { if (_target == null) return; if (!uniqueAI.IgnorePets) MagicAttackDamage += DamageToPets; else FindTarget(); AttackTime = Envir.Time + AttackSpeed + 500; if (MagicAttackDamage == 0) return; switch (uniqueAI.MagicAttackEffect) { case 1: Broadcast(new S.ObjectEffect { ObjectID = _target.ObjectID, Effect = SpellEffect.Entrapment }); break; case 2: Broadcast(new S.ObjectEffect { ObjectID = _target.ObjectID, Effect = SpellEffect.GreatFoxSpirit }); break; default: break; } DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 500, _target, MagicAttackDamage, DefenceType.MAC); ActionList.Add(action); }
public void NapalmShot(MapObject target, UserMagic magic) { if (target == null || !target.IsAttackTarget(this)) return; if ((Info.MentalState != 1) && !CanFly(target.CurrentLocation)) return; int distance = Functions.MaxDistance(CurrentLocation, target.CurrentLocation); int damage = (GetAttackPower(MinMC, MaxMC) + magic.GetPower()); damage = ApplyArcherState(damage); int delay = distance * 50 + 500; //50 MS per Step DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + delay, this, magic, damage, target.CurrentLocation); CurrentMap.ActionList.Add(action); }
public void OneWithNature(MapObject target, UserMagic magic) { int damage = GetAttackPower(MinMC, MaxMC) + magic.GetPower(); DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + 500, this, magic, damage, CurrentLocation); CurrentMap.ActionList.Add(action); }
private void SlashingBurst(UserMagic magic, out bool cast) { cast = true; // damage int damage = GetAttackPower(MaxDC, MaxDC) * magic.GetPower(); // objects = this, magic, damage, currentlocation, direction, attackRange DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + 500, this, magic, damage, CurrentLocation, Direction, 1); CurrentMap.ActionList.Add(action); // telpo location Point location = Functions.PointMove(CurrentLocation, Direction, 2); if (!CurrentMap.ValidPoint(location)) return; Cell cInfo = CurrentMap.GetCell(location); bool blocked = false; if (cInfo.Objects != null) { for (int c = 0; c < cInfo.Objects.Count; c++) { MapObject ob = cInfo.Objects[c]; if (!ob.Blocking) continue; blocked = true; if ((cInfo.Objects == null) || blocked) break; } } // blocked telpo cancel if (blocked) return; Teleport(CurrentMap, location, false); //// move character //CurrentMap.GetCell(CurrentLocation).Remove(this); //RemoveObjects(Direction, 1); //CurrentLocation = location; //CurrentMap.GetCell(CurrentLocation).Add(this); //AddObjects(Direction, 1); //Enqueue(new S.UserAttackMove { Direction = Direction, Location = location }); }
private void CounterAttackCast(UserMagic magic, MapObject target) { if (target == null || magic == null) return; if (CounterAttack == false) return; int criticalDamage = Envir.Random.Next(0, 100) <= Accuracy ? MaxDC * 2 : MinDC * 2; int damage = (MinDC / 5 + 4 * (magic.Level + Level / 20)) * criticalDamage / 20 + MaxDC; MirDirection dir = Functions.ReverseDirection(target.Direction); Direction = dir; if (Functions.InRange(CurrentLocation, target.CurrentLocation, 1) == false) return; if (Envir.Random.Next(10) > magic.Level + 6) return; Enqueue(new S.ObjectMagic { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Spell = Spell.CounterAttack, TargetID = target.ObjectID, Target = target.CurrentLocation, Cast = true, Level = GetMagic(Spell.CounterAttack).Level, SelfBroadcast = true }); DelayedAction action = new DelayedAction(DelayedType.Damage, AttackTime, target, damage, DefenceType.AC, true); ActionList.Add(action); LevelMagic(magic); CounterAttack = false; }
private void PetEnhancer(MapObject target, UserMagic magic, out bool cast) { cast = false; if (target == null || target.Race != ObjectType.Monster || !target.IsFriendlyTarget(this)) return; int duration = GetAttackPower(MinSC, MaxSC) + magic.GetPower(); cast = true; DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + 500, magic, duration, target); ActionList.Add(action); }
private void Entrapment(MapObject target, UserMagic magic) { if (target == null || !target.IsAttackTarget(this)) return; int damage = 0; DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + 500, magic, damage, target); ActionList.Add(action); }
private void Curse(UserMagic magic, Point location, out bool cast) { cast = false; UserItem item = GetAmulet(1); if (item == null) return; cast = true; ConsumeItem(item, 1); if (Envir.Random.Next(10 - ((magic.Level + 1) * 2)) > 2) return; int delay = Functions.MaxDistance(CurrentLocation, location) * 50 + 500; //50 MS per Step DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + delay, this, magic, GetAttackPower(MinSC, MaxSC) + (magic.Level + 1) * 5, location, 1 + ((magic.Level + 1) * 2)); CurrentMap.ActionList.Add(action); }
private void Plague(UserMagic magic, Point location, out bool cast) { cast = false; UserItem item = GetAmulet(1); if (item == null) return; cast = true; int delay = Functions.MaxDistance(CurrentLocation, location) * 50 + 500; //50 MS per Step PoisonType pType = PoisonType.None; UserItem itemp = GetPoison(1, 1); if (itemp != null) pType = PoisonType.Green; else { itemp = GetPoison(1, 2); if (itemp != null) pType = PoisonType.Red; } DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + delay, this, magic, GetAttackPower(MinSC, MaxSC), location, pType); CurrentMap.ActionList.Add(action); ConsumeItem(item, 1); if (itemp != null) ConsumeItem(itemp, 1); }
private void Hallucination(MapObject target, UserMagic magic) { if (target == null || target.Race != ObjectType.Monster || !target.IsAttackTarget(this)) return; int damage = 0; int delay = Functions.MaxDistance(CurrentLocation, target.CurrentLocation) * 50 + 500; //50 MS per Step DelayedAction action = new DelayedAction(DelayedType.Magic, delay, magic, damage, target); ActionList.Add(action); }
public override void Process(DelayedAction action) { throw new NotSupportedException(); }
private void HeavenlySword(UserMagic magic) { int damage = GetAttackPower(MinDC, MaxDC) + magic.GetPower(); DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + 500, this, magic, damage, CurrentLocation, Direction); CurrentMap.ActionList.Add(action); }
public void SpecialArrowShot(MapObject target, UserMagic magic) { if (target == null || !target.IsAttackTarget(this)) return; if ((Info.MentalState != 1) && !CanFly(target.CurrentLocation)) return; int distance = Functions.MaxDistance(CurrentLocation, target.CurrentLocation); int damage = (GetAttackPower(MinMC, MaxMC) + magic.GetPower()); if (magic.Spell != Spell.CrippleShot) damage = (int)(damage * Math.Max(1, (distance * 0.4)));//range boost damage = ApplyArcherState(damage); int delay = distance * 50 + 500; //50 MS per Step DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + delay, magic, damage, target); ActionList.Add(action); }
private void Trap(UserMagic magic, MapObject target, out bool cast) { cast = false; if (target == null || !target.IsAttackTarget(this) || !(target is MonsterObject)) return; if (target.Level >= Level + 2) return; Point location = target.CurrentLocation; LevelMagic(magic); uint duration = 60000; int value = (int)duration; DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + 500, this, magic, value, location); CurrentMap.ActionList.Add(action); cast = true; }
public void ArcherSummon(UserMagic magic, MapObject target, Point location) { if (target != null && target.IsAttackTarget(this)) location = target.CurrentLocation; if (!CanFly(location)) return; uint duration = (uint)((magic.Level * 5 + 10) * 1000); int value = (int)duration; int delay = Functions.MaxDistance(CurrentLocation, location) * 50 + 500; //50 MS per Step DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + delay, magic, value, location, target); ActionList.Add(action); }
private void CrescentSlash(UserMagic magic) { int criticalDamage = Envir.Random.Next(0, 100) <= Accuracy ? MaxDC * 2 : MinDC * 2; //int damage = (MinDC / 5 + 4 * (magic.Level + Level / 20)) * criticalDamage / 20 + MaxDC; int damage = (MinDC / 5 + 4 * (magic.Level + Level / 20)) + criticalDamage / 20 + MaxDC; MirDirection backDir = Functions.ReverseDirection(Direction); MirDirection preBackDir = Functions.PreviousDir(backDir); MirDirection nextBackDir = Functions.NextDir(backDir); for (int i = 0; i < 8; i++) { MirDirection dir = (MirDirection)i; Point hitPoint = Functions.PointMove(CurrentLocation, dir, 1); if (dir != backDir && dir != preBackDir && dir != nextBackDir) { if (!CurrentMap.ValidPoint(hitPoint)) continue; Cell cell = CurrentMap.GetCell(hitPoint); if (cell.Objects == null) continue; for (int j = 0; j < cell.Objects.Count; j++) { MapObject target = cell.Objects[j]; switch (target.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (target.IsAttackTarget(this)) { DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + AttackSpeed, target, damage, DefenceType.AC, true); ActionList.Add(action); } break; } } LevelMagic(magic); } } }
private void Portal(UserMagic magic, Point location, out bool cast) { cast = false; if (!CurrentMap.ValidPoint(location)) return; if (PortalObjectsArray[1] != null && PortalObjectsArray[1].Node != null) { PortalObjectsArray[0].ExpireTime = 0; PortalObjectsArray[0].Process(); } if (!CanFly(location)) return; int duration = 30 + (magic.Level * 30); int value = duration; DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + 500, this, magic, value, location); CurrentMap.ActionList.Add(action); cast = true; }
private void FlashDash(UserMagic magic) { bool success = false; ActionTime = Envir.Time; int travel = 0; bool blocked = false; int jumpDistance = (magic.Level <= 1) ? 0 : 1;//3 max Point location = CurrentLocation; for (int i = 0; i < jumpDistance; i++) { location = Functions.PointMove(location, Direction, 1); if (!CurrentMap.ValidPoint(location)) break; Cell cInfo = CurrentMap.GetCell(location); if (cInfo.Objects != null) { for (int c = 0; c < cInfo.Objects.Count; c++) { MapObject ob = cInfo.Objects[c]; if (!ob.Blocking) continue; blocked = true; if ((cInfo.Objects == null) || blocked) break; } } if (blocked) break; travel++; } jumpDistance = travel; if (jumpDistance > 0) { location = Functions.PointMove(CurrentLocation, Direction, jumpDistance); CurrentMap.GetCell(CurrentLocation).Remove(this); RemoveObjects(Direction, 1); CurrentLocation = location; CurrentMap.GetCell(CurrentLocation).Add(this); AddObjects(Direction, 1); Enqueue(new S.UserDashAttack { Direction = Direction, Location = location }); Broadcast(new S.ObjectDashAttack { ObjectID = ObjectID, Direction = Direction, Location = location, Distance = jumpDistance }); } else { Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation }); } if (travel == 0) location = CurrentLocation; int attackDelay = (AttackSpeed - 120) <= 300 ? 300 : (AttackSpeed - 120); AttackTime = Envir.Time + attackDelay; SpellTime = Envir.Time + 300; location = Functions.PointMove(location, Direction, 1); if (CurrentMap.ValidPoint(location)) { Cell cInfo = CurrentMap.GetCell(location); if (cInfo.Objects != null) { for (int c = 0; c < cInfo.Objects.Count; c++) { MapObject ob = cInfo.Objects[c]; switch (ob.Race) { case ObjectType.Monster: case ObjectType.Player: //Only targets if (ob.IsAttackTarget(this)) { DelayedAction action = new DelayedAction(DelayedType.Damage, AttackTime, ob, GetAttackPower(MinDC, MaxDC), DefenceType.AC, true); ActionList.Add(action); success = true; if ((((ob.Race != ObjectType.Player) || Settings.PvpCanResistPoison) && (Envir.Random.Next(Settings.PoisonAttackWeight) >= ob.PoisonResist)) && (Envir.Random.Next(15) <= magic.Level + 1)) { DelayedAction pa = new DelayedAction(DelayedType.Poison, AttackTime, ob, PoisonType.Stun, SpellEffect.TwinDrakeBlade, magic.Level + 1, 1000); ActionList.Add(pa); } } break; } } } } if (success) //technicaly this makes flashdash lvl when it casts rather then when it hits (it wont lvl if it's not hitting!) LevelMagic(magic); magic.CastTime = Envir.Time; Enqueue(new S.MagicCast { Spell = magic.Spell }); }
public void MagicAttack(PlayerObject _target) { if (_target == null) return; Direction = Functions.DirectionFromPoint(CurrentLocation, _target.CurrentLocation); AttackTime = Envir.Time + AttackSpeed + 500; if (MagicAttackDamage == 0) return; switch (uniqueAI.MagicAttackEffect) { case 1: // needs to be changed Broadcast(new S.ObjectEffect { ObjectID = _target.ObjectID, Effect = SpellEffect.Entrapment }); break; case 2: // FireWorks Broadcast(new S.ObjectEffect { ObjectID = _target.ObjectID, Effect = SpellEffect.GreatFoxSpirit }); break; default: break; } DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 500, _target, MagicAttackDamage, DefenceType.None); ActionList.Add(action); }
private bool DoubleShot(MapObject target, UserMagic magic) { if (target == null || !target.IsAttackTarget(this)) return false; if ((Info.MentalState != 1) && !CanFly(target.CurrentLocation)) return false; int distance = Functions.MaxDistance(CurrentLocation, target.CurrentLocation); int damage = (GetAttackPower(MinMC, MaxMC) + magic.GetPower()); damage = (int)(damage * Math.Max(1, (distance * 0.25)));//range boost damage = ApplyArcherState(damage); int delay = distance * 50 + 500; //50 MS per Step DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + delay, magic, damage, target); ActionList.Add(action); action = new DelayedAction(DelayedType.Magic, Envir.Time + delay + 50, magic, damage, target); ActionList.Add(action); return true; }
public void RangeAttack(MonsterObject _target) { if (_target == null) return; if (!uniqueAI.IgnorePets) RangeAttackDamage += DamageToPets; else FindTarget(); Direction = Functions.DirectionFromPoint(CurrentLocation, _target.CurrentLocation); AttackTime = Envir.Time + AttackSpeed + 500; Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation }); if (RangeAttackDamage == 0) return; switch (uniqueAI.RangeAttackEffect) { case 1: // needs to be changed Broadcast(new S.ObjectEffect { ObjectID = _target.ObjectID, Effect = SpellEffect.Entrapment }); break; case 2: // FireWorks Broadcast(new S.ObjectEffect { ObjectID = _target.ObjectID, Effect = SpellEffect.GreatFoxSpirit }); break; default: break; } DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 500, _target, RangeAttackDamage, DefenceType.AC); ActionList.Add(action); RangeAttackDamage = uniqueAI.RangeAttackDamage; }
private bool DelayedExplosion(MapObject target, UserMagic magic) { if (target == null || !target.IsAttackTarget(this) || !CanFly(target.CurrentLocation)) return false; int power = GetAttackPower(MinMC, MaxMC) + magic.GetPower(); int delay = Functions.MaxDistance(CurrentLocation, target.CurrentLocation) * 50 + 500; //50 MS per Step DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + delay, magic, power, target); ActionList.Add(action); return true; }
public void Process(DelayedAction action) { switch (action.Type) { case DelayedType.Magic: CompleteMagic(action.Params); break; case DelayedType.Spawn: MonsterObject mob = (MonsterObject) action.Params[0]; mob.Spawn(this, (Point) action.Params[1]); if (action.Params.Length > 2) ((MonsterObject) action.Params[2]).SlaveList.Add(mob); break; } }
private void ExplosiveTrap(UserMagic magic, Point location) { int trapCount = 0; for (int i = 0; i <= 3; i++) if (ArcherTrapObjectsArray[i, 0] != null) trapCount++; if (trapCount >= magic.Level + 1) return;//max 4 traps int freeTrapSpot = -1; for (int i = 0; i <= 3; i++) if (ArcherTrapObjectsArray[i, 0] == null) { freeTrapSpot = i; break; } if (freeTrapSpot == -1) return; int damage = GetAttackPower(MinMC, MaxMC) + magic.GetPower(); DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + 500, this, magic, damage, location, freeTrapSpot); CurrentMap.ActionList.Add(action); }
public void BindingShot(UserMagic magic, MapObject target, out bool cast) { cast = false; if (target == null || !target.IsAttackTarget(this) || !(target is MonsterObject)) return; if ((Info.MentalState != 1) && !CanFly(target.CurrentLocation)) return; if (target.Level > Level + 2) return; if (((MonsterObject)target).ShockTime >= Envir.Time) return;//Already shocked uint duration = (uint)((magic.Level * 5 + 10) * 1000); int value = (int)duration; int delay = Functions.MaxDistance(CurrentLocation, target.CurrentLocation) * 50 + 500; //50 MS per Step DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time + delay, magic, value, target); ActionList.Add(action); cast = true; }
private bool ProcessDelayedExplosion(Poison poison) { if (Dead) return false; if (ExplosionInflictedStage == 0) { Broadcast(new S.ObjectEffect { ObjectID = ObjectID, Effect = SpellEffect.DelayedExplosion, EffectType = 0 }); return true; } if (ExplosionInflictedStage == 1) { if (Envir.Time > ExplosionInflictedTime) ExplosionInflictedTime = poison.TickTime + 3000; Broadcast(new S.ObjectEffect { ObjectID = ObjectID, Effect = SpellEffect.DelayedExplosion, EffectType = 1 }); return true; } if (ExplosionInflictedStage == 2) { Broadcast(new S.ObjectEffect { ObjectID = ObjectID, Effect = SpellEffect.DelayedExplosion, EffectType = 2 }); if (poison.Owner != null) { switch (poison.Owner.Race) { case ObjectType.Player: PlayerObject caster = (PlayerObject)poison.Owner; DelayedAction action = new DelayedAction(DelayedType.Magic, Envir.Time, poison.Owner, caster.GetMagic(Spell.DelayedExplosion), poison.Value, this.CurrentLocation); CurrentMap.ActionList.Add(action); //Attacked((PlayerObject)poison.Owner, poison.Value, DefenceType.MAC, false); break; case ObjectType.Monster://this is in place so it could be used by mobs if one day someone chooses to Attacked((MonsterObject)poison.Owner, poison.Value, DefenceType.MAC); break; } LastHitter = poison.Owner; } return false; } return false; }