Files

276 lines
8.2 KiB
C#

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<MapObject> Targets = new List<MapObject>();
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<UserMagic> { 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()
{
}
}
}