using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using Library; using Library.Network; using Server.DBModels; using Server.Envir; using S = Library.Network.ServerPackets; namespace Zircon.Server.Models { public sealed class SpellObject : MapObject { public override ObjectType Race {get{return ObjectType.Spell;}} public override bool Blocking { get { return false; } } public Point DisplayLocation; public SpellEffect Effect; public int TickCount; public TimeSpan TickFrequency; public DateTime TickTime; public MapObject Owner; public UserMagic Magic; public int Power; public List Targets = new List(); public override bool CanBeSeenBy(PlayerObject ob) { return Visible && base.CanBeSeenBy(ob); } public override void Process() { base.Process(); if (Owner != null && (Owner.Node == null || Owner.Dead)) { Despawn(); return; } if (SEnvir.Now < TickTime) return; if (TickCount-- <= 0) { switch (Effect) { case SpellEffect.MonsterDeathCloud: MonsterObject monster = Owner as MonsterObject; if (monster == null) break; for (int i = CurrentCell.Objects.Count - 1; i >= 0; i--) { if (i >= CurrentCell.Objects.Count) continue; MapObject ob = CurrentCell.Objects[i]; if (!monster.CanAttackTarget(ob)) continue; monster.Attack(ob, 4000, Element.None); monster.Attack(ob, 4000, Element.None); } break; case SpellEffect.QierBian: if (this.Owner is MonsterObject owner3) { for (int index = this.CurrentCell.Objects.Count - 1; index >= 0; --index) { if (index < this.CurrentCell.Objects.Count) { MapObject ob = this.CurrentCell.Objects[index]; if (owner3.CanAttackTarget(ob)) { owner3.Attack(ob, 8000, Element.None); owner3.Attack(ob, 8000, Element.None); } } } } break; } Despawn(); return; } TickTime = SEnvir.Now + TickFrequency; switch (Effect) { case SpellEffect.TrapOctagon: for (int i = Targets.Count - 1; i >= 0; i--) { MapObject ob = Targets[i]; if (ob.Node != null && ob.ShockTime != DateTime.MinValue) continue; Targets.Remove(ob); } if (Targets.Count == 0) Despawn(); break; default: if (CurrentCell == null) { SEnvir.Log("[ERROR] {Effect} CurrentCell 空值."); return; } if (CurrentCell.Objects == null) { SEnvir.Log("[ERROR] {Effect} CurrentCell.Objects 空值."); return; } for (int i = CurrentCell.Objects.Count - 1; i >= 0; i--) { if (i >= CurrentCell.Objects.Count) continue; if (CurrentCell.Objects[i] == this) continue; ProcessSpell(CurrentCell.Objects[i]); if (CurrentCell == null) { SEnvir.Log("[ERROR] {Effect} CurrentCell 空循环."); return; } if (CurrentCell.Objects == null) { SEnvir.Log("[ERROR] {Effect} CurrentCell.Objects 空循环."); return; } } break; } } public void ProcessSpell(MapObject ob) { switch (Effect) { case SpellEffect.PoisonousCloud: if (!Owner.CanHelpTarget(ob)) return; BuffInfo buff = ob.Buffs.FirstOrDefault(x=> x.Type == BuffType.PoisonousCloud); TimeSpan remaining = TickTime - SEnvir.Now; if (buff != null) if (buff.RemainingTime > remaining) return; Library.Stats tmp = new Stats(); tmp.Values.Add(Stat.Agility, Power); ob.BuffAdd(BuffType.PoisonousCloud, remaining, tmp, false, false, TimeSpan.Zero); break; case SpellEffect.FireWall: case SpellEffect.Tempest: PlayerObject player = Owner as PlayerObject; if (player == null || !player.CanAttackTarget(ob)) return; int damage = player.MagicAttack(new List { Magic }, ob, true); if (damage > 0 && ob.Race == ObjectType.Player) { foreach (SpellObject spell in player.SpellList) { if (spell.Effect != Effect) continue; spell.TickCount--; } } break; case SpellEffect.MonsterFireWall: MonsterObject monster = Owner as MonsterObject; if (monster == null || !monster.CanAttackTarget(ob)) return; monster.Attack(ob, monster.GetDC(), Element.Fire); break; } } protected override void OnSpawned() { base.OnSpawned(); if (Owner != null ) Owner.SpellList.Add(this); AddAllObjects(); Activate(); } public override void OnDespawned() { base.OnDespawned(); Owner.SpellList.Remove(this); } public override void OnSafeDespawn() { base.OnSafeDespawn(); Owner.SpellList.Remove(this); } public override void CleanUp() { base.CleanUp(); Owner = null; Magic = null; Targets.Clear(); } public override Packet GetInfoPacket(PlayerObject ob) { return new S.ObjectSpell { ObjectID = ObjectID, Location = DisplayLocation, Effect = Effect, Direction = Direction, Power = Power, }; } public override Packet GetDataPacket(PlayerObject ob) { return null; } public override bool CanDataBeSeenBy(PlayerObject ob) { return false; } public override void Activate() { if (Activated) return; if (Effect == SpellEffect.SafeZone) return; Activated = true; SEnvir.ActiveObjects.Add(this); } public override void DeActivate() { return; } public override void ProcessHPMP() { } public override void ProcessNameColour() { } public override void ProcessBuff() { } public override void ProcessPoison() { } } }