From b57807407afa8b1cb50026422c20278f73d56632 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Mon, 30 Jul 2018 10:56:26 +0300 Subject: [PATCH] [General] Implement RecordDynamic packet, part 1 Spell, potion, enchantment, creature, NPC, armor, book, clothing, miscellaneous and weapon record data can now be sent in a RecordDynamic packet. Additionally, the packets include data related to associated magical effects (for spells, potions and enchantments), data related to default inventory contents (for creatures and NPCs) and data related to body parts affected (for armor and clothing). The server now has associated script functions for setting most of the details of the above, with the main exception being individual creature and NPC stats. Records can either be created entirely from scratch or can use an existing record (set via the baseId variable) as a starting point for their values. In the latter case, only the values that are specifically set override the starting values. Creature and NPC records also have an inventoryBaseId that can be used on top of the baseId to base their inventories on another existing record. The client's RecordHelper class has been heavily expanded to allow for the above mentioned functionality. When players create spells, potions and enchantments as part of regular gameplay, they send RecordDynamic packets that provide the server with the complete details of the records that should be created. When they create enchantments, they also provide the server with armor, book, clothing and weapon records corresponding to the items they've enchanted. This functionality added by this packet was originally supposed to be exclusive to the rewrite, but I've gone ahead and tried to provide it for the pre-rewrite in a way that can mostly be reused for the rewrite. --- apps/openmw-mp/CMakeLists.txt | 6 +- apps/openmw-mp/Script/Functions/Actors.hpp | 2 +- .../Script/Functions/RecordsDynamic.cpp | 1200 +++++++++++++++++ .../Script/Functions/RecordsDynamic.hpp | 880 ++++++++++++ apps/openmw-mp/Script/ScriptFunctions.hpp | 2 + apps/openmw/mwclass/armor.cpp | 13 + apps/openmw/mwclass/book.cpp | 12 + apps/openmw/mwclass/clothing.cpp | 12 + apps/openmw/mwclass/weapon.cpp | 12 + apps/openmw/mwgui/alchemywindow.cpp | 11 - apps/openmw/mwgui/enchantingdialog.cpp | 10 - apps/openmw/mwgui/spellcreationdialog.cpp | 24 +- apps/openmw/mwmechanics/alchemy.cpp | 31 +- apps/openmw/mwmechanics/enchanting.cpp | 43 +- apps/openmw/mwmp/DedicatedPlayer.cpp | 4 +- apps/openmw/mwmp/ObjectList.cpp | 2 +- apps/openmw/mwmp/RecordHelper.cpp | 771 ++++++++++- apps/openmw/mwmp/RecordHelper.hpp | 53 +- apps/openmw/mwmp/Worldstate.cpp | 256 ++++ apps/openmw/mwmp/Worldstate.hpp | 12 +- .../worldstate/ProcessorRecordDynamic.hpp | 2 +- components/openmw-mp/Base/BaseWorldstate.hpp | 169 +++ .../Worldstate/PacketRecordDynamic.cpp | 507 ++++++- .../Worldstate/PacketRecordDynamic.hpp | 10 + 24 files changed, 3967 insertions(+), 77 deletions(-) create mode 100644 apps/openmw-mp/Script/Functions/RecordsDynamic.cpp create mode 100644 apps/openmw-mp/Script/Functions/RecordsDynamic.hpp diff --git a/apps/openmw-mp/CMakeLists.txt b/apps/openmw-mp/CMakeLists.txt index a619e2a98..c691de081 100644 --- a/apps/openmw-mp/CMakeLists.txt +++ b/apps/openmw-mp/CMakeLists.txt @@ -64,9 +64,9 @@ set(SERVER Script/Functions/Books.cpp Script/Functions/Cells.cpp Script/Functions/CharClass.cpp Script/Functions/Chat.cpp Script/Functions/Dialogue.cpp Script/Functions/Factions.cpp Script/Functions/GUI.cpp Script/Functions/Items.cpp Script/Functions/Mechanics.cpp - Script/Functions/Positions.cpp Script/Functions/Quests.cpp Script/Functions/Server.cpp - Script/Functions/Settings.cpp Script/Functions/Shapeshift.cpp Script/Functions/Spells.cpp - Script/Functions/Stats.cpp Script/Functions/Timer.cpp + Script/Functions/Positions.cpp Script/Functions/Quests.cpp Script/Functions/RecordsDynamic.cpp + Script/Functions/Server.cpp Script/Functions/Settings.cpp Script/Functions/Shapeshift.cpp + Script/Functions/Spells.cpp Script/Functions/Stats.cpp Script/Functions/Timer.cpp Script/API/TimerAPI.cpp Script/API/PublicFnAPI.cpp ${LuaScript_Sources} diff --git a/apps/openmw-mp/Script/Functions/Actors.hpp b/apps/openmw-mp/Script/Functions/Actors.hpp index c4479eeda..0a9204ef5 100644 --- a/apps/openmw-mp/Script/Functions/Actors.hpp +++ b/apps/openmw-mp/Script/Functions/Actors.hpp @@ -122,7 +122,7 @@ public: static void ReadCellActorList(const char* cellDescription) noexcept; /** - * \brief Clear the data from the last actor list sent by the server. + * \brief Clear the data from the actor list stored on the server. * * \return void */ diff --git a/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp b/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp new file mode 100644 index 000000000..32d5f8260 --- /dev/null +++ b/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp @@ -0,0 +1,1200 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include "RecordsDynamic.hpp" + +using namespace std; +using namespace mwmp; + +SpellRecord tempSpell; +PotionRecord tempPotion; +EnchantmentRecord tempEnchantment; +CreatureRecord tempCreature; +NpcRecord tempNpc; +ArmorRecord tempArmor; +BookRecord tempBook; +ClothingRecord tempClothing; +MiscellaneousRecord tempMiscellaneous; +WeaponRecord tempWeapon; + +BaseOverrides tempOverrides; + +ESM::ENAMstruct tempEffect; +ESM::PartReference tempBodyPart; +mwmp::Item tempInventoryItem; + +const ESM::EffectList emptyEffectList = {}; + +const ESM::EffectList& GetRecordEffects(unsigned int recordIndex) +{ + unsigned short recordsType = RecordsDynamicFunctions::GetRecordType(); + + if (recordsType == mwmp::RECORD_TYPE::SPELL) + return WorldstateFunctions::readWorldstate->spellRecords.at(recordIndex).data.mEffects; + else if (recordsType == mwmp::RECORD_TYPE::POTION) + return WorldstateFunctions::readWorldstate->potionRecords.at(recordIndex).data.mEffects; + else if (recordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + return WorldstateFunctions::readWorldstate->enchantmentRecords.at(recordIndex).data.mEffects; + + return emptyEffectList; +} + +void RecordsDynamicFunctions::ClearRecords() noexcept +{ + WorldstateFunctions::writeWorldstate.spellRecords.clear(); + WorldstateFunctions::writeWorldstate.potionRecords.clear(); + WorldstateFunctions::writeWorldstate.enchantmentRecords.clear(); + WorldstateFunctions::writeWorldstate.creatureRecords.clear(); + WorldstateFunctions::writeWorldstate.npcRecords.clear(); + WorldstateFunctions::writeWorldstate.armorRecords.clear(); + WorldstateFunctions::writeWorldstate.bookRecords.clear(); + WorldstateFunctions::writeWorldstate.clothingRecords.clear(); + WorldstateFunctions::writeWorldstate.miscellaneousRecords.clear(); + WorldstateFunctions::writeWorldstate.weaponRecords.clear(); +} + +unsigned short RecordsDynamicFunctions::GetRecordType() noexcept +{ + return WorldstateFunctions::readWorldstate->recordsType; +} + +unsigned int RecordsDynamicFunctions::GetRecordCount() noexcept +{ + return WorldstateFunctions::readWorldstate->recordsCount; +} + +unsigned int RecordsDynamicFunctions::GetRecordEffectCount(unsigned int recordIndex) noexcept +{ + return GetRecordEffects(recordIndex).mList.size(); +} + +int RecordsDynamicFunctions::GetRecordSubtype(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::SPELL) + return WorldstateFunctions::readWorldstate->spellRecords.at(index).data.mData.mType; + else if (readRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + return WorldstateFunctions::readWorldstate->enchantmentRecords.at(index).data.mData.mType; + + return -1; +} + +const char *RecordsDynamicFunctions::GetRecordId(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::SPELL) + return WorldstateFunctions::readWorldstate->spellRecords.at(index).data.mId.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::POTION) + return WorldstateFunctions::readWorldstate->potionRecords.at(index).data.mId.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + return WorldstateFunctions::readWorldstate->enchantmentRecords.at(index).data.mId.c_str(); + + return "invalid"; +} + +const char *RecordsDynamicFunctions::GetRecordBaseId(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::SPELL) + return WorldstateFunctions::readWorldstate->spellRecords.at(index).baseId.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::POTION) + return WorldstateFunctions::readWorldstate->potionRecords.at(index).baseId.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + return WorldstateFunctions::readWorldstate->enchantmentRecords.at(index).baseId.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::ARMOR) + return WorldstateFunctions::readWorldstate->armorRecords.at(index).baseId.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::BOOK) + return WorldstateFunctions::readWorldstate->bookRecords.at(index).baseId.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::CLOTHING) + return WorldstateFunctions::readWorldstate->clothingRecords.at(index).baseId.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::WEAPON) + return WorldstateFunctions::readWorldstate->weaponRecords.at(index).baseId.c_str(); + + return "invalid"; +} + +const char *RecordsDynamicFunctions::GetRecordName(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::SPELL) + return WorldstateFunctions::readWorldstate->spellRecords.at(index).data.mName.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::POTION) + return WorldstateFunctions::readWorldstate->potionRecords.at(index).data.mName.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::ARMOR) + return WorldstateFunctions::readWorldstate->armorRecords.at(index).data.mName.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::BOOK) + return WorldstateFunctions::readWorldstate->bookRecords.at(index).data.mName.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::CLOTHING) + return WorldstateFunctions::readWorldstate->clothingRecords.at(index).data.mName.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::WEAPON) + return WorldstateFunctions::readWorldstate->weaponRecords.at(index).data.mName.c_str(); + + return "invalid"; +} + +const char *RecordsDynamicFunctions::GetRecordModel(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::POTION) + return WorldstateFunctions::readWorldstate->potionRecords.at(index).data.mModel.c_str(); + + return "invalid"; +} + +const char *RecordsDynamicFunctions::GetRecordIcon(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::POTION) + return WorldstateFunctions::readWorldstate->potionRecords.at(index).data.mIcon.c_str(); + + return "invalid"; +} + +const char *RecordsDynamicFunctions::GetRecordScript(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::POTION) + return WorldstateFunctions::readWorldstate->potionRecords.at(index).data.mScript.c_str(); + + return "invalid"; +} + +const char *RecordsDynamicFunctions::GetRecordEnchantmentId(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::ARMOR) + return WorldstateFunctions::readWorldstate->armorRecords.at(index).data.mEnchant.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::BOOK) + return WorldstateFunctions::readWorldstate->bookRecords.at(index).data.mEnchant.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::CLOTHING) + return WorldstateFunctions::readWorldstate->clothingRecords.at(index).data.mEnchant.c_str(); + else if (readRecordsType == mwmp::RECORD_TYPE::WEAPON) + return WorldstateFunctions::readWorldstate->weaponRecords.at(index).data.mEnchant.c_str(); + + return "invalid"; +} + +int RecordsDynamicFunctions::GetRecordEnchantmentCharge(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::ARMOR) + return WorldstateFunctions::readWorldstate->armorRecords.at(index).data.mData.mEnchant; + else if (readRecordsType == mwmp::RECORD_TYPE::BOOK) + return WorldstateFunctions::readWorldstate->bookRecords.at(index).data.mData.mEnchant; + else if (readRecordsType == mwmp::RECORD_TYPE::CLOTHING) + return WorldstateFunctions::readWorldstate->clothingRecords.at(index).data.mData.mEnchant; + else if (readRecordsType == mwmp::RECORD_TYPE::WEAPON) + return WorldstateFunctions::readWorldstate->weaponRecords.at(index).data.mData.mEnchant; + + return -1; +} + +int RecordsDynamicFunctions::GetRecordAutoCalc(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::POTION) + return WorldstateFunctions::readWorldstate->potionRecords.at(index).data.mData.mAutoCalc; + else if (readRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + return WorldstateFunctions::readWorldstate->enchantmentRecords.at(index).data.mData.mAutocalc; + + return -1; +} + +int RecordsDynamicFunctions::GetRecordCharge(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + return WorldstateFunctions::readWorldstate->enchantmentRecords.at(index).data.mData.mCharge; + + return -1; +} + +int RecordsDynamicFunctions::GetRecordCost(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::SPELL) + return WorldstateFunctions::readWorldstate->spellRecords.at(index).data.mData.mCost; + else if (readRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + return WorldstateFunctions::readWorldstate->enchantmentRecords.at(index).data.mData.mCost; + + return -1; +} + +int RecordsDynamicFunctions::GetRecordFlags(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::SPELL) + return WorldstateFunctions::readWorldstate->spellRecords.at(index).data.mData.mFlags; + + return -1; +} + +int RecordsDynamicFunctions::GetRecordValue(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::POTION) + return WorldstateFunctions::readWorldstate->potionRecords.at(index).data.mData.mValue; + + return -1; +} + +double RecordsDynamicFunctions::GetRecordWeight(unsigned int index) noexcept +{ + unsigned short readRecordsType = RecordsDynamicFunctions::GetRecordType(); + + if (readRecordsType == mwmp::RECORD_TYPE::POTION) + return WorldstateFunctions::readWorldstate->potionRecords.at(index).data.mData.mWeight; + + return -1; +} + +unsigned int RecordsDynamicFunctions::GetRecordEffectId(unsigned int recordIndex, unsigned int effectIndex) noexcept +{ + return GetRecordEffects(recordIndex).mList.at(effectIndex).mEffectID; +} + +int RecordsDynamicFunctions::GetRecordEffectAttribute(unsigned int recordIndex, unsigned int effectIndex) noexcept +{ + return GetRecordEffects(recordIndex).mList.at(effectIndex).mAttribute; +} + +int RecordsDynamicFunctions::GetRecordEffectSkill(unsigned int recordIndex, unsigned int effectIndex) noexcept +{ + return GetRecordEffects(recordIndex).mList.at(effectIndex).mSkill; +} + +unsigned int RecordsDynamicFunctions::GetRecordEffectRangeType(unsigned int recordIndex, unsigned int effectIndex) noexcept +{ + return GetRecordEffects(recordIndex).mList.at(effectIndex).mRange; +} + +int RecordsDynamicFunctions::GetRecordEffectArea(unsigned int recordIndex, unsigned int effectIndex) noexcept +{ + return GetRecordEffects(recordIndex).mList.at(effectIndex).mArea; +} + +int RecordsDynamicFunctions::GetRecordEffectDuration(unsigned int recordIndex, unsigned int effectIndex) noexcept +{ + return GetRecordEffects(recordIndex).mList.at(effectIndex).mDuration; +} + +int RecordsDynamicFunctions::GetRecordEffectMagnitudeMax(unsigned int recordIndex, unsigned int effectIndex) noexcept +{ + return GetRecordEffects(recordIndex).mList.at(effectIndex).mMagnMax; +} + +int RecordsDynamicFunctions::GetRecordEffectMagnitudeMin(unsigned int recordIndex, unsigned int effectIndex) noexcept +{ + return GetRecordEffects(recordIndex).mList.at(effectIndex).mMagnMin; +} + +void RecordsDynamicFunctions::SetRecordType(unsigned int type) noexcept +{ + WorldstateFunctions::writeWorldstate.recordsType = type; +} + +void RecordsDynamicFunctions::SetRecordId(const char* id) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::SPELL) + tempSpell.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + tempPotion.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + tempEnchantment.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + tempCreature.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::MISCELLANEOUS) + tempMiscellaneous.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mId = id; + + else + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set id for record type %i which lacks that property", writeRecordsType); +} + +void RecordsDynamicFunctions::SetRecordBaseId(const char* baseId) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::SPELL) + tempSpell.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + tempPotion.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + tempEnchantment.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + tempCreature.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::MISCELLANEOUS) + tempMiscellaneous.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.baseId = baseId; + else + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set baseId for record type %i which lacks that property", writeRecordsType); +} + +void RecordsDynamicFunctions::SetRecordInventoryBaseId(const char* inventoryBaseId) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + tempCreature.inventoryBaseId = inventoryBaseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.inventoryBaseId = inventoryBaseId; + else + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set inventoryBaseId for record type %i which lacks that property", writeRecordsType); +} + +void RecordsDynamicFunctions::SetRecordSubtype(unsigned int subtype) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::SPELL) + tempSpell.data.mData.mType = subtype; + else if (writeRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + tempEnchantment.data.mData.mType = subtype; + else if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + tempCreature.data.mData.mType = subtype; + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mData.mType = subtype; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mData.mType = subtype; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mData.mType = subtype; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set subtype for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasSubtype = true; +} + +void RecordsDynamicFunctions::SetRecordName(const char* name) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::SPELL) + tempSpell.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + tempPotion.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + tempCreature.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::MISCELLANEOUS) + tempMiscellaneous.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mName = name; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set name for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasName = true; +} + +void RecordsDynamicFunctions::SetRecordModel(const char* model) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + tempPotion.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + tempCreature.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::MISCELLANEOUS) + tempMiscellaneous.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mModel = model; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set model for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasModel = true; +} + +void RecordsDynamicFunctions::SetRecordIcon(const char* icon) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + tempPotion.data.mIcon = icon; + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mIcon = icon; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mIcon = icon; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mIcon = icon; + else if (writeRecordsType == mwmp::RECORD_TYPE::MISCELLANEOUS) + tempMiscellaneous.data.mIcon = icon; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mIcon = icon; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set icon for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasIcon = true; +} + +void RecordsDynamicFunctions::SetRecordScript(const char* script) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + tempPotion.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + tempCreature.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::MISCELLANEOUS) + tempMiscellaneous.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mScript = script; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set script for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasScript = true; +} + +void RecordsDynamicFunctions::SetRecordEnchantmentId(const char* enchantmentId) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mEnchant = enchantmentId; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mEnchant = enchantmentId; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mEnchant = enchantmentId; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mEnchant = enchantmentId; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set enchantment id for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasEnchantmentId = true; +} + +void RecordsDynamicFunctions::SetRecordEnchantmentCharge(int enchantmentCharge) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mData.mEnchant = enchantmentCharge; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mData.mEnchant = enchantmentCharge; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mData.mEnchant = enchantmentCharge; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mData.mEnchant = enchantmentCharge; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set enchantment charge for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasEnchantmentCharge = true; +} + +void RecordsDynamicFunctions::SetRecordAutoCalc(int autoCalc) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + tempPotion.data.mData.mAutoCalc = autoCalc; + else if (writeRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + tempEnchantment.data.mData.mAutocalc = autoCalc; + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + { + if (autoCalc) + { + tempNpc.data.mFlags |= ESM::NPC::Autocalc; + tempNpc.data.mNpdtType = ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS; + } + else + { + tempNpc.data.mFlags &= ~ESM::NPC::Autocalc; + tempNpc.data.mNpdtType = ESM::NPC::NPC_DEFAULT; + } + } + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set autoCalc for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasAutoCalc = true; +} + +void RecordsDynamicFunctions::SetRecordCharge(int charge) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + tempEnchantment.data.mData.mCharge = charge; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set charge for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasCharge = true; +} + +void RecordsDynamicFunctions::SetRecordCost(int cost) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::SPELL) + tempSpell.data.mData.mCost = cost; + else if (writeRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + tempEnchantment.data.mData.mCost = cost; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set cost for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasCost = true; +} + +void RecordsDynamicFunctions::SetRecordFlags(int flags) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::SPELL) + tempSpell.data.mData.mFlags = flags; + else if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + tempCreature.data.mFlags = flags; + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mFlags = flags; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mData.mFlags = flags; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set flags for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasFlags = true; +} + +void RecordsDynamicFunctions::SetRecordValue(int value) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + tempPotion.data.mData.mValue = value; + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mData.mValue = value; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mData.mValue = value; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mData.mValue = value; + else if (writeRecordsType == mwmp::RECORD_TYPE::MISCELLANEOUS) + tempMiscellaneous.data.mData.mValue = value; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mData.mValue = value; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set value for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasValue = true; +} + +void RecordsDynamicFunctions::SetRecordWeight(double weight) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + tempPotion.data.mData.mWeight = weight; + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mData.mWeight = weight; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mData.mWeight = weight; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mData.mWeight = weight; + else if (writeRecordsType == mwmp::RECORD_TYPE::MISCELLANEOUS) + tempMiscellaneous.data.mData.mWeight = weight; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mData.mWeight = weight; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set weight for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasWeight = true; +} + +void RecordsDynamicFunctions::SetRecordArmorRating(int armorRating) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mData.mArmor = armorRating; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set armor rating for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasArmorRating = true; +} + +void RecordsDynamicFunctions::SetRecordHealth(int health) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mData.mHealth = health; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mData.mHealth = health; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set health for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasHealth = true; +} + +void RecordsDynamicFunctions::SetRecordDamageChop(unsigned int minDamage, unsigned int maxDamage) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + { + tempWeapon.data.mData.mChop[0] = minDamage; + tempWeapon.data.mData.mChop[1] = maxDamage; + } + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set chop damage for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasDamageChop = true; +} + +void RecordsDynamicFunctions::SetRecordDamageSlash(unsigned int minDamage, unsigned int maxDamage) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + { + tempWeapon.data.mData.mSlash[0] = minDamage; + tempWeapon.data.mData.mSlash[1] = maxDamage; + } + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set slash damage for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasDamageSlash = true; +} + +void RecordsDynamicFunctions::SetRecordDamageThrust(unsigned int minDamage, unsigned int maxDamage) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + { + tempWeapon.data.mData.mThrust[0] = minDamage; + tempWeapon.data.mData.mThrust[1] = maxDamage; + } + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set thrust damage for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasDamageThrust = true; +} + +void RecordsDynamicFunctions::SetRecordReach(double reach) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mData.mReach = reach; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set reach for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasReach = true; +} + +void RecordsDynamicFunctions::SetRecordSpeed(double speed) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + tempWeapon.data.mData.mSpeed = speed; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set speed for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasSpeed = true; +} + +void RecordsDynamicFunctions::SetRecordKeyState(bool keyState) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::MISCELLANEOUS) + tempMiscellaneous.data.mData.mIsKey = keyState; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set key state for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasKeyState = true; +} + +void RecordsDynamicFunctions::SetRecordScrollState(bool scrollState) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mData.mIsScroll = scrollState; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set scroll state for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasScrollState = true; +} + +void RecordsDynamicFunctions::SetRecordSkillId(int skillId) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mData.mSkillId = skillId; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set skill id for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasSkillId = true; +} + +void RecordsDynamicFunctions::SetRecordText(const char* text) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + tempBook.data.mText = text; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set text for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasText = true; +} + +void RecordsDynamicFunctions::SetRecordHair(const char* hair) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mHair = hair; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set hair for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasHair = true; +} + +void RecordsDynamicFunctions::SetRecordHead(const char* head) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mHead = head; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set head for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasHead = true; +} + +void RecordsDynamicFunctions::SetRecordGender(unsigned int gender) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + { + tempNpc.data.setIsMale(gender); + } + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set gender for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasGender = true; +} + +void RecordsDynamicFunctions::SetRecordRace(const char* race) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mRace = race; + else + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set race for record type %i which lacks that property", writeRecordsType); +} + +void RecordsDynamicFunctions::SetRecordClass(const char* charClass) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mClass = charClass; + else + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set character class for record type %i which lacks that property", writeRecordsType); +} + +void RecordsDynamicFunctions::SetRecordFaction(const char* faction) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mFaction = faction; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set faction for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasFaction = true; +} + +void RecordsDynamicFunctions::SetRecordLevel(int level) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + tempCreature.data.mData.mLevel = level; + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.data.mNpdt.mLevel = level; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set level for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasLevel = true; +} + +void RecordsDynamicFunctions::SetRecordIdByIndex(unsigned int index, const char* id) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::SPELL) + WorldstateFunctions::writeWorldstate.spellRecords.at(index).data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + WorldstateFunctions::writeWorldstate.potionRecords.at(index).data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + WorldstateFunctions::writeWorldstate.enchantmentRecords.at(index).data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + WorldstateFunctions::writeWorldstate.armorRecords.at(index).data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + WorldstateFunctions::writeWorldstate.bookRecords.at(index).data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + WorldstateFunctions::writeWorldstate.clothingRecords.at(index).data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + WorldstateFunctions::writeWorldstate.weaponRecords.at(index).data.mId = id; + else + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set id for record type %i which lacks that property", writeRecordsType); +} + +void RecordsDynamicFunctions::SetRecordEnchantmentIdByIndex(unsigned int index, const char* enchantmentId) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + WorldstateFunctions::writeWorldstate.armorRecords.at(index).data.mEnchant = enchantmentId; + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + WorldstateFunctions::writeWorldstate.bookRecords.at(index).data.mEnchant = enchantmentId; + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + WorldstateFunctions::writeWorldstate.clothingRecords.at(index).data.mEnchant = enchantmentId; + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + WorldstateFunctions::writeWorldstate.weaponRecords.at(index).data.mEnchant = enchantmentId; + else + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set enchantmentId for record type %i which lacks that property", writeRecordsType); +} + +void RecordsDynamicFunctions::SetRecordEffectId(unsigned int effectId) noexcept +{ + tempEffect.mEffectID = effectId; +} + +void RecordsDynamicFunctions::SetRecordEffectAttribute(int attributeId) noexcept +{ + tempEffect.mAttribute = attributeId; +} + +void RecordsDynamicFunctions::SetRecordEffectSkill(int skillId) noexcept +{ + tempEffect.mSkill = skillId; +} + +void RecordsDynamicFunctions::SetRecordEffectRangeType(unsigned int rangeType) noexcept +{ + tempEffect.mRange = rangeType; +} + +void RecordsDynamicFunctions::SetRecordEffectArea(int area) noexcept +{ + tempEffect.mArea = area; +} + +void RecordsDynamicFunctions::SetRecordEffectDuration(int duration) noexcept +{ + tempEffect.mDuration = duration; +} + +void RecordsDynamicFunctions::SetRecordEffectMagnitudeMax(int magnitudeMax) noexcept +{ + tempEffect.mMagnMax = magnitudeMax; +} + +void RecordsDynamicFunctions::SetRecordEffectMagnitudeMin(int magnitudeMin) noexcept +{ + tempEffect.mMagnMin = magnitudeMin; +} + +void RecordsDynamicFunctions::SetRecordBodyPartType(unsigned int partType) noexcept +{ + tempBodyPart.mPart = partType; +} + +void RecordsDynamicFunctions::SetRecordBodyPartIdForMale(const char* partId) noexcept +{ + tempBodyPart.mMale = partId; +} + +void RecordsDynamicFunctions::SetRecordBodyPartIdForFemale(const char* partId) noexcept +{ + tempBodyPart.mFemale = partId; +} + +void RecordsDynamicFunctions::SetRecordInventoryItemId(const char* itemId) noexcept +{ + tempInventoryItem.refId = itemId; +} + +void RecordsDynamicFunctions::SetRecordInventoryItemCount(unsigned int count) noexcept +{ + tempInventoryItem.count = count; +} + +void RecordsDynamicFunctions::AddRecord() noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::SPELL) + { + tempSpell.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.spellRecords.push_back(tempSpell); + tempSpell = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + { + tempPotion.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.potionRecords.push_back(tempPotion); + tempPotion = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + { + tempEnchantment.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.enchantmentRecords.push_back(tempEnchantment); + tempEnchantment = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + { + tempCreature.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.creatureRecords.push_back(tempCreature); + tempCreature = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + { + tempNpc.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.npcRecords.push_back(tempNpc); + tempNpc = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + { + tempArmor.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.armorRecords.push_back(tempArmor); + tempArmor = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::BOOK) + { + tempBook.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.bookRecords.push_back(tempBook); + tempBook = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + { + tempClothing.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.clothingRecords.push_back(tempClothing); + tempClothing = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::MISCELLANEOUS) + { + tempMiscellaneous.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.miscellaneousRecords.push_back(tempMiscellaneous); + tempMiscellaneous = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) + { + tempWeapon.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.weaponRecords.push_back(tempWeapon); + tempWeapon = {}; + } + + tempOverrides = {}; +} + +void RecordsDynamicFunctions::AddRecordEffect() noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::SPELL) + tempSpell.data.mEffects.mList.push_back(tempEffect); + else if (writeRecordsType == mwmp::RECORD_TYPE::POTION) + tempPotion.data.mEffects.mList.push_back(tempEffect); + else if (writeRecordsType == mwmp::RECORD_TYPE::ENCHANTMENT) + tempEnchantment.data.mEffects.mList.push_back(tempEffect); + + tempOverrides.hasEffects = true; + tempEffect = {}; +} + +void RecordsDynamicFunctions::AddRecordBodyPart() noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) + tempArmor.data.mParts.mParts.push_back(tempBodyPart); + else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) + tempClothing.data.mParts.mParts.push_back(tempBodyPart); + + tempOverrides.hasBodyParts = true; + tempBodyPart = {}; +} + +void RecordsDynamicFunctions::AddRecordInventoryItem() noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CREATURE) + tempCreature.inventory.push_back(tempInventoryItem); + else if (writeRecordsType == mwmp::RECORD_TYPE::NPC) + tempNpc.inventory.push_back(tempInventoryItem); + + tempOverrides.hasInventory = true; + tempInventoryItem = {}; +} + +void RecordsDynamicFunctions::SendRecordDynamic(unsigned short pid, bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + WorldstateFunctions::writeWorldstate.guid = player->guid; + + mwmp::WorldstatePacket *packet = mwmp::Networking::get().getWorldstatePacketController()->GetPacket(ID_RECORD_DYNAMIC); + packet->setWorldstate(&WorldstateFunctions::writeWorldstate); + + if (!skipAttachedPlayer) + packet->Send(false); + if (sendToOtherPlayers) + packet->Send(true); +} diff --git a/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp b/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp new file mode 100644 index 000000000..34b62c12b --- /dev/null +++ b/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp @@ -0,0 +1,880 @@ +#ifndef OPENMW_RECORDSDYNAMICAPI_HPP +#define OPENMW_RECORDSDYNAMICAPI_HPP + +#include "../Types.hpp" + +#define RECORDSDYNAMICAPI \ + {"ClearRecords", RecordsDynamicFunctions::ClearRecords},\ + \ + {"GetRecordType", RecordsDynamicFunctions::GetRecordType},\ + {"GetRecordCount", RecordsDynamicFunctions::GetRecordCount},\ + {"GetRecordEffectCount", RecordsDynamicFunctions::GetRecordEffectCount},\ + \ + {"GetRecordId", RecordsDynamicFunctions::GetRecordId},\ + {"GetRecordBaseId", RecordsDynamicFunctions::GetRecordBaseId},\ + \ + {"GetRecordSubtype", RecordsDynamicFunctions::GetRecordSubtype},\ + {"GetRecordName", RecordsDynamicFunctions::GetRecordName},\ + {"GetRecordModel", RecordsDynamicFunctions::GetRecordModel},\ + {"GetRecordIcon", RecordsDynamicFunctions::GetRecordIcon},\ + {"GetRecordScript", RecordsDynamicFunctions::GetRecordScript},\ + {"GetRecordEnchantmentId", RecordsDynamicFunctions::GetRecordEnchantmentId},\ + {"GetRecordEnchantmentCharge", RecordsDynamicFunctions::GetRecordEnchantmentCharge},\ + \ + {"GetRecordAutoCalc", RecordsDynamicFunctions::GetRecordAutoCalc},\ + {"GetRecordCharge", RecordsDynamicFunctions::GetRecordCharge},\ + {"GetRecordCost", RecordsDynamicFunctions::GetRecordCost},\ + {"GetRecordFlags", RecordsDynamicFunctions::GetRecordFlags},\ + {"GetRecordValue", RecordsDynamicFunctions::GetRecordValue},\ + {"GetRecordWeight", RecordsDynamicFunctions::GetRecordWeight},\ + \ + {"GetRecordEffectId", RecordsDynamicFunctions::GetRecordEffectId},\ + {"GetRecordEffectAttribute", RecordsDynamicFunctions::GetRecordEffectAttribute},\ + {"GetRecordEffectSkill", RecordsDynamicFunctions::GetRecordEffectSkill},\ + {"GetRecordEffectRangeType", RecordsDynamicFunctions::GetRecordEffectRangeType},\ + {"GetRecordEffectArea", RecordsDynamicFunctions::GetRecordEffectArea},\ + {"GetRecordEffectDuration", RecordsDynamicFunctions::GetRecordEffectDuration},\ + {"GetRecordEffectMagnitudeMax", RecordsDynamicFunctions::GetRecordEffectMagnitudeMax},\ + {"GetRecordEffectMagnitudeMin", RecordsDynamicFunctions::GetRecordEffectMagnitudeMin},\ + \ + {"SetRecordType", RecordsDynamicFunctions::SetRecordType},\ + \ + {"SetRecordId", RecordsDynamicFunctions::SetRecordId},\ + {"SetRecordBaseId", RecordsDynamicFunctions::SetRecordBaseId},\ + {"SetRecordInventoryBaseId", RecordsDynamicFunctions::SetRecordInventoryBaseId},\ + \ + {"SetRecordSubtype", RecordsDynamicFunctions::SetRecordSubtype},\ + {"SetRecordName", RecordsDynamicFunctions::SetRecordName},\ + {"SetRecordModel", RecordsDynamicFunctions::SetRecordModel},\ + {"SetRecordIcon", RecordsDynamicFunctions::SetRecordIcon},\ + {"SetRecordScript", RecordsDynamicFunctions::SetRecordScript},\ + {"SetRecordEnchantmentId", RecordsDynamicFunctions::SetRecordEnchantmentId},\ + {"SetRecordEnchantmentCharge", RecordsDynamicFunctions::SetRecordEnchantmentCharge},\ + \ + {"SetRecordAutoCalc", RecordsDynamicFunctions::SetRecordAutoCalc},\ + {"SetRecordCharge", RecordsDynamicFunctions::SetRecordCharge},\ + {"SetRecordCost", RecordsDynamicFunctions::SetRecordCost},\ + {"SetRecordFlags", RecordsDynamicFunctions::SetRecordFlags},\ + {"SetRecordValue", RecordsDynamicFunctions::SetRecordValue},\ + {"SetRecordWeight", RecordsDynamicFunctions::SetRecordWeight},\ + \ + {"SetRecordArmorRating", RecordsDynamicFunctions::SetRecordArmorRating},\ + {"SetRecordHealth", RecordsDynamicFunctions::SetRecordHealth},\ + \ + {"SetRecordDamageChop", RecordsDynamicFunctions::SetRecordDamageChop},\ + {"SetRecordDamageSlash", RecordsDynamicFunctions::SetRecordDamageSlash},\ + {"SetRecordDamageThrust", RecordsDynamicFunctions::SetRecordDamageThrust},\ + {"SetRecordReach", RecordsDynamicFunctions::SetRecordReach},\ + {"SetRecordSpeed", RecordsDynamicFunctions::SetRecordSpeed},\ + \ + {"SetRecordKeyState", RecordsDynamicFunctions::SetRecordKeyState},\ + {"SetRecordScrollState", RecordsDynamicFunctions::SetRecordScrollState},\ + {"SetRecordSkillId", RecordsDynamicFunctions::SetRecordSkillId},\ + {"SetRecordText", RecordsDynamicFunctions::SetRecordText},\ + \ + {"SetRecordHair", RecordsDynamicFunctions::SetRecordHair},\ + {"SetRecordHead", RecordsDynamicFunctions::SetRecordHead},\ + {"SetRecordGender", RecordsDynamicFunctions::SetRecordGender},\ + {"SetRecordRace", RecordsDynamicFunctions::SetRecordRace},\ + {"SetRecordClass", RecordsDynamicFunctions::SetRecordClass},\ + {"SetRecordFaction", RecordsDynamicFunctions::SetRecordFaction},\ + \ + {"SetRecordLevel", RecordsDynamicFunctions::SetRecordLevel},\ + \ + {"SetRecordIdByIndex", RecordsDynamicFunctions::SetRecordIdByIndex},\ + {"SetRecordEnchantmentIdByIndex", RecordsDynamicFunctions::SetRecordEnchantmentIdByIndex},\ + \ + {"SetRecordEffectId", RecordsDynamicFunctions::SetRecordEffectId},\ + {"SetRecordEffectAttribute", RecordsDynamicFunctions::SetRecordEffectAttribute},\ + {"SetRecordEffectSkill", RecordsDynamicFunctions::SetRecordEffectSkill},\ + {"SetRecordEffectRangeType", RecordsDynamicFunctions::SetRecordEffectRangeType},\ + {"SetRecordEffectArea", RecordsDynamicFunctions::SetRecordEffectArea},\ + {"SetRecordEffectDuration", RecordsDynamicFunctions::SetRecordEffectDuration},\ + {"SetRecordEffectMagnitudeMax", RecordsDynamicFunctions::SetRecordEffectMagnitudeMax},\ + {"SetRecordEffectMagnitudeMin", RecordsDynamicFunctions::SetRecordEffectMagnitudeMin},\ + \ + {"SetRecordBodyPartType", RecordsDynamicFunctions::SetRecordBodyPartType},\ + {"SetRecordBodyPartIdForMale", RecordsDynamicFunctions::SetRecordBodyPartIdForMale},\ + {"SetRecordBodyPartIdForFemale", RecordsDynamicFunctions::SetRecordBodyPartIdForFemale},\ + \ + {"SetRecordInventoryItemId", RecordsDynamicFunctions::SetRecordInventoryItemId},\ + {"SetRecordInventoryItemCount", RecordsDynamicFunctions::SetRecordInventoryItemCount},\ + \ + {"AddRecord", RecordsDynamicFunctions::AddRecord},\ + {"AddRecordEffect", RecordsDynamicFunctions::AddRecordEffect},\ + {"AddRecordBodyPart", RecordsDynamicFunctions::AddRecordBodyPart},\ + {"AddRecordInventoryItem", RecordsDynamicFunctions::AddRecordInventoryItem},\ + \ + {"SendRecordDynamic", RecordsDynamicFunctions::SendRecordDynamic} + +class RecordsDynamicFunctions +{ +public: + + /** + * \brief Clear the data from the records stored on the server. + * + * \return void + */ + static void ClearRecords() noexcept; + + /** + * \brief Get the type of records in the read worldstate's dynamic records. + * + * \return The type of records (0 for SPELL, 1 for POTION, 2 for ENCHANTMENT, + * 3 for NPC). + */ + static unsigned short GetRecordType() noexcept; + + /** + * \brief Get the number of records in the read worldstate's dynamic records. + * + * \return The number of records. + */ + static unsigned int GetRecordCount() noexcept; + + /** + * \brief Get the number of effects for the record at a certain index in the read + * worldstate's current records. + * + * \param recordIndex The index of the record. + * \return The number of effects. + */ + static unsigned int GetRecordEffectCount(unsigned int recordIndex) noexcept; + + /** + * \brief Get the id of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The id of the record. + */ + static const char *GetRecordId(unsigned int index) noexcept; + + /** + * \brief Get the base id (i.e. the id this record should inherit default + * values from) of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The base id of the record. + */ + static const char *GetRecordBaseId(unsigned int index) noexcept; + + /** + * \brief Get the subtype of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The type of the record. + */ + static int GetRecordSubtype(unsigned int index) noexcept; + + /** + * \brief Get the name of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The name of the record. + */ + static const char *GetRecordName(unsigned int index) noexcept; + + /** + * \brief Get the model of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The model of the record. + */ + static const char *GetRecordModel(unsigned int index) noexcept; + + /** + * \brief Get the icon of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The icon of the record. + */ + static const char *GetRecordIcon(unsigned int index) noexcept; + + /** + * \brief Get the script of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The script of the record. + */ + static const char *GetRecordScript(unsigned int index) noexcept; + + /** + * \brief Get the enchantment id of the record at a certain index in the read + * worldstate's dynamic records of the current type. + * + * \param index The index of the record. + * \return The enchantment id of the record. + */ + static const char *GetRecordEnchantmentId(unsigned int index) noexcept; + + /** + * \brief Get the enchantment charge of the record at a certain index in + * the read worldstate's dynamic records of the current type. + * + * \param index The index of the record. + * \return The enchantment charge of the record. + */ + static int GetRecordEnchantmentCharge(unsigned int index) noexcept; + + /** + * \brief Get the auto-calculation flag value of the record at a certain index in + * the read worldstate's dynamic records of the current type. + * + * \param index The index of the record. + * \return The auto-calculation flag value of the record. + */ + static int GetRecordAutoCalc(unsigned int index) noexcept; + + /** + * \brief Get the charge of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The charge of the record. + */ + static int GetRecordCharge(unsigned int index) noexcept; + + /** + * \brief Get the cost of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The cost of the record. + */ + static int GetRecordCost(unsigned int index) noexcept; + + /** + * \brief Get the flags of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The flags of the spell as an integer. + */ + static int GetRecordFlags(unsigned int index) noexcept; + + /** + * \brief Get the value of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The value of the record. + */ + static int GetRecordValue(unsigned int index) noexcept; + + /** + * \brief Get the weight of the record at a certain index in the read worldstate's + * dynamic records of the current type. + * + * \param index The index of the record. + * \return The weight of the record. + */ + static double GetRecordWeight(unsigned int index) noexcept; + + /** + * \brief Get the ID of the effect at a certain index in the read worldstate's + * current records. + * + * \param recordIndex The index of the record. + * \param effectIndex The index of the effect. + * \return The ID of the effect. + */ + static unsigned int GetRecordEffectId(unsigned int recordIndex, unsigned int effectIndex) noexcept; + + /** + * \brief Get the ID of the attribute modified by the effect at a certain index in the + * read worldstate's current records. + * + * \param recordIndex The index of the record. + * \param effectIndex The index of the effect. + * \return The attribute ID for the effect. + */ + static int GetRecordEffectAttribute(unsigned int recordIndex, unsigned int effectIndex) noexcept; + + /** + * \brief Get the ID of the skill modified by the effect at a certain index in the + * read worldstate's current records. + * + * \param recordIndex The index of the record. + * \param effectIndex The index of the effect. + * \return The skill ID for the effect. + */ + static int GetRecordEffectSkill(unsigned int recordIndex, unsigned int effectIndex) noexcept; + + /** + * \brief Get the range type of the effect at a certain index in the read worldstate's + * current records (0 for self, 1 for touch, 2 for target). + * + * \param recordIndex The index of the record. + * \param effectIndex The index of the effect. + * \return The range of the effect. + */ + static unsigned int GetRecordEffectRangeType(unsigned int recordIndex, unsigned int effectIndex) noexcept; + + /** + * \brief Get the area of the effect at a certain index in the read worldstate's current + * records. + * + * \param recordIndex The index of the record. + * \param effectIndex The index of the effect. + * \return The area of the effect. + */ + static int GetRecordEffectArea(unsigned int recordIndex, unsigned int effectIndex) noexcept; + + /** + * \brief Get the duration of the effect at a certain index in the read worldstate's current + * records. + * + * \param recordIndex The index of the record. + * \param effectIndex The index of the effect. + * \return The duration of the effect. + */ + static int GetRecordEffectDuration(unsigned int recordIndex, unsigned int effectIndex) noexcept; + + /** + * \brief Get the maximum magnitude of the effect at a certain index in the read + * worldstate's current records. + * + * \param recordIndex The index of the record. + * \param effectIndex The index of the effect. + * \return The maximum magnitude of the effect. + */ + static int GetRecordEffectMagnitudeMax(unsigned int recordIndex, unsigned int effectIndex) noexcept; + + /** + * \brief Get the minimum magnitude of the effect at a certain index in the read + * worldstate's current records. + * + * \param recordIndex The index of the record. + * \param effectIndex The index of the effect. + * \return The minimum magnitude of the effect. + */ + static int GetRecordEffectMagnitudeMin(unsigned int recordIndex, unsigned int effectIndex) noexcept; + + /** + * \brief Set which type of temporary records stored on the server should have + * their data changed via setter functions. + * + * \param type The type of records. + * \return void + */ + static void SetRecordType(unsigned int type) noexcept; + + /** + * \brief Set the id of the temporary record stored on the server for the + * currently specified record type. + * + * \param id The id of the record. + * \return void + */ + static void SetRecordId(const char* id) noexcept; + + /** + * \brief Set the base id (i.e. the id this record should inherit default + * values from) of the temporary record stored on the server for the + * currently specified record type. + * + * \param baseId The baseId of the record. + * \return void + */ + static void SetRecordBaseId(const char* baseId) noexcept; + + /** + * \brief Set the inventory base id (i.e. the id this record should inherit + * its inventory contents from) of the temporary record stored on the server for + * the currently specified record type. + * + * \param inventoryBaseId The inventoryBaseId of the record. + * \return void + */ + static void SetRecordInventoryBaseId(const char* inventoryBaseId) noexcept; + + /** + * \brief Set the subtype of the temporary record stored on the server for + * the currently specified record type. + * + * \param type The spell type. + * \return void + */ + static void SetRecordSubtype(unsigned int subtype) noexcept; + + /** + * \brief Set the name of the temporary record stored on the server for the + * currently specified record type. + * + * \param name The name of the record. + * \return void + */ + static void SetRecordName(const char* name) noexcept; + + /** + * \brief Set the model of the temporary record stored on the server for the + * currently specified record type. + * + * \param model The model of the record. + * \return void + */ + static void SetRecordModel(const char* model) noexcept; + + /** + * \brief Set the icon of the temporary record stored on the server for the + * currently specified record type. + * + * \param icon The icon of the record. + * \return void + */ + static void SetRecordIcon(const char* icon) noexcept; + + /** + * \brief Set the script of the temporary record stored on the server for the + * currently specified record type. + * + * \param script The script of the record. + * \return void + */ + static void SetRecordScript(const char* script) noexcept; + + /** + * \brief Set the enchantment id of the temporary record stored on the server + * for the currently specified record type. + * + * \param enchantmentId The enchantment id of the record. + * \return void + */ + static void SetRecordEnchantmentId(const char* enchantmentId) noexcept; + + /** + * \brief Set the enchantment charge of the temporary record stored on the server + * for the currently specified record type. + * + * \param enchantmentCharge The enchantmentCharge of the record. + * \return void + */ + static void SetRecordEnchantmentCharge(int enchantmentCharge) noexcept; + + /** + * \brief Set the auto-calculation flag value of the temporary record stored + * on the server for the currently specified record type. + * + * \param autoCalc The auto-calculation flag value of the record. + * \return void + */ + static void SetRecordAutoCalc(int autoCalc) noexcept; + + /** + * \brief Set the charge of the temporary record stored on the server for the + * currently specified record type. + * + * \param charge The charge of the record. + * \return void + */ + static void SetRecordCharge(int charge) noexcept; + + /** + * \brief Set the cost of the temporary record stored on the server for the + * currently specified record type. + * + * \param cost The cost of the record. + * \return void + */ + static void SetRecordCost(int cost) noexcept; + + /** + * \brief Set the flags of the temporary record stored on the server for the + * currently specified record type. + * + * \param flags The flags of the record. + * \return void + */ + static void SetRecordFlags(int flags) noexcept; + + /** + * \brief Set the value of the temporary record stored on the server for the + * currently specified record type. + * + * \param value The value of the record. + * \return void + */ + static void SetRecordValue(int value) noexcept; + + /** + * \brief Set the weight of the temporary record stored on the server for the + * currently specified record type. + * + * \param weight The weight of the record. + * \return void + */ + static void SetRecordWeight(double weight) noexcept; + + /** + * \brief Set the armor rating of the temporary record stored on the server + * for the currently specified record type. + * + * \param armorRating The armor rating of the record. + * \return void + */ + static void SetRecordArmorRating(int armorRating) noexcept; + + /** + * \brief Set the health of the temporary record stored on the server for the + * currently specified record type. + * + * \param health The health of the record. + * \return void + */ + static void SetRecordHealth(int health) noexcept; + + /** + * \brief Set the chop damage of the temporary record stored on the server for the + * currently specified record type. + * + * \param minDamage The minimum damage of the record. + * \param maxDamage The maximum damage of the record. + * \return void + */ + static void SetRecordDamageChop(unsigned int minDamage, unsigned int maxDamage) noexcept; + + /** + * \brief Set the slash damage of the temporary record stored on the server for the + * currently specified record type. + * + * \param minDamage The minimum damage of the record. + * \param maxDamage The maximum damage of the record. + * \return void + */ + static void SetRecordDamageSlash(unsigned int minDamage, unsigned int maxDamage) noexcept; + + /** + * \brief Set the thrust damage of the temporary record stored on the server for the + * currently specified record type. + * + * \param minDamage The minimum damage of the record. + * \param maxDamage The maximum damage of the record. + * \return void + */ + static void SetRecordDamageThrust(unsigned int minDamage, unsigned int maxDamage) noexcept; + + /** + * \brief Set the reach of the temporary record stored on the server for the + * currently specified record type. + * + * \param reach The reach of the record. + * \return void + */ + static void SetRecordReach(double reach) noexcept; + + /** + * \brief Set the speed of the temporary record stored on the server for the + * currently specified record type. + * + * \param speed The speed of the record. + * \return void + */ + static void SetRecordSpeed(double speed) noexcept; + + /** + * \brief Set whether the temporary record stored on the server for the + * currently specified record type is a key. + * + * Note: This is only applicable to Miscellaneous records. + * + * \param keyState Whether the record is a key. + * \return void + */ + static void SetRecordKeyState(bool keyState) noexcept; + + /** + * \brief Set whether the temporary record stored on the server for the + * currently specified record type is a scroll. + * + * Note: This is only applicable to Book records. + * + * \param scrollState Whether the record is a scroll. + * \return void + */ + static void SetRecordScrollState(bool scrollState) noexcept; + + /** + * \brief Set the skill ID of the temporary record stored on the server for the + * currently specified record type. + * + * \param skillId The skill ID of the record. + * \return void + */ + static void SetRecordSkillId(int skillId) noexcept; + + /** + * \brief Set the text of the temporary record stored on the server for the + * currently specified record type. + * + * \param text The text of the record. + * \return void + */ + static void SetRecordText(const char* text) noexcept; + + /** + * \brief Set the hair of the temporary record stored on the server for the + * currently specified record type. + * + * \param hair The hair of the record. + * \return void + */ + static void SetRecordHair(const char* hair) noexcept; + + /** + * \brief Set the head of the temporary record stored on the server for the + * currently specified record type. + * + * \param hair The head of the record. + * \return void + */ + static void SetRecordHead(const char* head) noexcept; + + /** + * \brief Set the gender of the temporary record stored on the server for the + * currently specified record type (0 for female, 1 for male). + * + * \param hair The race of the record. + * \return void + */ + static void SetRecordGender(unsigned int gender) noexcept; + + /** + * \brief Set the race of the temporary record stored on the server for the + * currently specified record type. + * + * \param hair The race of the record. + * \return void + */ + static void SetRecordRace(const char* race) noexcept; + + /** + * \brief Set the character class of the temporary record stored on the server + * for the currently specified record type. + * + * \param hair The character class of the record. + * \return void + */ + static void SetRecordClass(const char* charClass) noexcept; + + /** + * \brief Set the faction of the temporary record stored on the server for the + * currently specified record type. + * + * \param faction The faction of the record. + * \return void + */ + static void SetRecordFaction(const char* faction) noexcept; + + /** + * \brief Set the level of the temporary record stored on the server for the + * currently specified record type. + * + * \param value The level of the record. + * \return void + */ + static void SetRecordLevel(int level) noexcept; + + /** + * \brief Set the id of the record at a certain index in the records stored on the server. + * + * When resending a received RecordsDynamic packet, this allows you to set the server-generated + * id of a record without having to clear and recreate the packet. + * + * \param index The index of the record. + * \param id The id of the record. + * \return void + */ + static void SetRecordIdByIndex(unsigned int index, const char* id) noexcept; + + /** + * \brief Set the enchantment id of the record at a certain index in the records stored on + * the server. + * + * When resending a received RecordsDynamic packet, this allows you to set the server-generated + * enchantment id of a record without having to clear and recreate the packet. + * + * \param index The index of the record. + * \param enchantmentId The enchantment id of the record. + * \return void + */ + static void SetRecordEnchantmentIdByIndex(unsigned int index, const char* enchantmentId) noexcept; + + /** + * \brief Set the ID of the temporary effect stored on the server. + * + * \param effectId The ID of the effect. + * \return void + */ + static void SetRecordEffectId(unsigned int effectId) noexcept; + + /** + * \brief Set the ID of the attribute modified by the temporary effect stored on + * the server. + * + * \param attributeId The ID of the attribute. + * \return void + */ + static void SetRecordEffectAttribute(int attributeId) noexcept; + + /** + * \brief Set the ID of the skill modified by the temporary effect stored on the + * server. + * + * \param skillId The ID of the skill. + * \return void + */ + static void SetRecordEffectSkill(int skillId) noexcept; + + /** + * \brief Set the range type of the temporary effect stored on the server (0 for + * self, 1 for touch, 2 for target). + * + * \param rangeType The range type of the effect. + * \return void + */ + static void SetRecordEffectRangeType(unsigned int rangeType) noexcept; + + /** + * \brief Set the area of the temporary effect stored on the server. + * + * \param area The area of the effect. + * \return void + */ + static void SetRecordEffectArea(int area) noexcept; + + /** + * \brief Set the duration of the temporary effect stored on the server. + * + * \param duration The duration of the effect. + * \return void + */ + static void SetRecordEffectDuration(int duration) noexcept; + + /** + * \brief Set the maximum magnitude of the temporary effect stored on the server. + * + * \param magnitudeMax The maximum magnitude of the effect. + * \return void + */ + static void SetRecordEffectMagnitudeMax(int magnitudeMax) noexcept; + + /** + * \brief Set the minimum magnitude of the temporary effect stored on the server. + * + * \param magnitudeMin The minimum magnitude of the effect. + * \return void + */ + static void SetRecordEffectMagnitudeMin(int magnitudeMin) noexcept; + + /** + * \brief Set the type of the temporary body part stored on the server. + * + * \param partType The type of the body part. + * \return void + */ + static void SetRecordBodyPartType(unsigned int partType) noexcept; + + /** + * \brief Set the id of the male version of the temporary body part stored on the + * server. + * + * \param partId The id of the body part. + * \return void + */ + static void SetRecordBodyPartIdForMale(const char* partId) noexcept; + + /** + * \brief Set the id of the female version of the temporary body part stored on the + * server. + * + * \param partId The id of the body part. + * \return void + */ + static void SetRecordBodyPartIdForFemale(const char* partId) noexcept; + + /** + * \brief Set the id of the of the temporary inventory item stored on the server. + * + * \param partId The id of the inventory item. + * \return void + */ + static void SetRecordInventoryItemId(const char* itemId) noexcept; + + /** + * \brief Set the count of the of the temporary inventory item stored on the server. + * + * \param count The count of the inventory item. + * \return void + */ + static void SetRecordInventoryItemCount(unsigned int count) noexcept; + + /** + * \brief Add a copy of the server's temporary record of the current specified + * type to the stored records. + * + * In the process, the server's temporary record will automatically be cleared + * so a new one can be set up. + * + * \return void + */ + static void AddRecord() noexcept; + + /** + * \brief Add a copy of the server's temporary effect to the temporary record + * of the current specified type. + * + * In the process, the server's temporary effect will automatically be cleared + * so a new one can be set up. + * + * \return void + */ + static void AddRecordEffect() noexcept; + + /** + * \brief Add a copy of the server's temporary body part to the temporary record + * of the current specified type. + * + * In the process, the server's temporary body part will automatically be cleared + * so a new one can be set up. + * + * \return void + */ + static void AddRecordBodyPart() noexcept; + + /** + * \brief Add a copy of the server's temporary inventory item to the temporary record + * of the current specified type. + * + * In the process, the server's temporary inventory item will automatically be cleared + * so a new one can be set up. + * + * Note: Any items added this way will be ignored if the record already has a valid + * inventoryBaseId. + * + * \return void + */ + static void AddRecordInventoryItem() noexcept; + + /** + * \brief Send a RecordDynamic packet with the current specified record type. + * + * \param pid The player ID attached to the packet. + * \param sendToOtherPlayers Whether this packet should be sent to players other than the + * player attached to the packet (false by default). + * \param skipAttachedPlayer Whether the packet should skip being sent to the player attached + * to the packet (false by default). + * \return void + */ + static void SendRecordDynamic(unsigned short pid, bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept; + +}; + +#endif //OPENMW_RECORDSDYNAMICAPI_HPP diff --git a/apps/openmw-mp/Script/ScriptFunctions.hpp b/apps/openmw-mp/Script/ScriptFunctions.hpp index f69b2ff77..e5d8e799c 100644 --- a/apps/openmw-mp/Script/ScriptFunctions.hpp +++ b/apps/openmw-mp/Script/ScriptFunctions.hpp @@ -15,6 +15,7 @@ #include