afxRPGMagicSpell.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  2. // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  3. // Copyright (C) 2015 Faust Logic, Inc.
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. //
  23. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  24. #include "afx/arcaneFX.h"
  25. #include "afxRPGMagicSpell.h"
  26. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  27. // afxRPGMagicSpellData
  28. IMPLEMENT_CO_DATABLOCK_V1(afxRPGMagicSpellData);
  29. ConsoleDocClass( afxRPGMagicSpellData,
  30. "@brief A datablock for defining RPG aspects of a spell.\n\n"
  31. "@ingroup afxMisc\n"
  32. "@ingroup AFX\n"
  33. "@ingroup Datablocks\n"
  34. );
  35. afxRPGMagicSpellData::afxRPGMagicSpellData()
  36. {
  37. // spell parameters
  38. spell_name = ST_NULLSTRING;
  39. spell_desc = ST_NULLSTRING;
  40. spell_target = TARGET_NOTHING;
  41. spell_range = 0.0f;
  42. mana_cost = 0;
  43. n_reagents = 0;
  44. for (S32 i = 0; i < MAX_REAGENTS_PER_SPELL; i++)
  45. {
  46. reagent_cost[i] = 1;
  47. reagent_name[i] = ST_NULLSTRING;
  48. }
  49. // spell phase timing
  50. casting_dur = 0.0f;
  51. // interface elements
  52. icon_name = ST_NULLSTRING;
  53. source_pack = ST_NULLSTRING;
  54. is_placeholder = false;
  55. free_target_style = 0;
  56. target_optional = false;
  57. }
  58. ImplementEnumType( afxRPGMagicSpell_TargetType, "Possible RPG spell target types.\n" "@ingroup afxRPGMagicSpell\n\n" )
  59. { afxRPGMagicSpellData::TARGET_NOTHING, "nothing", "..." },
  60. { afxRPGMagicSpellData::TARGET_SELF, "self", "..." },
  61. { afxRPGMagicSpellData::TARGET_FRIEND, "friend", "..." },
  62. { afxRPGMagicSpellData::TARGET_ENEMY, "enemy", "..." },
  63. { afxRPGMagicSpellData::TARGET_CORPSE, "corpse", "..." },
  64. { afxRPGMagicSpellData::TARGET_FREE, "free", "..." },
  65. EndImplementEnumType;
  66. #define myOffset(field) Offset(field, afxRPGMagicSpellData)
  67. void afxRPGMagicSpellData::initPersistFields()
  68. {
  69. // spell parameters
  70. addField("spellName", TypeString, myOffset(spell_name),
  71. "...");
  72. addField("desc", TypeString, myOffset(spell_desc),
  73. "...");
  74. addField("target", TYPEID< afxRPGMagicSpellData::TargetType >(), myOffset(spell_target),
  75. "...");
  76. addField("range", TypeF32, myOffset(spell_range),
  77. "...");
  78. addField("manaCost", TypeS32, myOffset(mana_cost),
  79. "...");
  80. addField("reagentCost", TypeS8, myOffset(reagent_cost), MAX_REAGENTS_PER_SPELL,
  81. "...");
  82. addField("reagentName", TypeString, myOffset(reagent_name), MAX_REAGENTS_PER_SPELL,
  83. "...");
  84. // spell phase timing
  85. addField("castingDur", TypeF32, myOffset(casting_dur));
  86. // interface elements
  87. addField("iconBitmap", TypeFilename, myOffset(icon_name));
  88. addField("sourcePack", TypeString, myOffset(source_pack));
  89. addField("isPlaceholder", TypeBool, myOffset(is_placeholder));
  90. addField("freeTargetStyle", TypeS8, myOffset(free_target_style));
  91. addField("targetOptional", TypeBool, myOffset(target_optional));
  92. Parent::initPersistFields();
  93. }
  94. bool afxRPGMagicSpellData::onAdd()
  95. {
  96. if (Parent::onAdd() == false)
  97. return false;
  98. n_reagents = 0;
  99. for (S32 i = 0; i < MAX_REAGENTS_PER_SPELL && reagent_name[i] != ST_NULLSTRING; i++)
  100. n_reagents++;
  101. return true;
  102. }
  103. void afxRPGMagicSpellData::packData(BitStream* stream)
  104. {
  105. Parent::packData(stream);
  106. stream->write(spell_target);
  107. stream->write(spell_range);
  108. stream->write(mana_cost);
  109. stream->write(n_reagents);
  110. for (S32 i = 0; i < n_reagents; i++)
  111. {
  112. stream->write(reagent_cost[i]);
  113. stream->writeString(reagent_name[i]);
  114. }
  115. stream->write(casting_dur);
  116. stream->writeString(spell_name);
  117. stream->writeLongString(511, spell_desc);
  118. stream->writeString(icon_name);
  119. stream->writeString(source_pack);
  120. stream->writeFlag(is_placeholder);
  121. stream->writeFlag(target_optional);
  122. stream->write(free_target_style);
  123. }
  124. void afxRPGMagicSpellData::unpackData(BitStream* stream)
  125. {
  126. Parent::unpackData(stream);
  127. stream->read(&spell_target);
  128. stream->read(&spell_range);
  129. stream->read(&mana_cost);
  130. stream->read(&n_reagents);
  131. for (S32 i = 0; i < n_reagents; i++)
  132. {
  133. stream->read(&reagent_cost[i]);
  134. reagent_name[i] = stream->readSTString();
  135. }
  136. stream->read(&casting_dur);
  137. spell_name = stream->readSTString();
  138. {
  139. char value[512];
  140. stream->readLongString(511, value);
  141. spell_desc = StringTable->insert(value);
  142. }
  143. icon_name = stream->readSTString();
  144. source_pack = stream->readSTString();
  145. is_placeholder = stream->readFlag();
  146. target_optional = stream->readFlag();
  147. stream->read(&free_target_style);
  148. }
  149. #define NAME_FMT "<just:left><font:Arial:20><color:FFD200>"
  150. #define TARGET_FMT "<just:right><font:Arial:20><color:ACACAC>"
  151. #define MANACOST_FMT "<just:left><font:Arial:16><color:FFFFFF>"
  152. #define RANGE_FMT "<just:right><font:Arial:16><color:FFFFFF>"
  153. #define CASTLEN_FMT "<just:left><font:Arial:16><color:FFFFFF>"
  154. #define DESC_FMT "<just:left><font:Arial:16><color:ACACAC>"
  155. #define SMALL_BR "<font:Arial:4>\n"
  156. #define BR "\n"
  157. #define PACK_FMT "<just:right><font:Arial:14><color:ACACAC>"
  158. #define PACK_NAME_FMT "<color:FFD200>"
  159. char* afxRPGMagicSpellData::fmt_placeholder_desc(char* buffer, int len) const
  160. {
  161. char pack_str[32];
  162. if (source_pack == ST_NULLSTRING)
  163. dStrcpy(pack_str, "unknown", 32);
  164. else
  165. dSprintf(pack_str, 32, "%s", source_pack);
  166. dSprintf(buffer, len,
  167. NAME_FMT "%s" BR
  168. SMALL_BR
  169. DESC_FMT "%s" BR
  170. SMALL_BR SMALL_BR
  171. PACK_FMT "source: " PACK_NAME_FMT "%s",
  172. spell_name, spell_desc, pack_str);
  173. return buffer;
  174. }
  175. char* afxRPGMagicSpellData::formatDesc(char* buffer, int len) const
  176. {
  177. if (is_placeholder)
  178. return fmt_placeholder_desc(buffer, len);
  179. char target_str[32]; target_str[0] = '\0';
  180. // CAUTION: The following block of code is fragile and tricky since it depends
  181. // on the underlying structures defined by ImplementEnumType/EndImplementEnumType.
  182. // This done so the enum strings can be used directly in the spell description text.
  183. for (unsigned int i = 0; i < _afxRPGMagicSpell_TargetType::_sEnumTable.getNumValues(); i++)
  184. {
  185. if (_afxRPGMagicSpell_TargetType::_sEnumTable[i].mInt == spell_target)
  186. {
  187. if (spell_target != TARGET_NOTHING)
  188. {
  189. dStrcpy(target_str, _afxRPGMagicSpell_TargetType::_sEnumTable[i].mName, 32);
  190. if (spell_target != TARGET_FREE && target_optional)
  191. dStrcat(target_str, " (opt)", 32);
  192. }
  193. break;
  194. }
  195. }
  196. char range_str[32]; range_str[0] = '\0';
  197. if (spell_range > 0)
  198. {
  199. if (spell_range == ((F32)((S32)spell_range)))
  200. dSprintf(range_str, 32, "%d meter range", (S32) spell_range);
  201. else
  202. dSprintf(range_str, 32, "%.1f meter range", spell_range);
  203. }
  204. char casting_str[32];
  205. if (casting_dur <= 0)
  206. dStrcpy(casting_str, "instant", 32);
  207. else
  208. dSprintf(casting_str, 32, "%.1f sec cast", casting_dur);
  209. char pack_str[32];
  210. if (source_pack == ST_NULLSTRING)
  211. dStrcpy(pack_str, "unknown", 32);
  212. else
  213. dSprintf(pack_str, 32, "%s", source_pack);
  214. dSprintf(buffer, len,
  215. NAME_FMT "%s" TARGET_FMT "%s" BR
  216. SMALL_BR
  217. MANACOST_FMT "%d Mana" RANGE_FMT "%s" BR
  218. CASTLEN_FMT "%s" BR
  219. SMALL_BR SMALL_BR
  220. DESC_FMT "%s" BR SMALL_BR
  221. PACK_FMT "source: " PACK_NAME_FMT "%s",
  222. spell_name, target_str,
  223. mana_cost, range_str,
  224. casting_str,
  225. spell_desc, pack_str);
  226. return buffer;
  227. }
  228. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//