diff --git a/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp b/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp index d4cbb4b00..60609b0bb 100644 --- a/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp +++ b/apps/openmw-mp/Script/Functions/RecordsDynamic.cpp @@ -8,7 +8,9 @@ #include #include "RecordsDynamic.hpp" +#include "Utils.hpp" +using namespace std; using namespace mwmp; SpellRecord tempSpell; @@ -744,18 +746,15 @@ void RecordsDynamicFunctions::SetRecordAutoCalc(int autoCalc) noexcept 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) { + Utils::setFlag(tempNpc.data.mFlags, ESM::NPC::Autocalc, autoCalc); 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 { @@ -1603,6 +1602,151 @@ void RecordsDynamicFunctions::SetRecordStringVariable(const char* stringVar) noe } } +void RecordsDynamicFunctions::SetRecordHasAmbient(bool hasAmbi) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CELL) { + tempCell.data.mHasAmbi = hasAmbi; + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set has ambient for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasAmbiState = true; +} + +void RecordsDynamicFunctions::SetRecordAmbientColor(unsigned int red, unsigned int green, unsigned int blue) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CELL) { + tempCell.data.mAmbi.mAmbient = red + (green << 8) + (blue << 16); + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set ambient color for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasAmbientColor = true; +} + +void RecordsDynamicFunctions::SetRecordSunlightColor(unsigned int red, unsigned int green, unsigned int blue) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CELL) { + tempCell.data.mAmbi.mSunlight = red + (green << 8) + (blue << 16); + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set ambient color for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasSunlightColor = true; +} + +void RecordsDynamicFunctions::SetRecordFog(unsigned int red, unsigned int green, unsigned int blue, double density) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CELL) { + tempCell.data.mAmbi.mFog = red + (green << 8) + (blue << 16); + tempCell.data.mAmbi.mFogDensity = density; + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set ambient color for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasFog = true; +} + +void RecordsDynamicFunctions::SetRecordHasWater(bool hasWater) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CELL) { + Utils::setFlag(tempCell.data.mData.mFlags, ESM::Cell::Flags::HasWater, hasWater); + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set ambient color for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasWaterState = true; +} + +void RecordsDynamicFunctions::SetRecordWaterLevel(double waterLevel) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CELL) { + tempCell.data.mWater = waterLevel; + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set ambient color for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasWaterLevel = true; +} + +void RecordsDynamicFunctions::SetRecordNoSleep(bool noSleep) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CELL) { + Utils::setFlag(tempCell.data.mData.mFlags, ESM::Cell::Flags::NoSleep, noSleep); + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set no sleep state for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasNoSleep = true; +} + +void RecordsDynamicFunctions::SetRecordQuasiEx(bool quasiEx) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CELL) { + Utils::setFlag(tempCell.data.mData.mFlags, ESM::Cell::Flags::QuasiEx, quasiEx); + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set quasi exterior state for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasQuasiEx = true; +} + +void RecordsDynamicFunctions::SetRecordRegion(const char* region) noexcept +{ + unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; + + if (writeRecordsType == mwmp::RECORD_TYPE::CELL) { + tempCell.data.mRegion = region; + } + else + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set quasi exterior state for record type %i which lacks that property", writeRecordsType); + return; + } + + tempOverrides.hasRegion = true; +} + void RecordsDynamicFunctions::SetRecordIdByIndex(unsigned int index, const char* id) noexcept { unsigned short writeRecordsType = WorldstateFunctions::writeWorldstate.recordsType; diff --git a/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp b/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp index 37965beea..a52cb4931 100644 --- a/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp +++ b/apps/openmw-mp/Script/Functions/RecordsDynamic.hpp @@ -112,6 +112,16 @@ {"SetRecordFloatVariable", RecordsDynamicFunctions::SetRecordFloatVariable},\ {"SetRecordStringVariable", RecordsDynamicFunctions::SetRecordStringVariable},\ \ + {"SetRecordHasAmbient", RecordsDynamicFunctions::SetRecordHasAmbient},\ + {"SetRecordAmbientColor", RecordsDynamicFunctions::SetRecordAmbientColor},\ + {"SetRecordSunlightColor", RecordsDynamicFunctions::SetRecordSunlightColor},\ + {"SetRecordFog", RecordsDynamicFunctions::SetRecordFog},\ + {"SetRecordHasWater", RecordsDynamicFunctions::SetRecordHasWater},\ + {"SetRecordWaterLevel", RecordsDynamicFunctions::SetRecordWaterLevel},\ + {"SetRecordNoSleep", RecordsDynamicFunctions::SetRecordNoSleep},\ + {"SetRecordQuasiEx", RecordsDynamicFunctions::SetRecordQuasiEx},\ + {"SetRecordRegion", RecordsDynamicFunctions::SetRecordRegion},\ + \ {"SetRecordIdByIndex", RecordsDynamicFunctions::SetRecordIdByIndex},\ {"SetRecordEnchantmentIdByIndex", RecordsDynamicFunctions::SetRecordEnchantmentIdByIndex},\ \ @@ -949,6 +959,86 @@ public: */ static void SetRecordStringVariable(const char* stringVar) noexcept; + /** + * \brief Set the ambient state of the temporary record stored on the server for the + * currently specified record type. + * + * \param bool Ambient state of the record + * \return void + */ + static void SetRecordHasAmbient(bool hasAmbi) noexcept; + + /** + * \brief Set the ambient color of the temporary record stored on the server for the + * currently specified record type. + * + * \param color Ambient color of the record + * \return void + */ + static void SetRecordAmbientColor(unsigned int red, unsigned int green, unsigned int blue) noexcept; + + /** + * \brief Set the sunlight color of the temporary record stored on the server for the + * currently specified record type. + * + * \param color Sunlight color of the record + * \return void + */ + static void SetRecordSunlightColor(unsigned int red, unsigned int green, unsigned int blue) noexcept; + + /** + * \brief Set the fog of the temporary record stored on the server for the + * currently specified record type. + * + * \param color Fog color of the record + * \param density Fog density of the record + * \return void + */ + static void SetRecordFog(unsigned int red, unsigned int green, unsigned int blue, double density) noexcept; + + /** + * \brief Set the water state of the temporary record stored on the server for the + * currently specified record type. + * + * \param hasWater Water state of the record + * \return void + */ + static void SetRecordHasWater(bool hasWater) noexcept; + + /** + * \brief Set the water level of the temporary record stored on the server for the + * currently specified record type. + * + * \param waterLevel waterLevel of the record + * \return void + */ + static void SetRecordWaterLevel(double waterLevel) noexcept; + + /** + * \brief Set whether players are allowed to sleep in the temporary record + * stored on the server for the currently specified record type. + * + * \param noSleep Whether players are allowed to sleep + * \return void + */ + static void SetRecordNoSleep(bool noSleep) noexcept; + + /** + * \brief Set whether the temporary record stored on the server for the + * currently specified record type is a quasi exterior. + * \param quasiEx Whether the record is a quasi exterior. + * \return void + */ + static void SetRecordQuasiEx(bool quasiEx) noexcept; + + /** + * \brief Set region of the temporary record stored on the server for the + * currently specified record type. + * \param region The region of the record + * \return void + */ + static void SetRecordRegion(const char* region) noexcept; + /** * \brief Set the id of the record at a certain index in the records stored on the server. * diff --git a/apps/openmw/mwmp/RecordHelper.cpp b/apps/openmw/mwmp/RecordHelper.cpp index 312cf4e7e..f07bdb865 100644 --- a/apps/openmw/mwmp/RecordHelper.cpp +++ b/apps/openmw/mwmp/RecordHelper.cpp @@ -7,6 +7,7 @@ #include "Main.hpp" #include "CellController.hpp" #include "Cell.hpp" +#include void RecordHelper::overrideRecord(const mwmp::ActivatorRecord& record) { @@ -351,7 +352,7 @@ void RecordHelper::overrideRecord(const mwmp::CellRecord& record) if (record.baseId.empty()) { - recordData.mData.mFlags |= ESM::Cell::Flags::Interior; + Utils::setFlag(recordData.mData.mFlags, ESM::Cell::Flags::Interior, true); recordData.mCellId.mWorldspace = Misc::StringUtils::lowerCase(recordData.mName); world->unloadCell(recordData); @@ -365,6 +366,44 @@ void RecordHelper::overrideRecord(const mwmp::CellRecord& record) finalData.mName = recordData.mName; finalData.mCellId.mWorldspace = Misc::StringUtils::lowerCase(recordData.mName); + if (record.baseOverrides.hasAmbiState) + finalData.mHasAmbi= recordData.mHasAmbi; + if (record.baseOverrides.hasAmbientColor) + finalData.mAmbi.mAmbient = recordData.mAmbi.mAmbient; + if (record.baseOverrides.hasSunlightColor) + finalData.mAmbi.mSunlight = recordData.mAmbi.mSunlight; + if (record.baseOverrides.hasFog) { + finalData.mAmbi.mFog = recordData.mAmbi.mFog; + finalData.mAmbi.mFogDensity = recordData.mAmbi.mFogDensity; + } + if (record.baseOverrides.hasWaterState) { + Utils::setFlag( + finalData.mData.mFlags, + ESM::Cell::Flags::HasWater, + recordData.mData.mFlags + ); + } + if (record.baseOverrides.hasWaterLevel) { + finalData.mWater = recordData.mWater; + } + if (record.baseOverrides.hasNoSleep) { + Utils::setFlag( + finalData.mData.mFlags, + ESM::Cell::Flags::NoSleep, + recordData.mData.mFlags + ); + } + if (record.baseOverrides.hasQuasiEx) { + Utils::setFlag( + finalData.mData.mFlags, + ESM::Cell::Flags::QuasiEx, + recordData.mData.mFlags + ); + } + if (record.baseOverrides.hasRegion) { + finalData.mRegion = recordData.mRegion; + } + world->unloadCell(finalData); world->clearCellStore(finalData); world->getModifiableStore().overrideRecord(finalData); @@ -1111,11 +1150,7 @@ void RecordHelper::overrideRecord(const mwmp::NpcRecord& record) if (record.baseOverrides.hasAutoCalc) { finalData.mNpdtType = recordData.mNpdtType; - - if ((recordData.mFlags & ESM::NPC::Autocalc) != 0) - finalData.mFlags |= ESM::NPC::Autocalc; - else - finalData.mFlags &= ~ESM::NPC::Autocalc; + Utils::setFlag(finalData.mFlags, ESM::NPC::Autocalc, recordData.mFlags); } if (!record.inventoryBaseId.empty() && doesRecordIdExist(record.inventoryBaseId)) diff --git a/components/openmw-mp/Base/BaseWorldstate.hpp b/components/openmw-mp/Base/BaseWorldstate.hpp index fbf835940..6e4c231b9 100644 --- a/components/openmw-mp/Base/BaseWorldstate.hpp +++ b/components/openmw-mp/Base/BaseWorldstate.hpp @@ -145,6 +145,16 @@ namespace mwmp bool hasScriptText = false; + bool hasAmbiState = false; + bool hasAmbientColor = false; + bool hasSunlightColor = false; + bool hasFog = false; + bool hasWaterState = false; + bool hasWaterLevel = false; + bool hasNoSleep = false; + bool hasQuasiEx = false; + bool hasRegion = false; + bool hasVolume = false; bool hasMinRange = false; bool hasMaxRange = false; diff --git a/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp b/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp index 4f0b04564..c3fba328d 100644 --- a/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp +++ b/components/openmw-mp/Packets/Worldstate/PacketRecordDynamic.cpp @@ -504,6 +504,27 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *newBitstream, bool send) RW(record.baseId, send, true); RW(recordData.mName, send, true); + RW(recordData.mHasAmbi, send); + RW(recordData.mAmbi.mAmbient, send, true); + RW(recordData.mAmbi.mSunlight, send, true); + RW(recordData.mAmbi.mFog, send, true); + RW(recordData.mAmbi.mFogDensity, send); + RW(recordData.mData.mFlags, send); + RW(recordData.mWater, send); + + if (!record.baseId.empty()) + { + auto&& overrides = record.baseOverrides; + RW(overrides.hasAmbiState, send); + RW(overrides.hasAmbientColor, send); + RW(overrides.hasSunlightColor, send); + RW(overrides.hasFog, send); + RW(overrides.hasWaterState, send); + RW(overrides.hasWaterLevel, send); + RW(overrides.hasNoSleep, send); + RW(overrides.hasQuasiEx, send); + RW(overrides.hasRegion, send); + } } } else if (worldstate->recordsType == mwmp::RECORD_TYPE::CONTAINER) diff --git a/components/openmw-mp/Utils.hpp b/components/openmw-mp/Utils.hpp index 804248f7e..19cf17b39 100644 --- a/components/openmw-mp/Utils.hpp +++ b/components/openmw-mp/Utils.hpp @@ -65,5 +65,21 @@ namespace Utils std::string intToHexStr(unsigned val); unsigned int hexStrToInt(std::string hexString); + + template + void setFlag(T& flags, E bit, bool value) { + if (value) + flags |= bit; + else + flags &= ~bit; + } + + template + void setFlag(T& flags, E bit, T source) { + if (source & bit) + flags |= bit; + else + flags &= ~bit; + } } #endif //UTILS_HPP