//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames // Copyright (C) 2015 Faust Logic, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// #include "afx/arcaneFX.h" #include "afxRPGMagicSpell.h" //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// // afxRPGMagicSpellData IMPLEMENT_CO_DATABLOCK_V1(afxRPGMagicSpellData); ConsoleDocClass( afxRPGMagicSpellData, "@brief A datablock for defining RPG aspects of a spell.\n\n" "@ingroup afxMisc\n" "@ingroup AFX\n" "@ingroup Datablocks\n" ); afxRPGMagicSpellData::afxRPGMagicSpellData() { // spell parameters spell_name = ST_NULLSTRING; spell_desc = ST_NULLSTRING; spell_target = TARGET_NOTHING; spell_range = 0.0f; mana_cost = 0; n_reagents = 0; for (S32 i = 0; i < MAX_REAGENTS_PER_SPELL; i++) { reagent_cost[i] = 1; reagent_name[i] = ST_NULLSTRING; } // spell phase timing casting_dur = 0.0f; // interface elements icon_name = ST_NULLSTRING; source_pack = ST_NULLSTRING; is_placeholder = false; free_target_style = 0; target_optional = false; } ImplementEnumType( afxRPGMagicSpell_TargetType, "Possible RPG spell target types.\n" "@ingroup afxRPGMagicSpell\n\n" ) { afxRPGMagicSpellData::TARGET_NOTHING, "nothing", "..." }, { afxRPGMagicSpellData::TARGET_SELF, "self", "..." }, { afxRPGMagicSpellData::TARGET_FRIEND, "friend", "..." }, { afxRPGMagicSpellData::TARGET_ENEMY, "enemy", "..." }, { afxRPGMagicSpellData::TARGET_CORPSE, "corpse", "..." }, { afxRPGMagicSpellData::TARGET_FREE, "free", "..." }, EndImplementEnumType; #define myOffset(field) Offset(field, afxRPGMagicSpellData) void afxRPGMagicSpellData::initPersistFields() { // spell parameters addField("spellName", TypeString, myOffset(spell_name), "..."); addField("desc", TypeString, myOffset(spell_desc), "..."); addField("target", TYPEID< afxRPGMagicSpellData::TargetType >(), myOffset(spell_target), "..."); addField("range", TypeF32, myOffset(spell_range), "..."); addField("manaCost", TypeS32, myOffset(mana_cost), "..."); addField("reagentCost", TypeS8, myOffset(reagent_cost), MAX_REAGENTS_PER_SPELL, "..."); addField("reagentName", TypeString, myOffset(reagent_name), MAX_REAGENTS_PER_SPELL, "..."); // spell phase timing addField("castingDur", TypeF32, myOffset(casting_dur)); // interface elements addField("iconBitmap", TypeFilename, myOffset(icon_name)); addField("sourcePack", TypeString, myOffset(source_pack)); addField("isPlaceholder", TypeBool, myOffset(is_placeholder)); addField("freeTargetStyle", TypeS8, myOffset(free_target_style)); addField("targetOptional", TypeBool, myOffset(target_optional)); Parent::initPersistFields(); } bool afxRPGMagicSpellData::onAdd() { if (Parent::onAdd() == false) return false; n_reagents = 0; for (S32 i = 0; i < MAX_REAGENTS_PER_SPELL && reagent_name[i] != ST_NULLSTRING; i++) n_reagents++; return true; } void afxRPGMagicSpellData::packData(BitStream* stream) { Parent::packData(stream); stream->write(spell_target); stream->write(spell_range); stream->write(mana_cost); stream->write(n_reagents); for (S32 i = 0; i < n_reagents; i++) { stream->write(reagent_cost[i]); stream->writeString(reagent_name[i]); } stream->write(casting_dur); stream->writeString(spell_name); stream->writeLongString(511, spell_desc); stream->writeString(icon_name); stream->writeString(source_pack); stream->writeFlag(is_placeholder); stream->writeFlag(target_optional); stream->write(free_target_style); } void afxRPGMagicSpellData::unpackData(BitStream* stream) { Parent::unpackData(stream); stream->read(&spell_target); stream->read(&spell_range); stream->read(&mana_cost); stream->read(&n_reagents); for (S32 i = 0; i < n_reagents; i++) { stream->read(&reagent_cost[i]); reagent_name[i] = stream->readSTString(); } stream->read(&casting_dur); spell_name = stream->readSTString(); { char value[512]; stream->readLongString(511, value); spell_desc = StringTable->insert(value); } icon_name = stream->readSTString(); source_pack = stream->readSTString(); is_placeholder = stream->readFlag(); target_optional = stream->readFlag(); stream->read(&free_target_style); } #define NAME_FMT "" #define TARGET_FMT "" #define MANACOST_FMT "" #define RANGE_FMT "" #define CASTLEN_FMT "" #define DESC_FMT "" #define SMALL_BR "\n" #define BR "\n" #define PACK_FMT "" #define PACK_NAME_FMT "" char* afxRPGMagicSpellData::fmt_placeholder_desc(char* buffer, int len) const { char pack_str[32]; if (source_pack == ST_NULLSTRING) dStrcpy(pack_str, "unknown", 32); else dSprintf(pack_str, 32, "%s", source_pack); dSprintf(buffer, len, NAME_FMT "%s" BR SMALL_BR DESC_FMT "%s" BR SMALL_BR SMALL_BR PACK_FMT "source: " PACK_NAME_FMT "%s", spell_name, spell_desc, pack_str); return buffer; } char* afxRPGMagicSpellData::formatDesc(char* buffer, int len) const { if (is_placeholder) return fmt_placeholder_desc(buffer, len); char target_str[32]; target_str[0] = '\0'; // CAUTION: The following block of code is fragile and tricky since it depends // on the underlying structures defined by ImplementEnumType/EndImplementEnumType. // This done so the enum strings can be used directly in the spell description text. for (unsigned int i = 0; i < _afxRPGMagicSpell_TargetType::_sEnumTable.getNumValues(); i++) { if (_afxRPGMagicSpell_TargetType::_sEnumTable[i].mInt == spell_target) { if (spell_target != TARGET_NOTHING) { dStrcpy(target_str, _afxRPGMagicSpell_TargetType::_sEnumTable[i].mName, 32); if (spell_target != TARGET_FREE && target_optional) dStrcat(target_str, " (opt)", 32); } break; } } char range_str[32]; range_str[0] = '\0'; if (spell_range > 0) { if (spell_range == ((F32)((S32)spell_range))) dSprintf(range_str, 32, "%d meter range", (S32) spell_range); else dSprintf(range_str, 32, "%.1f meter range", spell_range); } char casting_str[32]; if (casting_dur <= 0) dStrcpy(casting_str, "instant", 32); else dSprintf(casting_str, 32, "%.1f sec cast", casting_dur); char pack_str[32]; if (source_pack == ST_NULLSTRING) dStrcpy(pack_str, "unknown", 32); else dSprintf(pack_str, 32, "%s", source_pack); dSprintf(buffer, len, NAME_FMT "%s" TARGET_FMT "%s" BR SMALL_BR MANACOST_FMT "%d Mana" RANGE_FMT "%s" BR CASTLEN_FMT "%s" BR SMALL_BR SMALL_BR DESC_FMT "%s" BR SMALL_BR PACK_FMT "source: " PACK_NAME_FMT "%s", spell_name, target_str, mana_cost, range_str, casting_str, spell_desc, pack_str); return buffer; } //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//