From 18e2a146456a42718f01625ed269f7fc2eecefa8 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 4 Aug 2019 17:53:18 +0300 Subject: [PATCH] [General] Implement tool-related records for RecordDynamic packets --- .../Script/Functions/RecordsDynamic.cpp | 138 +++++++++ .../Script/Functions/RecordsDynamic.hpp | 20 ++ apps/openmw/mwmp/RecordHelper.cpp | 292 ++++++++++++++++++ apps/openmw/mwmp/RecordHelper.hpp | 12 + apps/openmw/mwmp/Worldstate.cpp | 48 +++ components/openmw-mp/Base/BaseWorldstate.hpp | 44 ++- .../Worldstate/PacketRecordDynamic.cpp | 140 +++++++++ 7 files changed, 693 insertions(+), 1 deletion(-) diff --git a/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp b/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp index bf4e02689..437019eb6 100644 --- a/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp +++ b/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp @@ -27,6 +27,10 @@ DoorRecord tempDoor; ActivatorRecord tempActivator; StaticRecord tempStatic; IngredientRecord tempIngredient; +ApparatusRecord tempApparatus; +LockpickRecord tempLockpick; +ProbeRecord tempProbe; +RepairRecord tempRepair; BaseOverrides tempOverrides; @@ -68,6 +72,10 @@ void RecordsDynamicFunctions::ClearRecords() noexcept WorldstateFunctions::writeWorldstate.activatorRecords.clear(); WorldstateFunctions::writeWorldstate.staticRecords.clear(); WorldstateFunctions::writeWorldstate.ingredientRecords.clear(); + WorldstateFunctions::writeWorldstate.apparatusRecords.clear(); + WorldstateFunctions::writeWorldstate.lockpickRecords.clear(); + WorldstateFunctions::writeWorldstate.probeRecords.clear(); + WorldstateFunctions::writeWorldstate.repairRecords.clear(); } unsigned short RecordsDynamicFunctions::GetRecordType() noexcept @@ -358,6 +366,14 @@ void RecordsDynamicFunctions::SetRecordId(const char* id) noexcept tempStatic.data.mId = id; else if (writeRecordsType == mwmp::RECORD_TYPE::INGREDIENT) tempIngredient.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + tempApparatus.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + tempLockpick.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + tempProbe.data.mId = id; + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + tempRepair.data.mId = id; else LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set id for record type %i which lacks that property", writeRecordsType); } @@ -396,6 +412,14 @@ void RecordsDynamicFunctions::SetRecordBaseId(const char* baseId) noexcept tempStatic.baseId = baseId; else if (writeRecordsType == mwmp::RECORD_TYPE::INGREDIENT) tempIngredient.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + tempApparatus.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + tempLockpick.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + tempProbe.baseId = baseId; + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + tempRepair.baseId = baseId; else LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set baseId for record type %i which lacks that property", writeRecordsType); } @@ -428,6 +452,8 @@ void RecordsDynamicFunctions::SetRecordSubtype(unsigned int subtype) noexcept tempClothing.data.mData.mType = subtype; else if (writeRecordsType == mwmp::RECORD_TYPE::WEAPON) tempWeapon.data.mData.mType = subtype; + else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + tempApparatus.data.mData.mType = subtype; else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set subtype for record type %i which lacks that property", writeRecordsType); @@ -467,6 +493,14 @@ void RecordsDynamicFunctions::SetRecordName(const char* name) noexcept tempActivator.data.mName = name; else if (writeRecordsType == mwmp::RECORD_TYPE::INGREDIENT) tempIngredient.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + tempApparatus.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + tempLockpick.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + tempProbe.data.mName = name; + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + tempRepair.data.mName = name; else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set name for record type %i which lacks that property", writeRecordsType); @@ -506,6 +540,14 @@ void RecordsDynamicFunctions::SetRecordModel(const char* model) noexcept tempStatic.data.mModel = model; else if (writeRecordsType == mwmp::RECORD_TYPE::INGREDIENT) tempIngredient.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + tempApparatus.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + tempLockpick.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + tempProbe.data.mModel = model; + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + tempRepair.data.mModel = model; else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set model for record type %i which lacks that property", writeRecordsType); @@ -533,6 +575,14 @@ void RecordsDynamicFunctions::SetRecordIcon(const char* icon) noexcept tempWeapon.data.mIcon = icon; else if (writeRecordsType == mwmp::RECORD_TYPE::INGREDIENT) tempIngredient.data.mIcon = icon; + else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + tempApparatus.data.mIcon = icon; + else if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + tempLockpick.data.mIcon = icon; + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + tempProbe.data.mIcon = icon; + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + tempRepair.data.mIcon = icon; else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set icon for record type %i which lacks that property", writeRecordsType); @@ -570,6 +620,14 @@ void RecordsDynamicFunctions::SetRecordScript(const char* script) noexcept tempActivator.data.mScript = script; else if (writeRecordsType == mwmp::RECORD_TYPE::INGREDIENT) tempIngredient.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + tempApparatus.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + tempLockpick.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + tempProbe.data.mScript = script; + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + tempRepair.data.mScript = script; else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set script for record type %i which lacks that property", writeRecordsType); @@ -724,6 +782,14 @@ void RecordsDynamicFunctions::SetRecordValue(int value) noexcept tempWeapon.data.mData.mValue = value; else if (writeRecordsType == mwmp::RECORD_TYPE::INGREDIENT) tempIngredient.data.mData.mValue = value; + else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + tempApparatus.data.mData.mValue = value; + else if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + tempLockpick.data.mData.mValue = value; + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + tempProbe.data.mData.mValue = value; + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + tempRepair.data.mData.mValue = value; else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set value for record type %i which lacks that property", writeRecordsType); @@ -753,6 +819,14 @@ void RecordsDynamicFunctions::SetRecordWeight(double weight) noexcept tempContainer.data.mWeight = weight; else if (writeRecordsType == mwmp::RECORD_TYPE::INGREDIENT) tempIngredient.data.mData.mWeight = weight; + else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + tempApparatus.data.mData.mWeight = weight; + else if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + tempLockpick.data.mData.mWeight = weight; + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + tempProbe.data.mData.mWeight = weight; + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + tempRepair.data.mData.mWeight = weight; else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set weight for record type %i which lacks that property", writeRecordsType); @@ -762,6 +836,46 @@ void RecordsDynamicFunctions::SetRecordWeight(double weight) noexcept tempOverrides.hasWeight = true; } +void RecordsDynamicFunctions::SetRecordQuality(double quality) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + tempApparatus.data.mData.mQuality = quality; + else if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + tempLockpick.data.mData.mQuality = quality; + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + tempProbe.data.mData.mQuality = quality; + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + tempRepair.data.mData.mQuality = quality; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set quality for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasQuality = true; +} + +void RecordsDynamicFunctions::SetRecordUses(int uses) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + tempLockpick.data.mData.mUses = uses; + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + tempProbe.data.mData.mUses = uses; + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + tempRepair.data.mData.mUses = uses; + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Tried to set value for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasUses = true; +} + void RecordsDynamicFunctions::SetRecordArmorRating(int armorRating) noexcept { unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; @@ -1319,6 +1433,30 @@ void RecordsDynamicFunctions::AddRecord() noexcept WorldstateFunctions::writeWorldstate.ingredientRecords.push_back(tempIngredient); tempIngredient = {}; } + else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) + { + tempApparatus.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.apparatusRecords.push_back(tempApparatus); + tempApparatus = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::LOCKPICK) + { + tempLockpick.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.lockpickRecords.push_back(tempLockpick); + tempLockpick = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::PROBE) + { + tempProbe.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.probeRecords.push_back(tempProbe); + tempProbe = {}; + } + else if (writeRecordsType == mwmp::RECORD_TYPE::REPAIR) + { + tempRepair.baseOverrides = tempOverrides; + WorldstateFunctions::writeWorldstate.repairRecords.push_back(tempRepair); + tempRepair = {}; + } effectCount = 0; tempOverrides = {}; diff --git a/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp b/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp index 0fc633549..1b56a28a4 100644 --- a/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp +++ b/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp @@ -57,6 +57,8 @@ {"SetRecordFlags", RecordsDynamicFunctions::SetRecordFlags},\ {"SetRecordValue", RecordsDynamicFunctions::SetRecordValue},\ {"SetRecordWeight", RecordsDynamicFunctions::SetRecordWeight},\ + {"SetRecordQuality", RecordsDynamicFunctions::SetRecordQuality},\ + {"SetRecordUses", RecordsDynamicFunctions::SetRecordUses},\ \ {"SetRecordArmorRating", RecordsDynamicFunctions::SetRecordArmorRating},\ {"SetRecordHealth", RecordsDynamicFunctions::SetRecordHealth},\ @@ -519,6 +521,24 @@ public: */ static void SetRecordWeight(double weight) noexcept; + /** + * \brief Set the item quality 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 SetRecordQuality(double quality) noexcept; + + /** + * \brief Set the number of uses of the temporary record stored on the server for the + * currently specified record type. + * + * \param uses The number of uses of the record. + * \return void + */ + static void SetRecordUses(int uses) noexcept; + /** * \brief Set the armor rating of the temporary record stored on the server * for the currently specified record type. diff --git a/apps/openmw/mwmp/RecordHelper.cpp b/apps/openmw/mwmp/RecordHelper.cpp index 2c161725b..9dbcb8884 100644 --- a/apps/openmw/mwmp/RecordHelper.cpp +++ b/apps/openmw/mwmp/RecordHelper.cpp @@ -125,6 +125,34 @@ bool RecordHelper::doesIngredientRecordExist(const std::string& id) return world->getStore().get().search(id); } +bool RecordHelper::doesApparatusRecordExist(const std::string& id) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + return world->getStore().get().search(id); +} + +bool RecordHelper::doesLockpickRecordExist(const std::string& id) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + return world->getStore().get().search(id); +} + +bool RecordHelper::doesProbeRecordExist(const std::string& id) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + return world->getStore().get().search(id); +} + +bool RecordHelper::doesRepairRecordExist(const std::string& id) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + return world->getStore().get().search(id); +} + std::string RecordHelper::createCreatureRecord(const ESM::Creature& record) { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1128,6 +1156,242 @@ void RecordHelper::overrideIngredientRecord(const mwmp::IngredientRecord& record world->updatePtrsWithRefId(recordData.mId); } +void RecordHelper::overrideApparatusRecord(const mwmp::ApparatusRecord& record) +{ + const ESM::Apparatus &recordData = record.data; + + if (recordData.mId.empty()) + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided"); + return; + } + + bool isExistingId = doesApparatusRecordExist(recordData.mId); + MWBase::World *world = MWBase::Environment::get().getWorld(); + + if (record.baseId.empty()) + { + world->getModifiableStore().overrideRecord(recordData); + } + else if (doesApparatusRecordExist(record.baseId)) + { + const ESM::Apparatus *baseData = world->getStore().get().search(record.baseId); + ESM::Apparatus finalData = *baseData; + finalData.mId = recordData.mId; + + if (record.baseOverrides.hasName) + finalData.mName = recordData.mName; + + if (record.baseOverrides.hasModel) + finalData.mModel = recordData.mModel; + + if (record.baseOverrides.hasIcon) + finalData.mIcon = recordData.mIcon; + + if (record.baseOverrides.hasSubtype) + finalData.mData.mType = recordData.mData.mType; + + if (record.baseOverrides.hasWeight) + finalData.mData.mWeight = recordData.mData.mWeight; + + if (record.baseOverrides.hasValue) + finalData.mData.mValue = recordData.mData.mValue; + + if (record.baseOverrides.hasQuality) + finalData.mData.mQuality = recordData.mData.mQuality; + + if (record.baseOverrides.hasScript) + finalData.mScript = recordData.mScript; + + world->getModifiableStore().overrideRecord(finalData); + } + else + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str()); + return; + } + + if (isExistingId) + world->updatePtrsWithRefId(recordData.mId); +} + +void RecordHelper::overrideLockpickRecord(const mwmp::LockpickRecord& record) +{ + const ESM::Lockpick &recordData = record.data; + + if (recordData.mId.empty()) + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided"); + return; + } + + bool isExistingId = doesLockpickRecordExist(recordData.mId); + MWBase::World *world = MWBase::Environment::get().getWorld(); + + if (record.baseId.empty()) + { + world->getModifiableStore().overrideRecord(recordData); + } + else if (doesLockpickRecordExist(record.baseId)) + { + const ESM::Lockpick *baseData = world->getStore().get().search(record.baseId); + ESM::Lockpick finalData = *baseData; + finalData.mId = recordData.mId; + + if (record.baseOverrides.hasName) + finalData.mName = recordData.mName; + + if (record.baseOverrides.hasModel) + finalData.mModel = recordData.mModel; + + if (record.baseOverrides.hasIcon) + finalData.mIcon = recordData.mIcon; + + if (record.baseOverrides.hasWeight) + finalData.mData.mWeight = recordData.mData.mWeight; + + if (record.baseOverrides.hasValue) + finalData.mData.mValue = recordData.mData.mValue; + + if (record.baseOverrides.hasQuality) + finalData.mData.mQuality = recordData.mData.mQuality; + + if (record.baseOverrides.hasUses) + finalData.mData.mUses = recordData.mData.mUses; + + if (record.baseOverrides.hasScript) + finalData.mScript = recordData.mScript; + + world->getModifiableStore().overrideRecord(finalData); + } + else + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str()); + return; + } + + if (isExistingId) + world->updatePtrsWithRefId(recordData.mId); +} + +void RecordHelper::overrideProbeRecord(const mwmp::ProbeRecord& record) +{ + const ESM::Probe &recordData = record.data; + + if (recordData.mId.empty()) + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided"); + return; + } + + bool isExistingId = doesProbeRecordExist(recordData.mId); + MWBase::World *world = MWBase::Environment::get().getWorld(); + + if (record.baseId.empty()) + { + world->getModifiableStore().overrideRecord(recordData); + } + else if (doesProbeRecordExist(record.baseId)) + { + const ESM::Probe *baseData = world->getStore().get().search(record.baseId); + ESM::Probe finalData = *baseData; + finalData.mId = recordData.mId; + + if (record.baseOverrides.hasName) + finalData.mName = recordData.mName; + + if (record.baseOverrides.hasModel) + finalData.mModel = recordData.mModel; + + if (record.baseOverrides.hasIcon) + finalData.mIcon = recordData.mIcon; + + if (record.baseOverrides.hasWeight) + finalData.mData.mWeight = recordData.mData.mWeight; + + if (record.baseOverrides.hasValue) + finalData.mData.mValue = recordData.mData.mValue; + + if (record.baseOverrides.hasQuality) + finalData.mData.mQuality = recordData.mData.mQuality; + + if (record.baseOverrides.hasUses) + finalData.mData.mUses = recordData.mData.mUses; + + if (record.baseOverrides.hasScript) + finalData.mScript = recordData.mScript; + + world->getModifiableStore().overrideRecord(finalData); + } + else + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str()); + return; + } + + if (isExistingId) + world->updatePtrsWithRefId(recordData.mId); +} + +void RecordHelper::overrideRepairRecord(const mwmp::RepairRecord& record) +{ + const ESM::Repair &recordData = record.data; + + if (recordData.mId.empty()) + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided"); + return; + } + + bool isExistingId = doesRepairRecordExist(recordData.mId); + MWBase::World *world = MWBase::Environment::get().getWorld(); + + if (record.baseId.empty()) + { + world->getModifiableStore().overrideRecord(recordData); + } + else if (doesRepairRecordExist(record.baseId)) + { + const ESM::Repair *baseData = world->getStore().get().search(record.baseId); + ESM::Repair finalData = *baseData; + finalData.mId = recordData.mId; + + if (record.baseOverrides.hasName) + finalData.mName = recordData.mName; + + if (record.baseOverrides.hasModel) + finalData.mModel = recordData.mModel; + + if (record.baseOverrides.hasIcon) + finalData.mIcon = recordData.mIcon; + + if (record.baseOverrides.hasWeight) + finalData.mData.mWeight = recordData.mData.mWeight; + + if (record.baseOverrides.hasValue) + finalData.mData.mValue = recordData.mData.mValue; + + if (record.baseOverrides.hasQuality) + finalData.mData.mQuality = recordData.mData.mQuality; + + if (record.baseOverrides.hasUses) + finalData.mData.mUses = recordData.mData.mUses; + + if (record.baseOverrides.hasScript) + finalData.mScript = recordData.mScript; + + world->getModifiableStore().overrideRecord(finalData); + } + else + { + LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str()); + return; + } + + if (isExistingId) + world->updatePtrsWithRefId(recordData.mId); +} + void RecordHelper::overrideCreatureRecord(const ESM::Creature& record) { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1232,3 +1496,31 @@ void RecordHelper::overrideIngredientRecord(const ESM::Ingredient& record) world->getModifiableStore().overrideRecord(record); } + +void RecordHelper::overrideApparatusRecord(const ESM::Apparatus& record) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + world->getModifiableStore().overrideRecord(record); +} + +void RecordHelper::overrideLockpickRecord(const ESM::Lockpick& record) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + world->getModifiableStore().overrideRecord(record); +} + +void RecordHelper::overrideProbeRecord(const ESM::Probe& record) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + world->getModifiableStore().overrideRecord(record); +} + +void RecordHelper::overrideRepairRecord(const ESM::Repair& record) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + world->getModifiableStore().overrideRecord(record); +} diff --git a/apps/openmw/mwmp/RecordHelper.hpp b/apps/openmw/mwmp/RecordHelper.hpp index b8cd88420..9a7677463 100644 --- a/apps/openmw/mwmp/RecordHelper.hpp +++ b/apps/openmw/mwmp/RecordHelper.hpp @@ -31,6 +31,10 @@ namespace RecordHelper bool doesStaticRecordExist(const std::string& id); bool doesIngredientRecordExist(const std::string& id); + bool doesApparatusRecordExist(const std::string& id); + bool doesLockpickRecordExist(const std::string& id); + bool doesProbeRecordExist(const std::string& id); + bool doesRepairRecordExist(const std::string& id); std::string createCreatureRecord(const ESM::Creature& record); std::string createNpcRecord(const ESM::NPC& record); @@ -55,6 +59,10 @@ namespace RecordHelper void overrideStaticRecord(const mwmp::StaticRecord& record); void overrideIngredientRecord(const mwmp::IngredientRecord& record); + void overrideApparatusRecord(const mwmp::ApparatusRecord& record); + void overrideLockpickRecord(const mwmp::LockpickRecord& record); + void overrideProbeRecord(const mwmp::ProbeRecord& record); + void overrideRepairRecord(const mwmp::RepairRecord& record); void overrideCreatureRecord(const ESM::Creature& record); void overrideNpcRecord(const ESM::NPC& record); @@ -76,6 +84,10 @@ namespace RecordHelper void overrideStaticRecord(const ESM::Static& record); void overrideIngredientRecord(const ESM::Ingredient& record); + void overrideApparatusRecord(const ESM::Apparatus& record); + void overrideLockpickRecord(const ESM::Lockpick& record); + void overrideProbeRecord(const ESM::Probe& record); + void overrideRepairRecord(const ESM::Repair& record); } diff --git a/apps/openmw/mwmp/Worldstate.cpp b/apps/openmw/mwmp/Worldstate.cpp index f8408146a..8e837a302 100644 --- a/apps/openmw/mwmp/Worldstate.cpp +++ b/apps/openmw/mwmp/Worldstate.cpp @@ -218,6 +218,54 @@ void Worldstate::addRecords() RecordHelper::overrideIngredientRecord(record); } } + else if (recordsType == mwmp::RECORD_TYPE::APPARATUS) + { + for (auto &&record : apparatusRecords) + { + bool hasBaseId = !record.baseId.empty(); + + LOG_APPEND(Log::LOG_INFO, "- apparatus record %s, %s\n-- baseId is %s", record.data.mId.c_str(), record.data.mName.c_str(), + hasBaseId ? record.baseId.c_str() : "empty"); + + RecordHelper::overrideApparatusRecord(record); + } + } + else if (recordsType == mwmp::RECORD_TYPE::LOCKPICK) + { + for (auto &&record : lockpickRecords) + { + bool hasBaseId = !record.baseId.empty(); + + LOG_APPEND(Log::LOG_INFO, "- lockpick record %s, %s\n-- baseId is %s", record.data.mId.c_str(), record.data.mName.c_str(), + hasBaseId ? record.baseId.c_str() : "empty"); + + RecordHelper::overrideLockpickRecord(record); + } + } + else if (recordsType == mwmp::RECORD_TYPE::PROBE) + { + for (auto &&record : probeRecords) + { + bool hasBaseId = !record.baseId.empty(); + + LOG_APPEND(Log::LOG_INFO, "- probe record %s, %s\n-- baseId is %s", record.data.mId.c_str(), record.data.mName.c_str(), + hasBaseId ? record.baseId.c_str() : "empty"); + + RecordHelper::overrideProbeRecord(record); + } + } + else if (recordsType == mwmp::RECORD_TYPE::REPAIR) + { + for (auto &&record : repairRecords) + { + bool hasBaseId = !record.baseId.empty(); + + LOG_APPEND(Log::LOG_INFO, "- repair record %s, %s\n-- baseId is %s", record.data.mId.c_str(), record.data.mName.c_str(), + hasBaseId ? record.baseId.c_str() : "empty"); + + RecordHelper::overrideRepairRecord(record); + } + } } bool Worldstate::containsExploredMapTile(int cellX, int cellY) diff --git a/components/openmw-mp/Base/BaseWorldstate.hpp b/components/openmw-mp/Base/BaseWorldstate.hpp index f42dbd785..357112337 100644 --- a/components/openmw-mp/Base/BaseWorldstate.hpp +++ b/components/openmw-mp/Base/BaseWorldstate.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -13,8 +14,11 @@ #include #include #include +#include #include #include +#include +#include #include #include #include @@ -41,7 +45,11 @@ namespace mwmp DOOR, ACTIVATOR, STATIC, - INGREDIENT + INGREDIENT, + APPARATUS, + LOCKPICK, + PROBE, + REPAIR }; // When using an existing record as a base, this struct tracks which changes @@ -77,6 +85,8 @@ namespace mwmp bool hasFlags = false; bool hasValue = false; bool hasWeight = false; + bool hasQuality = false; + bool hasUses = false; bool hasArmorRating = false; bool hasHealth = false; @@ -113,6 +123,13 @@ namespace mwmp BaseOverrides baseOverrides; }; + struct ApparatusRecord + { + ESM::Apparatus data; + std::string baseId; + BaseOverrides baseOverrides; + }; + struct ArmorRecord { ESM::Armor data; @@ -172,6 +189,13 @@ namespace mwmp BaseOverrides baseOverrides; }; + struct LockpickRecord + { + ESM::Lockpick data; + std::string baseId; + BaseOverrides baseOverrides; + }; + struct MiscellaneousRecord { ESM::Miscellaneous data; @@ -195,6 +219,20 @@ namespace mwmp BaseOverrides baseOverrides; }; + struct ProbeRecord + { + ESM::Probe data; + std::string baseId; + BaseOverrides baseOverrides; + }; + + struct RepairRecord + { + ESM::Repair data; + std::string baseId; + BaseOverrides baseOverrides; + }; + struct SpellRecord { ESM::Spell data; @@ -271,6 +309,7 @@ namespace mwmp unsigned int recordsCount; std::vector activatorRecords; + std::vector apparatusRecords; std::vector armorRecords; std::vector bookRecords; std::vector clothingRecords; @@ -279,9 +318,12 @@ namespace mwmp std::vector doorRecords; std::vector enchantmentRecords; std::vector ingredientRecords; + std::vector lockpickRecords; std::vector miscellaneousRecords; std::vector npcRecords; std::vector potionRecords; + std::vector probeRecords; + std::vector repairRecords; std::vector spellRecords; std::vector staticRecords; std::vector weaponRecords; diff --git a/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp b/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp index 778011346..0306291e6 100644 --- a/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp +++ b/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp @@ -50,6 +50,14 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send) worldstate->recordsCount = Utils::getVectorSize(worldstate->staticRecords); else if (worldstate->recordsType == mwmp::RECORD_TYPE::INGREDIENT) worldstate->recordsCount = Utils::getVectorSize(worldstate->ingredientRecords); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::APPARATUS) + worldstate->recordsCount = Utils::getVectorSize(worldstate->apparatusRecords); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::LOCKPICK) + worldstate->recordsCount = Utils::getVectorSize(worldstate->lockpickRecords); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::PROBE) + worldstate->recordsCount = Utils::getVectorSize(worldstate->probeRecords); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::REPAIR) + worldstate->recordsCount = Utils::getVectorSize(worldstate->repairRecords); else { LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Processed invalid ID_RECORD_DYNAMIC packet about unimplemented recordsType %i", @@ -100,6 +108,14 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send) Utils::resetVector(worldstate->staticRecords, worldstate->recordsCount); else if (worldstate->recordsType == mwmp::RECORD_TYPE::INGREDIENT) Utils::resetVector(worldstate->ingredientRecords, worldstate->recordsCount); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::APPARATUS) + Utils::resetVector(worldstate->apparatusRecords, worldstate->recordsCount); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::LOCKPICK) + Utils::resetVector(worldstate->lockpickRecords, worldstate->recordsCount); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::PROBE) + Utils::resetVector(worldstate->probeRecords, worldstate->recordsCount); + else if (worldstate->recordsType == mwmp::RECORD_TYPE::REPAIR) + Utils::resetVector(worldstate->repairRecords, worldstate->recordsCount); } if (worldstate->recordsType == mwmp::RECORD_TYPE::SPELL) @@ -579,6 +595,130 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send) } } } + else if (worldstate->recordsType == mwmp::RECORD_TYPE::APPARATUS) + { + for (auto &&record : worldstate->apparatusRecords) + { + auto &recordData = record.data; + + RW(record.baseId, send, true); + RW(recordData.mId, send, true); + RW(recordData.mName, send, true); + RW(recordData.mModel, send, true); + RW(recordData.mIcon, send, true); + RW(recordData.mData.mType, send, true); + RW(recordData.mData.mWeight, send, true); + RW(recordData.mData.mValue, send, true); + RW(recordData.mData.mQuality, send, true); + RW(recordData.mScript, send, true); + + if (!record.baseId.empty()) + { + auto &&overrides = record.baseOverrides; + RW(overrides.hasName, send); + RW(overrides.hasModel, send); + RW(overrides.hasIcon, send); + RW(overrides.hasSubtype, send); + RW(overrides.hasWeight, send); + RW(overrides.hasValue, send); + RW(overrides.hasQuality, send); + RW(overrides.hasScript, send); + } + } + } + else if (worldstate->recordsType == mwmp::RECORD_TYPE::LOCKPICK) + { + for (auto &&record : worldstate->lockpickRecords) + { + auto &recordData = record.data; + + RW(record.baseId, send, true); + RW(recordData.mId, send, true); + RW(recordData.mName, send, true); + RW(recordData.mModel, send, true); + RW(recordData.mIcon, send, true); + RW(recordData.mData.mWeight, send, true); + RW(recordData.mData.mValue, send, true); + RW(recordData.mData.mQuality, send, true); + RW(recordData.mData.mUses, send, true); + RW(recordData.mScript, send, true); + + if (!record.baseId.empty()) + { + auto &&overrides = record.baseOverrides; + RW(overrides.hasName, send); + RW(overrides.hasModel, send); + RW(overrides.hasIcon, send); + RW(overrides.hasWeight, send); + RW(overrides.hasValue, send); + RW(overrides.hasQuality, send); + RW(overrides.hasUses, send); + RW(overrides.hasScript, send); + } + } + } + else if (worldstate->recordsType == mwmp::RECORD_TYPE::PROBE) + { + for (auto &&record : worldstate->probeRecords) + { + auto &recordData = record.data; + + RW(record.baseId, send, true); + RW(recordData.mId, send, true); + RW(recordData.mName, send, true); + RW(recordData.mModel, send, true); + RW(recordData.mIcon, send, true); + RW(recordData.mData.mWeight, send, true); + RW(recordData.mData.mValue, send, true); + RW(recordData.mData.mQuality, send, true); + RW(recordData.mData.mUses, send, true); + RW(recordData.mScript, send, true); + + if (!record.baseId.empty()) + { + auto &&overrides = record.baseOverrides; + RW(overrides.hasName, send); + RW(overrides.hasModel, send); + RW(overrides.hasIcon, send); + RW(overrides.hasWeight, send); + RW(overrides.hasValue, send); + RW(overrides.hasQuality, send); + RW(overrides.hasUses, send); + RW(overrides.hasScript, send); + } + } + } + else if (worldstate->recordsType == mwmp::RECORD_TYPE::REPAIR) + { + for (auto &&record : worldstate->repairRecords) + { + auto &recordData = record.data; + + RW(record.baseId, send, true); + RW(recordData.mId, send, true); + RW(recordData.mName, send, true); + RW(recordData.mModel, send, true); + RW(recordData.mIcon, send, true); + RW(recordData.mData.mWeight, send, true); + RW(recordData.mData.mValue, send, true); + RW(recordData.mData.mQuality, send, true); + RW(recordData.mData.mUses, send, true); + RW(recordData.mScript, send, true); + + if (!record.baseId.empty()) + { + auto &&overrides = record.baseOverrides; + RW(overrides.hasName, send); + RW(overrides.hasModel, send); + RW(overrides.hasIcon, send); + RW(overrides.hasWeight, send); + RW(overrides.hasValue, send); + RW(overrides.hasQuality, send); + RW(overrides.hasUses, send); + RW(overrides.hasScript, send); + } + } + } } void PacketRecordDynamic::ProcessEffects(ESM::EffectList &effectList, bool send)