mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 16:26:42 +00:00 
			
		
		
		
	[General] Implement body part records for RecordDynamic packet
This commit is contained in:
		
							parent
							
								
									0dae3074a6
								
							
						
					
					
						commit
						23d410f473
					
				
					 7 changed files with 169 additions and 9 deletions
				
			
		|  | @ -34,12 +34,13 @@ RepairRecord tempRepair; | |||
| LightRecord tempLight; | ||||
| CellRecord tempCell; | ||||
| ScriptRecord tempScript; | ||||
| BodyPartRecord tempBodyPart; | ||||
| 
 | ||||
| BaseOverrides tempOverrides; | ||||
| 
 | ||||
| unsigned int effectCount = 0; | ||||
| ESM::ENAMstruct tempEffect; | ||||
| ESM::PartReference tempBodyPart; | ||||
| ESM::PartReference tempBodyPartReference; | ||||
| mwmp::Item tempInventoryItem; | ||||
| 
 | ||||
| const ESM::EffectList emptyEffectList = {}; | ||||
|  | @ -82,6 +83,7 @@ void RecordsDynamicFunctions::ClearRecords() noexcept | |||
|     WorldstateFunctions::writeWorldstate.lightRecords.clear(); | ||||
|     WorldstateFunctions::writeWorldstate.cellRecords.clear(); | ||||
|     WorldstateFunctions::writeWorldstate.scriptRecords.clear(); | ||||
|     WorldstateFunctions::writeWorldstate.bodyPartRecords.clear(); | ||||
| } | ||||
| 
 | ||||
| unsigned short RecordsDynamicFunctions::GetRecordType() noexcept | ||||
|  | @ -384,6 +386,8 @@ void RecordsDynamicFunctions::SetRecordId(const char* id) noexcept | |||
|         tempLight.data.mId = id; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::SCRIPT) | ||||
|         tempScript.data.mId = id; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|         tempBodyPart.data.mId = id; | ||||
|     else | ||||
|         LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set id for record type %i which lacks that property", writeRecordsType); | ||||
| } | ||||
|  | @ -436,6 +440,8 @@ void RecordsDynamicFunctions::SetRecordBaseId(const char* baseId) noexcept | |||
|         tempCell.baseId = baseId; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::SCRIPT) | ||||
|         tempScript.baseId = baseId; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|         tempBodyPart.baseId = baseId; | ||||
|     else | ||||
|         LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set baseId for record type %i which lacks that property", writeRecordsType); | ||||
| } | ||||
|  | @ -470,6 +476,8 @@ void RecordsDynamicFunctions::SetRecordSubtype(unsigned int subtype) noexcept | |||
|         tempWeapon.data.mData.mType = subtype; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::APPARATUS) | ||||
|         tempApparatus.data.mData.mType = subtype; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|         tempBodyPart.data.mData.mType = subtype; | ||||
|     else | ||||
|     { | ||||
|         LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set subtype for record type %i which lacks that property", writeRecordsType); | ||||
|  | @ -570,6 +578,8 @@ void RecordsDynamicFunctions::SetRecordModel(const char* model) noexcept | |||
|         tempRepair.data.mModel = model; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::LIGHT) | ||||
|         tempLight.data.mModel = model; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|         tempBodyPart.data.mModel = model; | ||||
|     else | ||||
|     { | ||||
|         LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set model for record type %i which lacks that property", writeRecordsType); | ||||
|  | @ -783,6 +793,8 @@ void RecordsDynamicFunctions::SetRecordFlags(int flags) noexcept | |||
|         tempContainer.data.mFlags = flags; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::LIGHT) | ||||
|         tempLight.data.mData.mFlags = flags; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|         tempBodyPart.data.mData.mFlags = flags; | ||||
|     else | ||||
|     { | ||||
|         LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set flags for record type %i which lacks that property", writeRecordsType); | ||||
|  | @ -1186,6 +1198,8 @@ void RecordsDynamicFunctions::SetRecordRace(const char* race) noexcept | |||
| 
 | ||||
|     if (writeRecordsType == mwmp::RECORD_TYPE::NPC) | ||||
|         tempNpc.data.mRace = race; | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|         tempBodyPart.data.mRace = race; | ||||
|     else | ||||
|         LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set race for record type %i which lacks that property", writeRecordsType); | ||||
| 
 | ||||
|  | @ -1247,6 +1261,21 @@ void RecordsDynamicFunctions::SetRecordBloodType(int bloodType) noexcept | |||
|     tempOverrides.hasBloodType = true; | ||||
| } | ||||
| 
 | ||||
| void RecordsDynamicFunctions::SetRecordVampireState(bool vampireState) noexcept | ||||
| { | ||||
|     unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; | ||||
| 
 | ||||
|     if (writeRecordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|         tempBodyPart.data.mData.mVampire = vampireState; | ||||
|     else | ||||
|     { | ||||
|         LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set vampire state for record type %i which lacks that property", writeRecordsType); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     tempOverrides.hasVampireState = true; | ||||
| } | ||||
| 
 | ||||
| void RecordsDynamicFunctions::SetRecordLevel(int level) noexcept | ||||
| { | ||||
|     unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; | ||||
|  | @ -1506,17 +1535,25 @@ void RecordsDynamicFunctions::SetRecordEffectMagnitudeMin(int magnitudeMin) noex | |||
| 
 | ||||
| void RecordsDynamicFunctions::SetRecordBodyPartType(unsigned int partType) noexcept | ||||
| { | ||||
|     tempBodyPart.mPart = partType; | ||||
|     unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; | ||||
| 
 | ||||
|     if (writeRecordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|     { | ||||
|         tempBodyPart.data.mData.mPart = partType; | ||||
|         tempOverrides.hasBodyPartType = true; | ||||
|     } | ||||
|     else | ||||
|         tempBodyPartReference.mPart = partType; | ||||
| } | ||||
| 
 | ||||
| void RecordsDynamicFunctions::SetRecordBodyPartIdForMale(const char* partId) noexcept | ||||
| { | ||||
|     tempBodyPart.mMale = partId; | ||||
|     tempBodyPartReference.mMale = partId; | ||||
| } | ||||
| 
 | ||||
| void RecordsDynamicFunctions::SetRecordBodyPartIdForFemale(const char* partId) noexcept | ||||
| { | ||||
|     tempBodyPart.mFemale = partId; | ||||
|     tempBodyPartReference.mFemale = partId; | ||||
| } | ||||
| 
 | ||||
| void RecordsDynamicFunctions::SetRecordInventoryItemId(const char* itemId) noexcept | ||||
|  | @ -1665,6 +1702,12 @@ void RecordsDynamicFunctions::AddRecord() noexcept | |||
|         WorldstateFunctions::writeWorldstate.scriptRecords.push_back(tempScript); | ||||
|         tempScript = {}; | ||||
|     } | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|     { | ||||
|         tempBodyPart.baseOverrides = tempOverrides; | ||||
|         WorldstateFunctions::writeWorldstate.bodyPartRecords.push_back(tempBodyPart); | ||||
|         tempBodyPart = {}; | ||||
|     } | ||||
| 
 | ||||
|     effectCount = 0; | ||||
|     tempOverrides = {}; | ||||
|  | @ -1707,9 +1750,9 @@ void RecordsDynamicFunctions::AddRecordBodyPart() noexcept | |||
|     unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; | ||||
| 
 | ||||
|     if (writeRecordsType == mwmp::RECORD_TYPE::ARMOR) | ||||
|         tempArmor.data.mParts.mParts.push_back(tempBodyPart); | ||||
|         tempArmor.data.mParts.mParts.push_back(tempBodyPartReference); | ||||
|     else if (writeRecordsType == mwmp::RECORD_TYPE::CLOTHING) | ||||
|         tempClothing.data.mParts.mParts.push_back(tempBodyPart); | ||||
|         tempClothing.data.mParts.mParts.push_back(tempBodyPartReference); | ||||
| 
 | ||||
|     tempOverrides.hasBodyParts = true; | ||||
|     tempBodyPart = {}; | ||||
|  |  | |||
|  | @ -86,6 +86,7 @@ | |||
|     \ | ||||
|     {"SetRecordScale",                          RecordsDynamicFunctions::SetRecordScale},\ | ||||
|     {"SetRecordBloodType",                      RecordsDynamicFunctions::SetRecordBloodType},\ | ||||
|     {"SetRecordVampireState",                   RecordsDynamicFunctions::SetRecordVampireState},\ | ||||
|     \ | ||||
|     {"SetRecordLevel",                          RecordsDynamicFunctions::SetRecordLevel},\ | ||||
|     {"SetRecordMagicka",                        RecordsDynamicFunctions::SetRecordMagicka},\ | ||||
|  | @ -757,6 +758,15 @@ public: | |||
|     */ | ||||
|     static void SetRecordBloodType(int bloodType) noexcept; | ||||
| 
 | ||||
|     /**
 | ||||
|     * \brief Set the vampire state of the temporary record stored on the server for the | ||||
|     * currently specified record type. | ||||
|     * | ||||
|     * \param vampireState The vampire state of the record. | ||||
|     * \return void | ||||
|     */ | ||||
|     static void SetRecordVampireState(bool vampireState) noexcept; | ||||
| 
 | ||||
|     /**
 | ||||
|     * \brief Set the level of the temporary record stored on the server for the | ||||
|     * currently specified record type. | ||||
|  | @ -949,7 +959,9 @@ public: | |||
|     static void SetRecordEffectMagnitudeMin(int magnitudeMin) noexcept; | ||||
| 
 | ||||
|     /**
 | ||||
|     * \brief Set the type of the temporary body part stored on the server. | ||||
|     * \brief Set the body part type of the temporary body part stored on the server | ||||
|     * (which then needs to be added to ARMOR or CLOTHING records) or set the body part | ||||
|     * type of the current record if it's a BODYPART. | ||||
|     * | ||||
|     * \param partType The type of the body part. | ||||
|     * \return void | ||||
|  |  | |||
|  | @ -192,6 +192,55 @@ void RecordHelper::overrideRecord(const mwmp::ArmorRecord& record) | |||
|         world->updatePtrsWithRefId(recordData.mId); | ||||
| } | ||||
| 
 | ||||
| void RecordHelper::overrideRecord(const mwmp::BodyPartRecord& record) | ||||
| { | ||||
|     const ESM::BodyPart &recordData = record.data; | ||||
| 
 | ||||
|     if (recordData.mId.empty()) | ||||
|     { | ||||
|         LOG_APPEND(TimedLog::LOG_INFO, "-- Ignoring record override with no id provided"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     MWBase::World *world = MWBase::Environment::get().getWorld(); | ||||
| 
 | ||||
|     if (record.baseId.empty()) | ||||
|     { | ||||
|         world->getModifiableStore().overrideRecord(recordData); | ||||
|     } | ||||
|     else if (doesRecordIdExist<ESM::BodyPart>(record.baseId)) | ||||
|     { | ||||
|         const ESM::BodyPart *baseData = world->getStore().get<ESM::BodyPart>().search(record.baseId); | ||||
|         ESM::BodyPart finalData = *baseData; | ||||
|         finalData.mId = recordData.mId; | ||||
| 
 | ||||
|         if (record.baseOverrides.hasModel) | ||||
|             finalData.mModel = recordData.mModel; | ||||
| 
 | ||||
|         if (record.baseOverrides.hasRace) | ||||
|             finalData.mRace = recordData.mRace; | ||||
| 
 | ||||
|         if (record.baseOverrides.hasSubtype) | ||||
|             finalData.mData.mType = recordData.mData.mType; | ||||
| 
 | ||||
|         if (record.baseOverrides.hasBodyPartType) | ||||
|             finalData.mData.mPart = recordData.mData.mPart; | ||||
| 
 | ||||
|         if (record.baseOverrides.hasVampireState) | ||||
|             finalData.mData.mVampire = recordData.mData.mVampire; | ||||
| 
 | ||||
|         if (record.baseOverrides.hasFlags) | ||||
|             finalData.mData.mFlags = recordData.mData.mFlags; | ||||
| 
 | ||||
|         world->getModifiableStore().overrideRecord(finalData); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         LOG_APPEND(TimedLog::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str()); | ||||
|         return; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void RecordHelper::overrideRecord(const mwmp::BookRecord& record) | ||||
| { | ||||
|     const ESM::Book &recordData = record.data; | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ namespace RecordHelper | |||
|     void overrideRecord(const mwmp::ActivatorRecord& record); | ||||
|     void overrideRecord(const mwmp::ApparatusRecord& record); | ||||
|     void overrideRecord(const mwmp::ArmorRecord& record); | ||||
|     void overrideRecord(const mwmp::BodyPartRecord& record); | ||||
|     void overrideRecord(const mwmp::BookRecord& record); | ||||
|     void overrideRecord(const mwmp::CellRecord& record); | ||||
|     void overrideRecord(const mwmp::ClothingRecord& record); | ||||
|  |  | |||
|  | @ -304,6 +304,18 @@ void Worldstate::addRecords() | |||
|             RecordHelper::overrideRecord(record); | ||||
|         } | ||||
|     } | ||||
|     else if (recordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|     { | ||||
|         for (auto &&record : bodyPartRecords) | ||||
|         { | ||||
|             bool hasBaseId = !record.baseId.empty(); | ||||
| 
 | ||||
|             LOG_APPEND(TimedLog::LOG_INFO, "- bodypart record %s\n-- baseId is %s", record.data.mId.c_str(), | ||||
|                 hasBaseId ? record.baseId.c_str() : "empty"); | ||||
| 
 | ||||
|             RecordHelper::overrideRecord(record); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool Worldstate::containsExploredMapTile(int cellX, int cellY) | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include <components/esm/loadalch.hpp> | ||||
| #include <components/esm/loadappa.hpp> | ||||
| #include <components/esm/loadarmo.hpp> | ||||
| #include <components/esm/loadbody.hpp> | ||||
| #include <components/esm/loadbook.hpp> | ||||
| #include <components/esm/loadclot.hpp> | ||||
| #include <components/esm/loadcont.hpp> | ||||
|  | @ -54,7 +55,8 @@ namespace mwmp | |||
|         REPAIR, | ||||
|         LIGHT, | ||||
|         CELL, | ||||
|         SCRIPT | ||||
|         SCRIPT, | ||||
|         BODYPART | ||||
|     }; | ||||
| 
 | ||||
|     // When using an existing record as a base, this struct tracks which changes
 | ||||
|  | @ -118,6 +120,8 @@ namespace mwmp | |||
| 
 | ||||
|         bool hasScale = false; | ||||
|         bool hasBloodType = false; | ||||
|         bool hasBodyPartType = false; | ||||
|         bool hasVampireState = false; | ||||
| 
 | ||||
|         bool hasLevel = false; | ||||
|         bool hasMagicka = false; | ||||
|  | @ -156,6 +160,13 @@ namespace mwmp | |||
|         BaseOverrides baseOverrides; | ||||
|     }; | ||||
| 
 | ||||
|     struct BodyPartRecord | ||||
|     { | ||||
|         ESM::BodyPart data; | ||||
|         std::string baseId; | ||||
|         BaseOverrides baseOverrides; | ||||
|     }; | ||||
| 
 | ||||
|     struct BookRecord | ||||
|     { | ||||
|         ESM::Book data; | ||||
|  | @ -360,6 +371,7 @@ namespace mwmp | |||
|         std::vector<ActivatorRecord> activatorRecords; | ||||
|         std::vector<ApparatusRecord> apparatusRecords; | ||||
|         std::vector<ArmorRecord> armorRecords; | ||||
|         std::vector<BodyPartRecord> bodyPartRecords; | ||||
|         std::vector<BookRecord> bookRecords; | ||||
|         std::vector<CellRecord> cellRecords; | ||||
|         std::vector<ClothingRecord> clothingRecords; | ||||
|  |  | |||
|  | @ -64,6 +64,8 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send) | |||
|             worldstate->recordsCount = Utils::getVectorSize(worldstate->cellRecords); | ||||
|         else if (worldstate->recordsType == mwmp::RECORD_TYPE::SCRIPT) | ||||
|             worldstate->recordsCount = Utils::getVectorSize(worldstate->scriptRecords); | ||||
|         else if (worldstate->recordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|             worldstate->recordsCount = Utils::getVectorSize(worldstate->bodyPartRecords); | ||||
|         else | ||||
|         { | ||||
|             LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Processed invalid ID_RECORD_DYNAMIC packet about unimplemented recordsType %i", | ||||
|  | @ -128,6 +130,8 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send) | |||
|             Utils::resetVector(worldstate->cellRecords, worldstate->recordsCount); | ||||
|         else if (worldstate->recordsType == mwmp::RECORD_TYPE::SCRIPT) | ||||
|             Utils::resetVector(worldstate->scriptRecords, worldstate->recordsCount); | ||||
|         else if (worldstate->recordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|             Utils::resetVector(worldstate->bodyPartRecords, worldstate->recordsCount); | ||||
|     } | ||||
| 
 | ||||
|     if (worldstate->recordsType == mwmp::RECORD_TYPE::SPELL) | ||||
|  | @ -295,8 +299,8 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send) | |||
|                 RW(overrides.hasName, send); | ||||
|                 RW(overrides.hasGender, send); | ||||
|                 RW(overrides.hasFlags, send); | ||||
|                 RW(overrides.hasModel, send); | ||||
|                 RW(overrides.hasRace, send); | ||||
|                 RW(overrides.hasModel, send); | ||||
|                 RW(overrides.hasHair, send); | ||||
|                 RW(overrides.hasHead, send); | ||||
|                 RW(overrides.hasFaction, send); | ||||
|  | @ -813,6 +817,33 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send) | |||
|             } | ||||
|         } | ||||
|     } | ||||
|     else if (worldstate->recordsType == mwmp::RECORD_TYPE::BODYPART) | ||||
|     { | ||||
|         for (auto &&record : worldstate->bodyPartRecords) | ||||
|         { | ||||
|             auto &recordData = record.data; | ||||
| 
 | ||||
|             RW(record.baseId, send, true); | ||||
|             RW(recordData.mId, send, true); | ||||
|             RW(recordData.mModel, send, true); | ||||
|             RW(recordData.mRace, send, true); | ||||
|             RW(recordData.mData.mType, send); | ||||
|             RW(recordData.mData.mPart, send); | ||||
|             RW(recordData.mData.mVampire, send); | ||||
|             RW(recordData.mData.mFlags, send); | ||||
| 
 | ||||
|             if (!record.baseId.empty()) | ||||
|             { | ||||
|                 auto &&overrides = record.baseOverrides; | ||||
|                 RW(overrides.hasModel, send); | ||||
|                 RW(overrides.hasRace, send); | ||||
|                 RW(overrides.hasSubtype, send); | ||||
|                 RW(overrides.hasBodyPartType, send); | ||||
|                 RW(overrides.hasVampireState, send); | ||||
|                 RW(overrides.hasFlags, send); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void PacketRecordDynamic::ProcessEffects(ESM::EffectList &effectList, bool send) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue