Spell.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. //-----------------------------------------------------------------------------
  2. // Spell.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using System.IO;
  9. using Microsoft.Xna.Framework;
  10. using Microsoft.Xna.Framework.Content;
  11. using Microsoft.Xna.Framework.Graphics;
  12. namespace RolePlaying.Data
  13. {
  14. public class Spell : ContentObject
  15. #if WINDOWS
  16. , ICloneable
  17. #endif
  18. {
  19. /// <summary>
  20. /// The name of this spell.
  21. /// </summary>
  22. private string name;
  23. /// <summary>
  24. /// The name of this spell.
  25. /// </summary>
  26. public string Name
  27. {
  28. get { return name; }
  29. set { name = value; }
  30. }
  31. /// <summary>
  32. /// The long description of this spell.
  33. /// </summary>
  34. private string description;
  35. /// <summary>
  36. /// The long description of this spell.
  37. /// </summary>
  38. public string Description
  39. {
  40. get { return description; }
  41. set { description = value; }
  42. }
  43. /// <summary>
  44. /// The cost, in magic points, to cast this spell.
  45. /// </summary>
  46. private int magicPointCost;
  47. /// <summary>
  48. /// The cost, in magic points, to cast this spell.
  49. /// </summary>
  50. public int MagicPointCost
  51. {
  52. get { return magicPointCost; }
  53. set { magicPointCost = value; }
  54. }
  55. /// <summary>
  56. /// Builds and returns a string describing the power of this spell.
  57. /// </summary>
  58. public virtual string GetPowerText()
  59. {
  60. return TargetEffectRange.GetModifierString();
  61. }
  62. /// <summary>
  63. /// If true, the statistics change are used as a debuff (subtracted).
  64. /// Otherwise, the statistics change is used as a buff (added).
  65. /// </summary>
  66. private bool isOffensive;
  67. /// <summary>
  68. /// If true, the statistics change are used as a debuff (subtracted).
  69. /// Otherwise, the statistics change is used as a buff (added).
  70. /// </summary>
  71. public bool IsOffensive
  72. {
  73. get { return isOffensive; }
  74. set { isOffensive = value; }
  75. }
  76. /// <summary>
  77. /// The duration of the effect of this spell on its target, in rounds.
  78. /// </summary>
  79. /// <remarks>
  80. /// If the duration is zero, then the effects last for the rest of the battle.
  81. /// </remarks>
  82. private int targetDuration;
  83. /// <summary>
  84. /// The duration of the effect of this spell on its target, in rounds.
  85. /// </summary>
  86. /// <remarks>
  87. /// If the duration is zero, then the effects last for the rest of the battle.
  88. /// </remarks>
  89. public int TargetDuration
  90. {
  91. get { return targetDuration; }
  92. set { targetDuration = value; }
  93. }
  94. /// <summary>
  95. /// The range of statistics effects of this spell on its target.
  96. /// </summary>
  97. /// <remarks>
  98. /// This is a debuff if IsOffensive is true, otherwise it's a buff.
  99. /// </remarks>
  100. private StatisticsRange targetEffectRange = new StatisticsRange();
  101. /// <summary>
  102. /// The range of statistics effects of this spell on its target.
  103. /// </summary>
  104. /// <remarks>
  105. /// This is a debuff if IsOffensive is true, otherwise it's a buff.
  106. /// </remarks>
  107. [ContentSerializerIgnore]
  108. public StatisticsRange TargetEffectRange
  109. {
  110. get { return targetEffectRange; }
  111. }
  112. /// <summary>
  113. /// The initial range of statistics effects of this spell on its target.
  114. /// </summary>
  115. /// <remarks>
  116. /// This is a debuff if IsOffensive is true, otherwise it's a buff.
  117. /// </remarks>
  118. private StatisticsRange initialTargetEffectRange = new StatisticsRange();
  119. /// <summary>
  120. /// The initial range of statistics effects of this spell on its target.
  121. /// </summary>
  122. /// <remarks>
  123. /// This is a debuff if IsOffensive is true, otherwise it's a buff.
  124. /// </remarks>
  125. public StatisticsRange InitialTargetEffectRange
  126. {
  127. get { return initialTargetEffectRange; }
  128. set { initialTargetEffectRange = value; }
  129. }
  130. /// <summary>
  131. /// The number of simultaneous, adjacent targets affected by this spell.
  132. /// </summary>
  133. private int adjacentTargets;
  134. /// <summary>
  135. /// The number of simultaneous, adjacent targets affected by this spell.
  136. /// </summary>
  137. public int AdjacentTargets
  138. {
  139. get { return adjacentTargets; }
  140. set { adjacentTargets = value; }
  141. }
  142. /// <summary>
  143. /// The level of the spell.
  144. /// </summary>
  145. private int level = 1;
  146. /// <summary>
  147. /// The level of the spell.
  148. /// </summary>
  149. [ContentSerializerIgnore]
  150. public int Level
  151. {
  152. get { return level; }
  153. set
  154. {
  155. level = value;
  156. targetEffectRange = initialTargetEffectRange;
  157. for (int i = 1; i < level; i++)
  158. {
  159. targetEffectRange += LevelingProgression;
  160. }
  161. }
  162. }
  163. /// <summary>
  164. /// Defines how the spell improves as it levels up.
  165. /// </summary>
  166. private StatisticsValue levelingProgression = new StatisticsValue();
  167. /// <summary>
  168. /// Defines how the spell improves as it levels up.
  169. /// </summary>
  170. public StatisticsValue LevelingProgression
  171. {
  172. get { return levelingProgression; }
  173. set { levelingProgression = value; }
  174. }
  175. /// <summary>
  176. /// The name of the sound effect cue played when the spell is cast.
  177. /// </summary>
  178. private string creatingCueName;
  179. /// <summary>
  180. /// The name of the sound effect cue played when the spell is cast.
  181. /// </summary>
  182. public string CreatingCueName
  183. {
  184. get { return creatingCueName; }
  185. set { creatingCueName = value; }
  186. }
  187. /// <summary>
  188. /// The name of the sound effect cue played when the spell effect is traveling.
  189. /// </summary>
  190. private string travelingCueName;
  191. /// <summary>
  192. /// The name of the sound effect cue played when the spell effect is traveling.
  193. /// </summary>
  194. public string TravelingCueName
  195. {
  196. get { return travelingCueName; }
  197. set { travelingCueName = value; }
  198. }
  199. /// <summary>
  200. /// The name of the sound effect cue played when the spell affects its target.
  201. /// </summary>
  202. private string impactCueName;
  203. /// <summary>
  204. /// The name of the sound effect cue played when the spell affects its target.
  205. /// </summary>
  206. public string ImpactCueName
  207. {
  208. get { return impactCueName; }
  209. set { impactCueName = value; }
  210. }
  211. /// <summary>
  212. /// The name of the sound effect cue played when the spell effect is blocked.
  213. /// </summary>
  214. private string blockCueName;
  215. /// <summary>
  216. /// The name of the sound effect cue played when the spell effect is blocked.
  217. /// </summary>
  218. public string BlockCueName
  219. {
  220. get { return blockCueName; }
  221. set { blockCueName = value; }
  222. }
  223. /// <summary>
  224. /// The content path and name of the icon for this spell.
  225. /// </summary>
  226. private string iconTextureName;
  227. /// <summary>
  228. /// The content path and name of the icon for this spell.
  229. /// </summary>
  230. public string IconTextureName
  231. {
  232. get { return iconTextureName; }
  233. set { iconTextureName = value; }
  234. }
  235. /// <summary>
  236. /// The icon texture for this spell.
  237. /// </summary>
  238. private Texture2D iconTexture;
  239. /// <summary>
  240. /// The icon texture for this spell.
  241. /// </summary>
  242. [ContentSerializerIgnore]
  243. public Texture2D IconTexture
  244. {
  245. get { return iconTexture; }
  246. }
  247. /// <summary>
  248. /// The animating sprite used when this spell is in action.
  249. /// </summary>
  250. private AnimatingSprite spellSprite;
  251. /// <summary>
  252. /// The animating sprite used when this spell is in action.
  253. /// </summary>
  254. public AnimatingSprite SpellSprite
  255. {
  256. get { return spellSprite; }
  257. set { spellSprite = value; }
  258. }
  259. /// <summary>
  260. /// The overlay sprite for this spell.
  261. /// </summary>
  262. private AnimatingSprite overlay;
  263. /// <summary>
  264. /// The overlay sprite for this spell.
  265. /// </summary>
  266. public AnimatingSprite Overlay
  267. {
  268. get { return overlay; }
  269. set { overlay = value; }
  270. }
  271. /// <summary>
  272. /// Read an Spell object from the content pipeline.
  273. /// </summary>
  274. public class SpellReader : ContentTypeReader<Spell>
  275. {
  276. /// <summary>
  277. /// Read an Spell object from the content pipeline.
  278. /// </summary>
  279. protected override Spell Read(ContentReader input, Spell existingInstance)
  280. {
  281. Spell spell = existingInstance;
  282. if (spell == null)
  283. {
  284. spell = new Spell();
  285. }
  286. spell.AssetName = input.AssetName;
  287. spell.Name = input.ReadString();
  288. spell.Description = input.ReadString();
  289. spell.MagicPointCost = input.ReadInt32();
  290. spell.IconTextureName = input.ReadString();
  291. spell.iconTexture = input.ContentManager.Load<Texture2D>(
  292. Path.Combine("Textures", "Spells", spell.IconTextureName));
  293. spell.IsOffensive = input.ReadBoolean();
  294. spell.TargetDuration = input.ReadInt32();
  295. spell.targetEffectRange = spell.InitialTargetEffectRange =
  296. input.ReadObject<StatisticsRange>();
  297. spell.AdjacentTargets = input.ReadInt32();
  298. spell.LevelingProgression = input.ReadObject<StatisticsValue>();
  299. spell.CreatingCueName = input.ReadString();
  300. spell.TravelingCueName = input.ReadString();
  301. spell.ImpactCueName = input.ReadString();
  302. spell.BlockCueName = input.ReadString();
  303. spell.SpellSprite = input.ReadObject<AnimatingSprite>();
  304. spell.SpellSprite.SourceOffset = new Vector2(
  305. spell.SpellSprite.FrameDimensions.X / 2,
  306. spell.SpellSprite.FrameDimensions.Y);
  307. spell.Overlay = input.ReadObject<AnimatingSprite>();
  308. spell.Overlay.SourceOffset = new Vector2(
  309. spell.Overlay.FrameDimensions.X / 2,
  310. spell.Overlay.FrameDimensions.Y);
  311. spell.Level = 1;
  312. return spell;
  313. }
  314. }
  315. public object Clone()
  316. {
  317. Spell spell = new Spell();
  318. spell.adjacentTargets = adjacentTargets;
  319. spell.AssetName = AssetName;
  320. spell.blockCueName = blockCueName;
  321. spell.creatingCueName = creatingCueName;
  322. spell.description = description;
  323. spell.iconTexture = iconTexture;
  324. spell.iconTextureName = iconTextureName;
  325. spell.impactCueName = impactCueName;
  326. spell.initialTargetEffectRange = initialTargetEffectRange;
  327. spell.isOffensive = isOffensive;
  328. spell.levelingProgression = levelingProgression;
  329. spell.magicPointCost = magicPointCost;
  330. spell.name = name;
  331. spell.overlay = overlay.Clone() as AnimatingSprite;
  332. spell.spellSprite = spellSprite.Clone() as AnimatingSprite;
  333. spell.targetDuration = targetDuration;
  334. spell.travelingCueName = travelingCueName;
  335. spell.Level = Level;
  336. return spell;
  337. }
  338. internal static Spell Load(string spellAssetName, ContentManager contentManager)
  339. {
  340. var asset = XmlHelper.GetAssetElementFromXML(spellAssetName);
  341. var spell = new Spell()
  342. {
  343. AssetName = spellAssetName,
  344. Name = asset.Element("Name")?.Value ?? "Unknown Spell",
  345. Description = asset.Element("Description")?.Value ?? "No Description",
  346. MagicPointCost = int.Parse(asset.Element("MagicPointCost")?.Value ?? "0"),
  347. IconTextureName = asset.Element("IconTextureName")?.Value ?? "UnknownIcon",
  348. iconTexture = contentManager.Load<Texture2D>(Path.Combine("Textures", "Spells", asset.Element("IconTextureName").Value)),
  349. IsOffensive = bool.Parse(asset.Element("IsOffensive")?.Value ?? "false"),
  350. TargetDuration = int.Parse(asset.Element("TargetDuration")?.Value ?? "0"),
  351. /*targetEffectRange = StatisticsRange.FromString(
  352. asset.Element("TargetEffectRange")?.Value ?? "0");
  353. initialTargetEffectRange = targetEffectRange;*/
  354. AdjacentTargets = int.Parse(asset.Element("AdjacentTargets")?.Value ?? "0"),
  355. /*LevelingProgression = StatisticsValue.FromString(
  356. asset.Element("LevelingProgression")?.Value ?? "0");*/
  357. CreatingCueName = asset.Element("CreatingCueName")?.Value ?? "UnknownCue",
  358. TravelingCueName = asset.Element("TravelingCueName")?.Value ?? "UnknownCue",
  359. ImpactCueName = asset.Element("ImpactCueName")?.Value ?? "UnknownCue",
  360. BlockCueName = asset.Element("BlockCueName")?.Value ?? "UnknownCue",
  361. SpellSprite = asset.Element("SpellSprite") != null ? AnimatingSprite.Load(asset.Element("SpellSprite"), contentManager) : null,
  362. Overlay = asset.Element("Overlay") != null ? AnimatingSprite.Load(asset.Element("Overlay"), contentManager) : null,
  363. Level = int.Parse(asset.Element("Level")?.Value ?? "1")
  364. };
  365. return spell;
  366. }
  367. }
  368. }