/Server/WorldServer/Spells/SpellBook.cs

https://bitbucket.org/arcanosteam/arcanos · C# · 357 lines · 328 code · 28 blank · 1 comment · 67 complexity · 38dee13c21ab07670a2404f2c3c5ccf9 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using Arcanos.Server.WorldServer.Data;
  4. using Arcanos.Shared;
  5. using Arcanos.Shared.Objects;
  6. using Arcanos.Shared.Spells;
  7. using Arcanos.Shared.Timing;
  8. using Microsoft.Xna.Framework;
  9. namespace Arcanos.Server.WorldServer.Spells
  10. {
  11. public class SpellBook : SpellBookBase
  12. {
  13. public SpellBook(CreatureBase owner) : base(owner) { }
  14. public override void Update()
  15. {
  16. int count = AppliedAuras.Count;
  17. for (int i = 0; i < count; ++i)
  18. {
  19. Aura aura = AppliedAuras[i] as Aura;
  20. if (aura.ToBeRemoved)
  21. {
  22. AppliedAuras.RemoveAt(i--);
  23. --count;
  24. continue;
  25. }
  26. aura.Update();
  27. if (aura.ToBeRemoved)
  28. {
  29. AppliedAuras.RemoveAt(i--);
  30. --count;
  31. RemoveAura(aura);
  32. }
  33. }
  34. if (IsCasting)
  35. {
  36. CastingTime += Time.PerSecond;
  37. if (CastingTime >= CastingSpell.CastingTime)
  38. {
  39. CastSpellResult result;
  40. if (CastingTarget == null)
  41. result = FinishCast(CastingSpell, CastingGroundTarget, CastingFlags | CastSpellFlags.IgnoreAlreadyCasting);
  42. else
  43. result = FinishCast(CastingSpell, CastingTarget, CastingFlags | CastSpellFlags.IgnoreAlreadyCasting);
  44. if (result == CastSpellResult.Ok)
  45. StopCasting();
  46. else
  47. FailCasting(result);
  48. }
  49. }
  50. if (GlobalCooldown > 0)
  51. {
  52. GlobalCooldown -= Time.PerSecond;
  53. if (GlobalCooldown < 0)
  54. GlobalCooldown = 0;
  55. }
  56. foreach (KeyValuePair<int, CooldownInstance> pair in Cooldowns)
  57. if (pair.Value.Left > 0)
  58. {
  59. pair.Value.Left -= Time.PerSecond;
  60. if (pair.Value.Left < 0)
  61. pair.Value.Left = 0;
  62. }
  63. }
  64. public override CastSpellResult CastSpell(SpellTemplateBase spell, CreatureBase target, CastSpellFlags flags)
  65. {
  66. if (spell.HasFlag(SpellFlags.AutoTargetSelf))
  67. target = Owner;
  68. CastSpellResult result;
  69. if ((flags & CastSpellFlags.IgnoreCastingTime) == 0 && !spell.IsInstantCast())
  70. result = StartCasting(spell, target, flags);
  71. else
  72. result = FinishCast(spell, target, flags);
  73. if (result != CastSpellResult.Ok)
  74. Owner.SpellCastingFailed(spell, target, result);
  75. return result;
  76. }
  77. public override CastSpellResult CastSpell(SpellTemplateBase spell, Vector3 target, CastSpellFlags flags)
  78. {
  79. if (spell.HasFlag(SpellFlags.AutoTargetSelf))
  80. target = Owner.Position;
  81. CastSpellResult result;
  82. if ((flags & CastSpellFlags.IgnoreCastingTime) == 0 && !spell.IsInstantCast())
  83. result = StartCasting(spell, target, flags);
  84. else
  85. result = FinishCast(spell, target, flags);
  86. if (result != CastSpellResult.Ok)
  87. Owner.SpellCastingFailed(spell, target, result);
  88. return result;
  89. }
  90. public override CastSpellResult CanCastSpell(SpellTemplateBase spell, CreatureBase target, CastSpellFlags flags)
  91. {
  92. if (spell.HasFlag(SpellFlags.AutoTargetSelf))
  93. target = Owner;
  94. CastSpellResult genericCheckResult = CanCastSpell(spell, flags);
  95. if (genericCheckResult != CastSpellResult.Ok)
  96. return genericCheckResult;
  97. if ((flags & CastSpellFlags.IgnoreTargetCheck) == 0)
  98. {
  99. CastSpellResult targetCheckResult = spell.CanBeCastOn(Owner, target);
  100. if (targetCheckResult != CastSpellResult.Ok)
  101. return targetCheckResult;
  102. }
  103. return CastSpellResult.Ok;
  104. }
  105. public override CastSpellResult CanCastSpell(SpellTemplateBase spell, Vector3 target, CastSpellFlags flags)
  106. {
  107. if (spell.HasFlag(SpellFlags.AutoTargetSelf))
  108. target = Owner.Position;
  109. CastSpellResult genericCheckResult = CanCastSpell(spell, flags);
  110. if (genericCheckResult != CastSpellResult.Ok)
  111. return genericCheckResult;
  112. if ((flags & CastSpellFlags.IgnoreTargetCheck) == 0)
  113. {
  114. CastSpellResult targetCheckResult = spell.CanBeCastAt(Owner, target);
  115. if (targetCheckResult != CastSpellResult.Ok)
  116. return targetCheckResult;
  117. }
  118. return CastSpellResult.Ok;
  119. }
  120. public override void Interrupt(InterruptMask interrupt)
  121. {
  122. if (IsCasting)
  123. InterruptCasting(interrupt);
  124. InterruptAuras(interrupt);
  125. }
  126. public override void InterruptCasting(InterruptMask interrupt)
  127. {
  128. if (!IsCasting)
  129. return;
  130. if (!CastingSpell.IsCastingInterruptedBy(interrupt))
  131. return;
  132. FailCasting(CastSpellResult.Interrupted);
  133. }
  134. public override void InterruptAuras(InterruptMask interrupt)
  135. {
  136. foreach (AuraBase aura in AppliedAuras)
  137. if (aura.Spell.IsAuraInterruptedBy(interrupt))
  138. RemoveAura(aura);
  139. }
  140. public override CastSpellResult FinishCast(SpellTemplateBase spell, CreatureBase target, CastSpellFlags flags)
  141. {
  142. if (spell.HasFlag(SpellFlags.AutoTargetSelf))
  143. target = Owner;
  144. CastSpellResult result = CanCastSpell(spell, target, flags);
  145. if (result != CastSpellResult.Ok)
  146. return result;
  147. Owner.SpellCasted(spell, target);
  148. spell.Create(Owner, target);
  149. PutOnCooldown(spell);
  150. TakeRequirements(spell);
  151. return CastSpellResult.Ok;
  152. }
  153. public override CastSpellResult FinishCast(SpellTemplateBase spell, Vector3 target, CastSpellFlags flags)
  154. {
  155. if (spell.HasFlag(SpellFlags.AutoTargetSelf))
  156. target = Owner.Position;
  157. CastSpellResult result = CanCastSpell(spell, target, flags);
  158. if (result != CastSpellResult.Ok)
  159. return result;
  160. Owner.SpellCasted(spell, target);
  161. spell.Create(Owner, target);
  162. PutOnCooldown(spell);
  163. TakeRequirements(spell);
  164. return CastSpellResult.Ok;
  165. }
  166. public override CastSpellResult StartCasting(SpellTemplateBase spell, CreatureBase target, CastSpellFlags flags)
  167. {
  168. if (spell.HasFlag(SpellFlags.AutoTargetSelf))
  169. target = Owner;
  170. CastSpellResult result = CanCastSpell(spell, target, flags);
  171. if (result != CastSpellResult.Ok)
  172. return result;
  173. CastingSpell = spell;
  174. CastingTarget = target;
  175. CastingGroundTarget = Vector3.Zero;
  176. CastingTime = 0;
  177. CastingFlags = flags;
  178. Owner.SpellCastingStarted(spell, target);
  179. return CastSpellResult.Ok;
  180. }
  181. public override CastSpellResult StartCasting(SpellTemplateBase spell, Vector3 target, CastSpellFlags flags)
  182. {
  183. if (spell.HasFlag(SpellFlags.AutoTargetSelf))
  184. target = Owner.Position;
  185. CastSpellResult result = CanCastSpell(spell, target, flags);
  186. if (result != CastSpellResult.Ok)
  187. return result;
  188. CastingSpell = spell;
  189. CastingTarget = null;
  190. CastingGroundTarget = target;
  191. CastingTime = 0;
  192. CastingFlags = flags;
  193. Owner.SpellCastingStarted(spell, target);
  194. return CastSpellResult.Ok;
  195. }
  196. public override void FailCasting(CastSpellResult result)
  197. {
  198. if (CastingTarget == null)
  199. Owner.SpellCastingFailed(CastingSpell, CastingGroundTarget, result);
  200. else
  201. Owner.SpellCastingFailed(CastingSpell, CastingTarget, result);
  202. StopCasting();
  203. }
  204. public override void StopCasting()
  205. {
  206. CastingSpell = null;
  207. CastingTarget = null;
  208. CastingGroundTarget = Vector3.Zero;
  209. CastingTime = 0;
  210. CastingFlags = 0;
  211. }
  212. public override void AddSpell(SpellTemplateBase spell)
  213. {
  214. base.AddSpell(spell);
  215. RebuildSpellCache();
  216. }
  217. public override void RemoveSpell(SpellTemplateBase spell)
  218. {
  219. base.RemoveSpell(spell);
  220. RebuildSpellCache();
  221. }
  222. public override void RemoveAllSpells()
  223. {
  224. base.RemoveAllSpells();
  225. RebuildSpellCache();
  226. }
  227. public void AddCooldown(int categoryID, float left, float total)
  228. {
  229. Cooldowns.Add(categoryID, new CooldownInstance(total) { Left = left });
  230. }
  231. public override void ApplyAura(ulong casterGUID, SpellTemplateBase spell, int effectID)
  232. {
  233. Aura aura = new Aura(Owner, casterGUID, spell, effectID);
  234. AppliedAuras.Add(aura);
  235. AuraHandlers.Handle(aura, effectID, true);
  236. Owner.AuraApplied(aura);
  237. }
  238. public override void ApplyAura(ulong casterGUID, SpellTemplateBase spell, int effectID, float duration)
  239. {
  240. Aura aura = new Aura(Owner, casterGUID, spell, effectID);
  241. aura.DurationTotal = aura.DurationLeft = duration;
  242. AppliedAuras.Add(aura);
  243. AuraHandlers.Handle(aura, effectID, true);
  244. Owner.AuraApplied(aura);
  245. }
  246. public void ApplyAura(Aura aura)
  247. {
  248. aura.Owner = Owner;
  249. AppliedAuras.Add(aura);
  250. AuraHandlers.Handle(aura, aura.EffectID, true);
  251. }
  252. public override void RemoveAura(AuraBase aura)
  253. {
  254. aura.ToBeRemoved = true;
  255. AuraHandlers.Handle(aura as Aura, aura.EffectID, false);
  256. Owner.AuraRemoved(aura);
  257. }
  258. public void TakeRequirements(SpellTemplateBase spell)
  259. {
  260. if (spell.RequiredPowerAmount != 0)
  261. Owner.ModityPower(spell.RequiredPowerType, -spell.RequiredPowerAmount);
  262. // TODO: Reagents
  263. }
  264. public void ProcessProc(AuraType proc, CreatureBase target)
  265. {
  266. switch (proc)
  267. {
  268. case AuraType.MeleeHitProc:
  269. case AuraType.MeleeMissProc:
  270. break;
  271. default:
  272. throw new Exception();
  273. }
  274. foreach (Aura aura in GetAuras(proc))
  275. {
  276. if (R.Float() <= aura.Effect.FloatValue1)
  277. {
  278. SpellTemplate procSpell = DatabaseManager.Spells[aura.Effect.IntValue1];
  279. CastSpell(procSpell, target, CastSpellFlags.ProcSpellIgnores);
  280. }
  281. }
  282. }
  283. private readonly List<SpellTemplate> offensiveSpells = new List<SpellTemplate>();
  284. private readonly List<SpellTemplate> defensiveSpells = new List<SpellTemplate>();
  285. private readonly List<SpellTemplate> healingSpells = new List<SpellTemplate>();
  286. private void RebuildSpellCache()
  287. {
  288. foreach (SpellTemplate spell in Spells)
  289. {
  290. if (spell.HasOffensiveEffects())
  291. offensiveSpells.Add(spell);
  292. if (spell.HasDefensiveEffects())
  293. defensiveSpells.Add(spell);
  294. if (spell.HasHealingEffects())
  295. healingSpells.Add(spell);
  296. }
  297. }
  298. public IEnumerable<SpellTemplate> FindOffensiveSpells()
  299. {
  300. return offensiveSpells;
  301. }
  302. public IEnumerable<SpellTemplate> FindDefensiveSpells()
  303. {
  304. return defensiveSpells;
  305. }
  306. public IEnumerable<SpellTemplate> FindHealingSpells()
  307. {
  308. return healingSpells;
  309. }
  310. public IEnumerable<SpellTemplate> FindAvailableOffensiveSpells()
  311. {
  312. foreach (SpellTemplate spell in offensiveSpells)
  313. if (!IsOnCooldown(spell))
  314. yield return spell;
  315. }
  316. public IEnumerable<SpellTemplate> FindAvailableDefensiveSpells()
  317. {
  318. foreach (SpellTemplate spell in defensiveSpells)
  319. if (!IsOnCooldown(spell))
  320. yield return spell;
  321. }
  322. public IEnumerable<SpellTemplate> FindAvailableHealingSpells()
  323. {
  324. foreach (SpellTemplate spell in healingSpells)
  325. if (!IsOnCooldown(spell))
  326. yield return spell;
  327. }
  328. }
  329. }