diff --git a/dCommon/dEnums/MessageType/Game.h b/dCommon/dEnums/MessageType/Game.h index b4c44915..58bcd0c1 100644 --- a/dCommon/dEnums/MessageType/Game.h +++ b/dCommon/dEnums/MessageType/Game.h @@ -1603,12 +1603,17 @@ namespace MessageType { UPDATE_FORGED_ITEM = 1768, CAN_ITEMS_BE_REFORGED = 1769, NOTIFY_CLIENT_RAIL_START_FAILED = 1771, - GET_IS_ON_RAIL = 1772 + GET_IS_ON_RAIL = 1772, + + // DLU CUSTOM GAME MESSAGES, DO NOT NETWORK OR SEND TO CLIENTS (it wont do anything bad but still dont do it >:( ) + CLEAR_SESSION_FLAGS = 2000, + SET_RETROACTIVE_FLAGS = 2001, + GAME_MESSAGES_END, }; } template <> struct magic_enum::customize::enum_range { static constexpr int min = 0; - static constexpr int max = 1772; + static constexpr int max = static_cast(MessageType::Game::GAME_MESSAGES_END) - 1; }; diff --git a/dCommon/dEnums/eReplicaComponentType.h b/dCommon/dEnums/eReplicaComponentType.h index 2b991dfb..81c34bae 100644 --- a/dCommon/dEnums/eReplicaComponentType.h +++ b/dCommon/dEnums/eReplicaComponentType.h @@ -62,7 +62,7 @@ enum class eReplicaComponentType : uint32_t { SOUND_AMBIENT_2D, SOUND_AMBIENT_3D, PRECONDITION, - PLAYER_FLAG, + FLAG, CUSTOM_BUILD_ASSEMBLY, BASE_COMBAT_AI, MODULE_ASSEMBLY, diff --git a/dGame/Character.cpp b/dGame/Character.cpp index a1538e4d..77aa3469 100644 --- a/dGame/Character.cpp +++ b/dGame/Character.cpp @@ -22,6 +22,7 @@ #include "eGameMasterLevel.h" #include "ePlayerFlag.h" #include "CDPlayerFlagsTable.h" +#include "FlagComponent.h" Character::Character(uint32_t id, User* parentUser) { //First load the name, etc: @@ -37,7 +38,7 @@ Character::~Character() { m_ParentUser = nullptr; } -void Character::UpdateInfoFromDatabase() { +void Character::UpdateInfoFromDatabase(bool clearSessionFlags) { auto charInfo = Database::Get()->GetCharacterInfo(m_ID); if (charInfo) { @@ -65,10 +66,17 @@ void Character::UpdateInfoFromDatabase() { m_OurEntity = nullptr; m_BuildMode = false; + + // This is not done through a game message because our current implementation does this at a point + // in time where an Entity does not exist, so there is no FlagComponent to handle the msg. + if (clearSessionFlags) { + FlagComponent::ClearSessionFlags(m_Doc); + WriteToDatabase(); + } } -void Character::UpdateFromDatabase() { - UpdateInfoFromDatabase(); +void Character::UpdateFromDatabase(bool clearSessionFlags) { + UpdateInfoFromDatabase(clearSessionFlags); } void Character::DoQuickXMLDataParse() { @@ -197,25 +205,6 @@ void Character::DoQuickXMLDataParse() { character->QueryAttribute("lzrz", &m_OriginalRotation.z); character->QueryAttribute("lzrw", &m_OriginalRotation.w); } - - auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag"); - if (flags) { - auto* currentChild = flags->FirstChildElement(); - while (currentChild) { - const auto* temp = currentChild->Attribute("v"); - const auto* id = currentChild->Attribute("id"); - if (temp && id) { - uint32_t index = 0; - uint64_t value = 0; - - index = std::stoul(id); - value = std::stoull(temp); - - m_PlayerFlags.insert(std::make_pair(index, value)); - } - currentChild = currentChild->NextSiblingElement(); - } - } } void Character::UnlockEmote(int emoteID) { @@ -276,25 +265,6 @@ void Character::SaveXMLToDatabase() { character->LinkEndChild(emotes); } - //Export our flags: - auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag"); - if (!flags) { - flags = m_Doc.NewElement("flag"); //Create a flags tag if we don't have one - m_Doc.FirstChildElement("obj")->LinkEndChild(flags); //Link it to the obj tag so we can find next time - } - - flags->DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes - for (const auto& [index, flagBucket] : m_PlayerFlags) { - auto* f = flags->InsertNewChildElement("f"); - f->SetAttribute("id", index); - f->SetAttribute("v", flagBucket); - } - - for (const auto& sessionFlag : m_SessionFlags) { - auto* s = flags->InsertNewChildElement("s"); - s->SetAttribute("si", sessionFlag); - } - SaveXmlRespawnCheckpoints(); m_OurEntity->UpdateXMLDoc(m_Doc); @@ -307,23 +277,6 @@ void Character::SaveXMLToDatabase() { LOG("%i:%s Saved character to Database in: %fs", this->GetID(), this->GetName().c_str(), elapsed.count()); } -void Character::SetIsNewLogin() { - // If we dont have a flag element, then we cannot have a s element as a child of flag. - auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag"); - if (!flags) return; - - auto* currentChild = flags->FirstChildElement(); - while (currentChild) { - auto* nextChild = currentChild->NextSiblingElement(); - if (currentChild->Attribute("si")) { - LOG("Removed session flag (%s) from character %i:%s, saving character to database", currentChild->Attribute("si"), GetID(), GetName().c_str()); - flags->DeleteChild(currentChild); - WriteToDatabase(); - } - currentChild = nextChild; - } -} - void Character::WriteToDatabase() { //Dump our xml into m_XMLData: tinyxml2::XMLPrinter printer(0, true, 0); @@ -333,90 +286,6 @@ void Character::WriteToDatabase() { Database::Get()->UpdateCharacterXml(m_ID, printer.CStr()); } -void Character::SetPlayerFlag(const uint32_t flagId, const bool value) { - // If the flag is already set, we don't have to recalculate it - if (GetPlayerFlag(flagId) == value) return; - - if (value) { - // Update the mission component: - auto* player = Game::entityManager->GetEntity(m_ObjectID); - - if (player != nullptr) { - auto* missionComponent = player->GetComponent(); - - if (missionComponent != nullptr) { - missionComponent->Progress(eMissionTaskType::PLAYER_FLAG, flagId); - } - } - } - - const auto flagEntry = CDPlayerFlagsTable::GetEntry(flagId); - - if (flagEntry && flagEntry->sessionOnly) { - if (value) m_SessionFlags.insert(flagId); - else m_SessionFlags.erase(flagId); - } else { - // Calculate the index first - auto flagIndex = uint32_t(std::floor(flagId / 64)); - - const auto shiftedValue = 1ULL << flagId % 64; - - auto it = m_PlayerFlags.find(flagIndex); - - // Check if flag index exists - if (it != m_PlayerFlags.end()) { - // Update the value - if (value) { - it->second |= shiftedValue; - } else { - it->second &= ~shiftedValue; - } - } else { - if (value) { - // Otherwise, insert the value - uint64_t flagValue = 0; - - flagValue |= shiftedValue; - - m_PlayerFlags.insert(std::make_pair(flagIndex, flagValue)); - } - } - } - // Notify the client that a flag has changed server-side - GameMessages::SendNotifyClientFlagChange(m_ObjectID, flagId, value, m_ParentUser->GetSystemAddress()); -} - -bool Character::GetPlayerFlag(const uint32_t flagId) const { - using enum ePlayerFlag; - - bool toReturn = false; //by def, return false. - - const auto flagEntry = CDPlayerFlagsTable::GetEntry(flagId); - if (flagEntry && flagEntry->sessionOnly) { - toReturn = m_SessionFlags.contains(flagId); - } else { - // Calculate the index first - const auto flagIndex = uint32_t(std::floor(flagId / 64)); - - const auto shiftedValue = 1ULL << flagId % 64; - - auto it = m_PlayerFlags.find(flagIndex); - if (it != m_PlayerFlags.end()) { - // Don't set the data if we don't have to - toReturn = (it->second & shiftedValue) != 0; - } - } - - return toReturn; -} - -void Character::SetRetroactiveFlags() { - // Retroactive check for if player has joined a faction to set their 'joined a faction' flag to true. - if (GetPlayerFlag(ePlayerFlag::VENTURE_FACTION) || GetPlayerFlag(ePlayerFlag::ASSEMBLY_FACTION) || GetPlayerFlag(ePlayerFlag::PARADOX_FACTION) || GetPlayerFlag(ePlayerFlag::SENTINEL_FACTION)) { - SetPlayerFlag(ePlayerFlag::JOINED_A_FACTION, true); - } -} - void Character::SaveXmlRespawnCheckpoints() { //Export our respawn points: auto* points = m_Doc.FirstChildElement("obj")->FirstChildElement("res"); @@ -473,7 +342,11 @@ void Character::OnZoneLoad() { if (missionComponent != nullptr) { // Fix the monument race flag if (missionComponent->GetMissionState(319) >= eMissionState::READY_TO_COMPLETE) { - SetPlayerFlag(ePlayerFlag::AG_FINISH_LINE_BUILT, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = m_ObjectID; + setFlag.iFlagId = ePlayerFlag::AG_FINISH_LINE_BUILT; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } } diff --git a/dGame/Character.h b/dGame/Character.h index 99ed9855..024199c9 100644 --- a/dGame/Character.h +++ b/dGame/Character.h @@ -31,7 +31,7 @@ public: */ void WriteToDatabase(); void SaveXMLToDatabase(); - void UpdateFromDatabase(); + void UpdateFromDatabase(bool clearSessionFlags = false); void SaveXmlRespawnCheckpoints(); void LoadXmlRespawnCheckpoints(); @@ -40,15 +40,6 @@ public: const tinyxml2::XMLDocument& GetXMLDoc() const { return m_Doc; } void _setXmlDoc(tinyxml2::XMLDocument& doc) { doc.DeepCopy(&m_Doc); } - /** - * Out of abundance of safety and clarity of what this saves, this is its own function. - * - * Clears the s element from the flag element and saves the xml to the database. Used to prevent the news - * feed from showing up on world transfers. - * - */ - void SetIsNewLogin(); - /** * Gets the database ID of the character * @return the database ID of the character @@ -410,32 +401,11 @@ public: */ void UnlockEmote(int emoteID); - /** - * Sets a flag for the character, indicating certain parts of the game that have been interacted with. Not to be - * confused with the permissions - * @param flagId the ID of the flag to set - * @param value the value to set for the flag - */ - void SetPlayerFlag(uint32_t flagId, bool value); - - /** - * Gets the value for a certain character flag - * @param flagId the ID of the flag to get a value for - * @return the value of the flag given the ID (the default is false, obviously) - */ - bool GetPlayerFlag(uint32_t flagId) const; - /** * Notifies the character that they're now muted */ void SendMuteNotice() const; - /** - * Sets any flags that are meant to have been set that may not have been set due to them being - * missing in a previous patch. - */ - void SetRetroactiveFlags(); - /** * Get the equipped items for this character, only used for character creation * @return the equipped items for this character on world load @@ -465,7 +435,7 @@ public: void _setXmlData(const std::string& xmlData) { m_XMLData = xmlData; } private: - void UpdateInfoFromDatabase(); + void UpdateInfoFromDatabase(bool clearSessionFlags); /** * The ID of this character. First 32 bits of the ObjectID. */ @@ -620,17 +590,6 @@ private: */ uint64_t m_LastLogin{}; - /** - * Flags only set for the duration of a session - * - */ - std::set m_SessionFlags; - - /** - * The gameplay flags this character has (not just true values) - */ - std::unordered_map m_PlayerFlags; - /** * The character XML belonging to this character */ diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 90bf7e76..d11a2089 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -84,6 +84,7 @@ #include "GhostComponent.h" #include "AchievementVendorComponent.h" #include "VanityUtilities.h" +#include "FlagComponent.h" // Table includes #include "CDComponentsRegistryTable.h" @@ -482,6 +483,8 @@ void Entity::Initialize() { AddComponent(m_Character, systemAddress)->LoadFromXml(m_Character->GetXMLDoc()); AddComponent(); + + AddComponent()->LoadFromXml(m_Character->GetXMLDoc()); } if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) { diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index c95af3d7..718d9024 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -604,3 +604,10 @@ void EntityManager::FireEventServerSide(Entity* origin, std::string args) { bool EntityManager::IsExcludedFromGhosting(LOT lot) { return std::find(m_GhostingExcludedLOTs.begin(), m_GhostingExcludedLOTs.end(), lot) != m_GhostingExcludedLOTs.end(); } + +bool EntityManager::SendMsg(GameMessages::GameMsg& msg) { + bool bRet = false; + auto* entity = GetEntity(msg.target); + if (entity) bRet = entity->HandleMsg(msg); + return bRet; +} diff --git a/dGame/EntityManager.h b/dGame/EntityManager.h index fdbb1a55..831de0ca 100644 --- a/dGame/EntityManager.h +++ b/dGame/EntityManager.h @@ -8,6 +8,13 @@ #include "dCommonVars.h" +// Convenience macro to send a message to the entity manager +#define SEND_ENTITY_MSG(msg) Game::entityManager->SendMsg(msg) + +namespace GameMessages { + struct GameMsg; +}; + class Entity; class EntityInfo; class Player; @@ -72,6 +79,9 @@ public: const bool GetHardcoreDropinventoryOnDeath() { return m_HardcoreDropinventoryOnDeath; }; const uint32_t GetHardcoreUscoreEnemiesMultiplier() { return m_HardcoreUscoreEnemiesMultiplier; }; + // Sends a message to be handled by the receiving entity + bool SendMsg(GameMessages::GameMsg& msg); + private: void SerializeEntities(); void KillEntities(); diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index e0e37e7c..13e1f30f 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -197,6 +197,10 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) { skillComponent->Reset(); } + GameMessages::ClearSessionFlags msg{}; + msg.target = chars[i]->GetObjectID(); + SEND_ENTITY_MSG(msg); + Game::entityManager->DestroyEntity(chars[i]->GetEntity()); chars[i]->SaveXMLToDatabase(); @@ -210,8 +214,7 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) { for (const auto& characterId : Database::Get()->GetAccountCharacterIds(u->GetAccountID())) { Character* character = new Character(characterId, u); - character->UpdateFromDatabase(); - character->SetIsNewLogin(); + character->UpdateFromDatabase(true); chars.push_back(character); } diff --git a/dGame/dComponents/CMakeLists.txt b/dGame/dComponents/CMakeLists.txt index e1116895..fc0cf982 100644 --- a/dGame/dComponents/CMakeLists.txt +++ b/dGame/dComponents/CMakeLists.txt @@ -10,6 +10,7 @@ set(DGAME_DCOMPONENTS_SOURCES "ControllablePhysicsComponent.cpp" "DestroyableComponent.cpp" "DonationVendorComponent.cpp" + "FlagComponent.cpp" "GhostComponent.cpp" "InventoryComponent.cpp" "ItemComponent.cpp" diff --git a/dGame/dComponents/FlagComponent.cpp b/dGame/dComponents/FlagComponent.cpp new file mode 100644 index 00000000..1de06d4a --- /dev/null +++ b/dGame/dComponents/FlagComponent.cpp @@ -0,0 +1,199 @@ +#include "FlagComponent.h" + +#include "CDPlayerFlagsTable.h" + +#include "eMissionTaskType.h" +#include "ePlayerFlag.h" + +#include "MissionComponent.h" + +FlagComponent::FlagComponent(Entity* parent) : Component(parent) { + RegisterMsg(MessageType::Game::SET_FLAG, this, &FlagComponent::OnSetFlag); + RegisterMsg(MessageType::Game::GET_FLAG, this, &FlagComponent::OnGetFlag); + RegisterMsg(MessageType::Game::CLEAR_SESSION_FLAGS, this, &FlagComponent::OnClearSessionFlags); + RegisterMsg(MessageType::Game::SET_RETROACTIVE_FLAGS, this, &FlagComponent::OnSetRetroactiveFlags); +} + +bool FlagComponent::OnSetFlag(GameMessages::GameMsg& msg) { + auto& setFlag = static_cast(msg); + LOG("Set %i", setFlag.iFlagId); + SetPlayerFlag(setFlag.iFlagId, setFlag.bFlag); + + // This is always set the first time a player loads into a world from character select + // and is used to know when to refresh the players inventory items so they show up. + if (setFlag.iFlagId == ePlayerFlag::IS_NEWS_SCREEN_VISIBLE && setFlag.bFlag) { + m_Parent->SetVar(u"dlu_first_time_load", true); + } + + return true; +} + +bool FlagComponent::OnGetFlag(GameMessages::GameMsg& msg) { + auto& getFlag = static_cast(msg); + LOG("Get %i", getFlag.iFlagId); + + getFlag.bFlag = GetPlayerFlag(getFlag.iFlagId); + return true; +} + +void FlagComponent::UpdateXml(tinyxml2::XMLDocument& doc) { + if (!doc.FirstChildElement("obj")) return; + auto& obj = *doc.FirstChildElement("obj"); + + if (!obj.FirstChildElement("flag")) { + obj.InsertNewChildElement("flag"); + } + + auto& flags = *obj.FirstChildElement("flag"); + + flags.DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes + + // Save our flags + for (const auto& [index, flagBucket] : m_PlayerFlags) { + auto& f = *flags.InsertNewChildElement("f"); + f.SetAttribute("id", index); + f.SetAttribute("v", flagBucket); + } + + // Save our session flags + for (const auto& sessionFlag : m_SessionFlags) { + auto& s = *flags.InsertNewChildElement("s"); + LOG("Saving session flag %i", sessionFlag); + s.SetAttribute("si", sessionFlag); + } +} + +void FlagComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) { + if (!doc.FirstChildElement("obj")) return; + auto& obj = *doc.FirstChildElement("obj"); + + if (!obj.FirstChildElement("flag")) return; + auto& flags = *obj.FirstChildElement("flag"); + + const auto* currentChild = flags.FirstChildElement("f"); + while (currentChild) { + const auto* temp = currentChild->Attribute("v"); + const auto* id = currentChild->Attribute("id"); + if (temp && id) { + uint32_t index = 0; + uint64_t value = 0; + + index = std::stoul(id); + value = std::stoull(temp); + + m_PlayerFlags.insert(std::make_pair(index, value)); + } + currentChild = currentChild->NextSiblingElement("f"); + } + + // Now load our session flags + currentChild = flags.FirstChildElement("s"); + while (currentChild) { + const auto* temp = currentChild->Attribute("si"); + if (temp) { + uint32_t sessionIndex = 0; + sessionIndex = std::stoul(temp); + m_SessionFlags.insert(sessionIndex); + } + currentChild = currentChild->NextSiblingElement("s"); + } +} + +void FlagComponent::SetPlayerFlag(const uint32_t flagId, const bool value) { + // If the flag is already set, we don't have to recalculate it + if (GetPlayerFlag(flagId) == value) return; + + if (value) { + // Update the mission component: + auto* missionComponent = m_Parent->GetComponent(); + + if (missionComponent != nullptr) { + missionComponent->Progress(eMissionTaskType::PLAYER_FLAG, flagId); + } + } + + const auto flagEntry = CDPlayerFlagsTable::GetEntry(flagId); + + if (flagEntry && flagEntry->sessionOnly) { + if (value) m_SessionFlags.insert(flagId); + else m_SessionFlags.erase(flagId); + } else { + // Calculate the index first + auto flagIndex = uint32_t(std::floor(flagId / 64)); + + const auto shiftedValue = 1ULL << flagId % 64; + + auto it = m_PlayerFlags.find(flagIndex); + + // Check if flag index exists + if (it != m_PlayerFlags.end()) { + // Update the value + if (value) { + it->second |= shiftedValue; + } else { + it->second &= ~shiftedValue; + } + } else { + if (value) { + // Otherwise, insert the value + uint64_t flagValue = 0; + + flagValue |= shiftedValue; + + m_PlayerFlags.insert(std::make_pair(flagIndex, flagValue)); + } + } + } + // Notify the client that a flag has changed server-side + GameMessages::SendNotifyClientFlagChange(m_Parent->GetObjectID(), flagId, value, m_Parent->GetSystemAddress()); +} + +bool FlagComponent::GetPlayerFlag(const uint32_t flagId) const { + bool toReturn = false; //by def, return false. + + const auto flagEntry = CDPlayerFlagsTable::GetEntry(flagId); + if (flagEntry && flagEntry->sessionOnly) { + toReturn = m_SessionFlags.contains(flagId); + } else { + // Calculate the index first + const auto flagIndex = uint32_t(std::floor(flagId / 64)); + + const auto shiftedValue = 1ULL << flagId % 64; + + auto it = m_PlayerFlags.find(flagIndex); + if (it != m_PlayerFlags.end()) { + // Don't set the data if we don't have to + toReturn = (it->second & shiftedValue) != 0; + } + } + + return toReturn; +} + +bool FlagComponent::OnSetRetroactiveFlags(GameMessages::GameMsg& msg) { + // Retroactive check for if player has joined a faction to set their 'joined a faction' flag to true. + if (GetPlayerFlag(ePlayerFlag::VENTURE_FACTION) || + GetPlayerFlag(ePlayerFlag::ASSEMBLY_FACTION) || + GetPlayerFlag(ePlayerFlag::PARADOX_FACTION) || + GetPlayerFlag(ePlayerFlag::SENTINEL_FACTION)) { + SetPlayerFlag(ePlayerFlag::JOINED_A_FACTION, true); + } + return true; +} + +void FlagComponent::ClearSessionFlags(tinyxml2::XMLDocument& doc) { + if (!doc.FirstChildElement("obj")) return; + auto& obj = *doc.FirstChildElement("obj"); + + if (!obj.FirstChildElement("flag")) return; + auto& flags = *obj.FirstChildElement("flag"); + + auto* currentChild = flags.FirstChildElement(); + while (currentChild) { + auto* nextChild = currentChild->NextSiblingElement(); + if (currentChild->Attribute("si")) { + flags.DeleteChild(currentChild); + } + currentChild = nextChild; + } +} diff --git a/dGame/dComponents/FlagComponent.h b/dGame/dComponents/FlagComponent.h new file mode 100644 index 00000000..b2fffc3b --- /dev/null +++ b/dGame/dComponents/FlagComponent.h @@ -0,0 +1,59 @@ +#ifndef FLAGCOMPONENT_H +#define FLAGCOMPONENT_H + +#include +#include +#include + +#include "Component.h" +#include "eReplicaComponentType.h" + +class FlagComponent final : public Component { +public: + static const inline eReplicaComponentType ComponentType = eReplicaComponentType::FLAG; + FlagComponent(Entity* parent); + + void UpdateXml(tinyxml2::XMLDocument& doc) override; + void LoadFromXml(const tinyxml2::XMLDocument& doc) override; + + // Used to clear the save data from a static context where you only have a doc (switching characters) + static void ClearSessionFlags(tinyxml2::XMLDocument& doc); +private: + + /** + * Sets a flag for the character, indicating certain parts of the game that have been interacted with. Not to be + * confused with the permissions + * @param flagId the ID of the flag to set + * @param value the value to set for the flag + */ + bool OnSetFlag(GameMessages::GameMsg& msg); + void SetPlayerFlag(const uint32_t flagId, const bool value); + + /** + * Gets the value for a certain character flag + * @param flagId the ID of the flag to get a value for + * @return the value of the flag given the ID (the default is false, obviously) + */ + bool OnGetFlag(GameMessages::GameMsg& msg); + bool GetPlayerFlag(const uint32_t flagId) const; + + bool OnClearSessionFlags(GameMessages::GameMsg& msg) { m_SessionFlags.clear(); return true; } + + /** + * Sets any flags that are meant to have been set that may not have been set due to them being + * missing in a previous patch. + */ + bool OnSetRetroactiveFlags(GameMessages::GameMsg& msg); + /** + * Flags only set for the duration of a session + * + */ + std::set m_SessionFlags; + + /** + * The gameplay flags this character has (not just true values) + */ + std::unordered_map m_PlayerFlags; +}; + +#endif //!FLAGCOMPONENT_H diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 7121dd44..304a9a54 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -557,7 +557,11 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) { // Triggers the catch a pet missions if (petFlags.find(m_Parent->GetLOT()) != petFlags.end()) { - tamer->GetCharacter()->SetPlayerFlag(petFlags.at(m_Parent->GetLOT()), true); + GameMessages::SetFlag setFlag{}; + setFlag.target = tamer->GetObjectID(); + setFlag.iFlagId = petFlags.at(m_Parent->GetLOT()); + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } auto* missionComponent = tamer->GetComponent(); @@ -847,7 +851,11 @@ void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) { Game::entityManager->SerializeEntity(m_Parent); - owner->GetCharacter()->SetPlayerFlag(ePlayerFlag::FIRST_MANUAL_PET_HIBERNATE, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = owner->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::FIRST_MANUAL_PET_HIBERNATE; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); if (registerPet) { GameMessages::SendAddPetToPlayer(m_Owner, 0, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, m_Parent->GetLOT(), owner->GetSystemAddress()); diff --git a/dGame/dComponents/QuickBuildComponent.cpp b/dGame/dComponents/QuickBuildComponent.cpp index 7a5cd8a0..0d504a84 100644 --- a/dGame/dComponents/QuickBuildComponent.cpp +++ b/dGame/dComponents/QuickBuildComponent.cpp @@ -481,14 +481,12 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* const user) { } // Set flag - auto* character = user->GetCharacter(); - - if (character != nullptr) { - const auto flagNumber = m_Parent->GetVar(u"quickbuild_single_build_player_flag"); - - if (flagNumber != 0) { - character->SetPlayerFlag(flagNumber, true); - } + if (m_Parent->HasVar(u"quickbuild_single_build_player_flag")) { + GameMessages::SetFlag setFlag{}; + setFlag.target = user->GetObjectID(); + setFlag.iFlagId = m_Parent->GetVar(u"quickbuild_single_build_player_flag"); + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } RenderComponent::PlayAnimation(user, u"rebuild-celebrate", 1.09f); } diff --git a/dGame/dGameMessages/GameMessageHandler.cpp b/dGame/dGameMessages/GameMessageHandler.cpp index ef890401..d3de0af5 100644 --- a/dGame/dGameMessages/GameMessageHandler.cpp +++ b/dGame/dGameMessages/GameMessageHandler.cpp @@ -47,6 +47,7 @@ namespace { std::map g_MessageHandlers = { { REQUEST_SERVER_OBJECT_INFO, []() { return std::make_unique(); } }, { SHOOTING_GALLERY_FIRE, []() { return std::make_unique(); } }, + { SET_FLAG, []() { return std::make_unique(); } }, }; }; @@ -123,11 +124,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System break; } - case MessageType::Game::SET_FLAG: { - GameMessages::HandleSetFlag(inStream, entity); - break; - } - case MessageType::Game::HAS_BEEN_COLLECTED: { GameMessages::HandleHasBeenCollected(inStream, entity); break; @@ -215,13 +211,17 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System // After we've done our thing, tell the client they're ready GameMessages::SendPlayerReady(Game::zoneManager->GetZoneControlObject(), sysAddr); - if (Game::config->GetValue("allow_players_to_skip_cinematics") != "1" - || !entity->GetCharacter() - || !entity->GetCharacter()->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS)) return; - entity->AddCallbackTimer(0.5f, [entity, sysAddr]() { - if (!entity) return; - GameMessages::SendEndCinematic(entity->GetObjectID(), u"", sysAddr); - }); + GameMessages::GetFlag getFlag{}; + getFlag.target = entity->GetObjectID(); + getFlag.iFlagId = ePlayerFlag::DLU_SKIP_CINEMATICS; + SEND_ENTITY_MSG(getFlag); + + if (Game::config->GetValue("allow_players_to_skip_cinematics") == "1" && getFlag.bFlag) { + entity->AddCallbackTimer(0.5f, [entity, sysAddr]() { + if (!entity) return; + GameMessages::SendEndCinematic(entity->GetObjectID(), u"", sysAddr); + }); + } break; } diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 6fd7576f..ad214b36 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -5076,23 +5076,6 @@ void GameMessages::HandleModularBuildConvertModel(RakNet::BitStream& inStream, E item->SetCount(item->GetCount() - 1, false, false, true, eLootSourceType::QUICKBUILD); } -void GameMessages::HandleSetFlag(RakNet::BitStream& inStream, Entity* entity) { - bool bFlag{}; - int32_t iFlagID{}; - - inStream.Read(bFlag); - inStream.Read(iFlagID); - - auto character = entity->GetCharacter(); - if (character) character->SetPlayerFlag(iFlagID, bFlag); - - // This is always set the first time a player loads into a world from character select - // and is used to know when to refresh the players inventory items so they show up. - if (iFlagID == ePlayerFlag::IS_NEWS_SCREEN_VISIBLE && bFlag) { - entity->SetVar(u"dlu_first_time_load", true); - } -} - void GameMessages::HandleRespondToMission(RakNet::BitStream& inStream, Entity* entity) { int missionID{}; LWOOBJID playerID{}; @@ -5157,13 +5140,17 @@ void GameMessages::HandleMissionDialogOK(RakNet::BitStream& inStream, Entity* en missionComponent->CompleteMission(missionID); } - if (Game::config->GetValue("allow_players_to_skip_cinematics") != "1" - || !player->GetCharacter() - || !player->GetCharacter()->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS)) return; - player->AddCallbackTimer(0.5f, [player]() { - if (!player) return; - GameMessages::SendEndCinematic(player->GetObjectID(), u"", player->GetSystemAddress()); - }); + GameMessages::GetFlag getFlag{}; + getFlag.target = entity->GetObjectID(); + getFlag.iFlagId = ePlayerFlag::DLU_SKIP_CINEMATICS; + SEND_ENTITY_MSG(getFlag); + + if (Game::config->GetValue("allow_players_to_skip_cinematics") == "1" && getFlag.bFlag) { + player->AddCallbackTimer(0.5f, [player]() { + if (!player) return; + GameMessages::SendEndCinematic(player->GetObjectID(), u"", player->GetSystemAddress()); + }); + } } void GameMessages::HandleRequestLinkedMission(RakNet::BitStream& inStream, Entity* entity) { @@ -6443,4 +6430,14 @@ namespace GameMessages { auto* handlingEntity = Game::entityManager->GetEntity(targetForReport); if (handlingEntity) handlingEntity->HandleMsg(*this); } + + bool SetFlag::Deserialize(RakNet::BitStream& bitStream) { + if (!bitStream.Read(bFlag)) return false; + if (!bitStream.Read(iFlagId)) return false; + return true; + } + + void SetFlag::Handle(Entity& entity, const SystemAddress& sysAddr) { + entity.HandleMsg(*this); + } } diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index c3889674..b870e9e3 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -634,7 +634,6 @@ namespace GameMessages { void HandleRequestUse(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); void HandlePlayEmote(RakNet::BitStream& inStream, Entity* entity); void HandleModularBuildConvertModel(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr); - void HandleSetFlag(RakNet::BitStream& inStream, Entity* entity); void HandleRespondToMission(RakNet::BitStream& inStream, Entity* entity); void HandleMissionDialogOK(RakNet::BitStream& inStream, Entity* entity); void HandleRequestLinkedMission(RakNet::BitStream& inStream, Entity* entity); @@ -782,6 +781,30 @@ namespace GameMessages { bool Deserialize(RakNet::BitStream& bitStream) override; void Handle(Entity& entity, const SystemAddress& sysAddr) override; }; + + struct SetFlag : public GameMsg { + SetFlag() : GameMsg(MessageType::Game::SET_FLAG) {} + bool Deserialize(RakNet::BitStream& bitStream) override; + void Handle(Entity& entity, const SystemAddress& sysAddr) override; + + uint32_t iFlagId{}; + bool bFlag{}; + }; + + struct GetFlag : public GameMsg { + GetFlag() : GameMsg(MessageType::Game::GET_FLAG) {} + + uint32_t iFlagId{}; + bool bFlag{}; + }; + + struct ClearSessionFlags : public GameMsg { + ClearSessionFlags() : GameMsg(MessageType::Game::CLEAR_SESSION_FLAGS) {} + }; + + struct SetRetroactiveFlags : public GameMsg { + SetRetroactiveFlags() : GameMsg(MessageType::Game::SET_RETROACTIVE_FLAGS) {} + }; }; #endif // GAMEMESSAGES_H diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 2a841e39..f847e8ac 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -390,10 +390,15 @@ void Mission::Catchup() { } if (type == eMissionTaskType::PLAYER_FLAG) { - for (int32_t target : task->GetAllTargets()) { - const auto flag = GetCharacter()->GetPlayerFlag(target); + GameMessages::GetFlag getFlag{}; + getFlag.target = entity->GetObjectID(); - if (!flag) { + for (int32_t target : task->GetAllTargets()) { + getFlag.iFlagId = target; + getFlag.bFlag = false; + SEND_ENTITY_MSG(getFlag); + + if (!getFlag.bFlag) { continue; } diff --git a/dGame/dUtilities/Preconditions.cpp b/dGame/dUtilities/Preconditions.cpp index 118d9037..8797792d 100644 --- a/dGame/dUtilities/Preconditions.cpp +++ b/dGame/dUtilities/Preconditions.cpp @@ -146,17 +146,22 @@ bool Precondition::CheckValue(Entity* player, const uint32_t value, bool evaluat return missionComponent->GetMissionState(value) == eMissionState::AVAILABLE || missionComponent->GetMissionState(value) == eMissionState::COMPLETE_AVAILABLE; case PreconditionType::OnMission: if (missionComponent == nullptr) return false; - return missionComponent->GetMissionState(value) == eMissionState::ACTIVE || - missionComponent->GetMissionState(value) == eMissionState::COMPLETE_ACTIVE || - missionComponent->GetMissionState(value) == eMissionState::READY_TO_COMPLETE || - missionComponent->GetMissionState(value) == eMissionState::COMPLETE_READY_TO_COMPLETE; + return missionComponent->GetMissionState(value) == eMissionState::ACTIVE || + missionComponent->GetMissionState(value) == eMissionState::COMPLETE_ACTIVE || + missionComponent->GetMissionState(value) == eMissionState::READY_TO_COMPLETE || + missionComponent->GetMissionState(value) == eMissionState::COMPLETE_READY_TO_COMPLETE; case PreconditionType::MissionComplete: if (missionComponent == nullptr) return false; return missionComponent->GetMissionState(value) >= eMissionState::COMPLETE; case PreconditionType::PetDeployed: return false; // TODO - case PreconditionType::HasFlag: - return character->GetPlayerFlag(value); + case PreconditionType::HasFlag: { + GameMessages::GetFlag getFlag{}; + getFlag.target = player->GetObjectID(); + getFlag.iFlagId = value; + SEND_ENTITY_MSG(getFlag); + return getFlag.bFlag; + } case PreconditionType::WithinShape: return true; // Client checks this one case PreconditionType::InBuild: diff --git a/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp b/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp index 43f46746..1cbab3bc 100644 --- a/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp +++ b/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp @@ -108,11 +108,18 @@ namespace DEVGMCommands { void ToggleSkipCinematics(Entity* entity, const SystemAddress& sysAddr, const std::string args) { if (Game::config->GetValue("allow_players_to_skip_cinematics") != "1" && entity->GetGMLevel() < eGameMasterLevel::DEVELOPER) return; - auto* character = entity->GetCharacter(); - if (!character) return; - bool current = character->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS); - character->SetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS, !current); - if (!current) { + GameMessages::GetFlag current{}; + current.target = entity->GetObjectID(); + current.iFlagId = ePlayerFlag::DLU_SKIP_CINEMATICS; + SEND_ENTITY_MSG(current); + + GameMessages::SetFlag setFlag{}; + setFlag.target = entity->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::DLU_SKIP_CINEMATICS; + setFlag.bFlag = !current.bFlag; + SEND_ENTITY_MSG(setFlag); + + if (!current.bFlag) { GameMessages::SendSlashCommandFeedbackText(entity, u"You have elected to skip cinematics. Note that not all cinematics can be skipped, but most will be skipped now."); } else { GameMessages::SendSlashCommandFeedbackText(entity, u"Cinematics will no longer be skipped."); @@ -424,6 +431,9 @@ namespace DEVGMCommands { void SetFlag(Entity* entity, const SystemAddress& sysAddr, const std::string args) { const auto splitArgs = GeneralUtils::SplitString(args, ' '); + + GameMessages::SetFlag setFlag{}; + setFlag.target = entity->GetObjectID(); if (splitArgs.size() == 1) { const auto flagId = GeneralUtils::TryParse(splitArgs.at(0)); @@ -431,8 +441,9 @@ namespace DEVGMCommands { ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag id."); return; } - - entity->GetCharacter()->SetPlayerFlag(flagId.value(), true); + setFlag.iFlagId = flagId.value(); + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } else if (splitArgs.size() >= 2) { const auto flagId = GeneralUtils::TryParse(splitArgs.at(1)); std::string onOffFlag = splitArgs.at(0); @@ -445,12 +456,17 @@ namespace DEVGMCommands { ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag type."); return; } - - entity->GetCharacter()->SetPlayerFlag(flagId.value(), onOffFlag == "on"); + setFlag.iFlagId = flagId.value(); + setFlag.bFlag = onOffFlag == "on"; + SEND_ENTITY_MSG(setFlag); } } void ClearFlag(Entity* entity, const SystemAddress& sysAddr, const std::string args) { + GameMessages::SetFlag setFlag{}; + setFlag.target = entity->GetObjectID(); + setFlag.bFlag = false; + const auto splitArgs = GeneralUtils::SplitString(args, ' '); if (splitArgs.empty()) return; @@ -461,7 +477,8 @@ namespace DEVGMCommands { return; } - entity->GetCharacter()->SetPlayerFlag(flagId.value(), false); + setFlag.iFlagId = flagId.value(); + SEND_ENTITY_MSG(setFlag); } void PlayEffect(Entity* entity, const SystemAddress& sysAddr, const std::string args) { diff --git a/dScripts/02_server/Map/AG/AgCagedBricksServer.cpp b/dScripts/02_server/Map/AG/AgCagedBricksServer.cpp index 4d7e8a64..dbbb60d5 100644 --- a/dScripts/02_server/Map/AG/AgCagedBricksServer.cpp +++ b/dScripts/02_server/Map/AG/AgCagedBricksServer.cpp @@ -1,9 +1,8 @@ #include "AgCagedBricksServer.h" + #include "InventoryComponent.h" #include "GameMessages.h" -#include "Character.h" #include "EntityManager.h" -#include "eReplicaComponentType.h" #include "ePlayerFlag.h" void AgCagedBricksServer::OnUse(Entity* self, Entity* user) { @@ -14,14 +13,14 @@ void AgCagedBricksServer::OnUse(Entity* self, Entity* user) { } //Set the flag & mission status: - auto character = user->GetCharacter(); - - if (!character) return; - - character->SetPlayerFlag(ePlayerFlag::CAGED_SPIDER, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = user->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::CAGED_SPIDER; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); //Remove the maelstrom cube: - auto inv = static_cast(user->GetComponent(eReplicaComponentType::INVENTORY)); + auto* inv = user->GetComponent(); if (inv) { inv->RemoveItem(14553, 1); diff --git a/dScripts/02_server/Map/AG/RemoveRentalGear.cpp b/dScripts/02_server/Map/AG/RemoveRentalGear.cpp index f9bdf1ce..150b1d85 100644 --- a/dScripts/02_server/Map/AG/RemoveRentalGear.cpp +++ b/dScripts/02_server/Map/AG/RemoveRentalGear.cpp @@ -1,9 +1,8 @@ #include "RemoveRentalGear.h" + #include "InventoryComponent.h" #include "Item.h" #include "eMissionState.h" -#include "Character.h" -#include "eReplicaComponentType.h" #include "ePlayerFlag.h" /* @@ -23,7 +22,7 @@ void RemoveRentalGear::OnMissionDialogueOK(Entity* self, Entity* target, int mis if (missionID != defaultMission && missionID != 313) return; if (missionState == eMissionState::COMPLETE || missionState == eMissionState::READY_TO_COMPLETE) { - auto inv = static_cast(target->GetComponent(eReplicaComponentType::INVENTORY)); + auto* inv = target->GetComponent(); if (!inv) return; //remove the inventory items @@ -36,7 +35,10 @@ void RemoveRentalGear::OnMissionDialogueOK(Entity* self, Entity* target, int mis } //reset the equipment flag - auto character = target->GetCharacter(); - if (character) character->SetPlayerFlag(ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR, false); + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR; + setFlag.bFlag = false; + SEND_ENTITY_MSG(setFlag); } } diff --git a/dScripts/02_server/Map/AM/AmBlueX.cpp b/dScripts/02_server/Map/AM/AmBlueX.cpp index 180d4c54..f7a83708 100644 --- a/dScripts/02_server/Map/AM/AmBlueX.cpp +++ b/dScripts/02_server/Map/AM/AmBlueX.cpp @@ -2,7 +2,6 @@ #include "SkillComponent.h" #include "EntityManager.h" #include "EntityInfo.h" -#include "Character.h" void AmBlueX::OnUse(Entity* self, Entity* user) { auto* skillComponent = user->GetComponent(); @@ -16,10 +15,11 @@ void AmBlueX::OnSkillEventFired(Entity* self, Entity* caster, const std::string& self->SetNetworkVar(m_XUsedVariable, true); self->SetNetworkVar(m_StartEffectVariable, true); - auto* character = caster->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(self->GetVar(m_FlagVariable), true); - } + GameMessages::SetFlag setFlag{}; + setFlag.target = caster->GetObjectID(); + setFlag.iFlagId = self->GetVar(m_FlagVariable); + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); EntityInfo info{}; info.lot = m_FXObject; diff --git a/dScripts/02_server/Map/General/Binoculars.cpp b/dScripts/02_server/Map/General/Binoculars.cpp index 854ccf71..2ef02e63 100644 --- a/dScripts/02_server/Map/General/Binoculars.cpp +++ b/dScripts/02_server/Map/General/Binoculars.cpp @@ -1,15 +1,26 @@ #include "Binoculars.h" -#include "Character.h" + #include "GameMessages.h" #include "Game.h" -#include "dServer.h" +#include "dZoneManager.h" void Binoculars::OnUse(Entity* self, Entity* user) { const auto number = self->GetVarAsString(u"number"); - int32_t flag = std::stoi(std::to_string(Game::server->GetZoneID()).substr(0, 2) + number); - if (user->GetCharacter()->GetPlayerFlag(flag) == false) { - user->GetCharacter()->SetPlayerFlag(flag, true); + int32_t flag = std::stoi(std::to_string(Game::zoneManager->GetZoneID().GetMapID()).substr(0, 2) + number); + + GameMessages::GetFlag getFlag{}; + getFlag.target = user->GetObjectID(); + getFlag.iFlagId = flag; + SEND_ENTITY_MSG(getFlag); + + if (!getFlag.bFlag) { + GameMessages::SetFlag setFlag{}; + setFlag.target = user->GetObjectID(); + setFlag.iFlagId = flag; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); + GameMessages::SendFireEventClientSide(self->GetObjectID(), user->GetSystemAddress(), u"achieve", LWOOBJID_EMPTY, 0, -1, LWOOBJID_EMPTY); } } diff --git a/dScripts/02_server/Map/General/Ninjago/NjRailActivatorsServer.cpp b/dScripts/02_server/Map/General/Ninjago/NjRailActivatorsServer.cpp index fee3cd42..088adae1 100644 --- a/dScripts/02_server/Map/General/Ninjago/NjRailActivatorsServer.cpp +++ b/dScripts/02_server/Map/General/Ninjago/NjRailActivatorsServer.cpp @@ -1,6 +1,5 @@ #include "NjRailActivatorsServer.h" #include "QuickBuildComponent.h" -#include "Character.h" void NjRailActivatorsServer::OnUse(Entity* self, Entity* user) { const auto flag = self->GetVar(u"RailFlagNum"); @@ -8,9 +7,10 @@ void NjRailActivatorsServer::OnUse(Entity* self, Entity* user) { // Only allow use if this is not a quick build or the quick build is built if (quickBuildComponent == nullptr || quickBuildComponent->GetState() == eQuickBuildState::COMPLETED) { - auto* character = user->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(flag, true); - } + GameMessages::SetFlag setFlag{}; + setFlag.target = user->GetObjectID(); + setFlag.iFlagId = flag; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } } diff --git a/dScripts/02_server/Map/General/PetDigServer.cpp b/dScripts/02_server/Map/General/PetDigServer.cpp index 77a50e5a..7302e1e4 100644 --- a/dScripts/02_server/Map/General/PetDigServer.cpp +++ b/dScripts/02_server/Map/General/PetDigServer.cpp @@ -1,10 +1,9 @@ -#include "dZoneManager.h" #include "PetDigServer.h" + +#include "dZoneManager.h" #include "MissionComponent.h" #include "EntityManager.h" -#include "Character.h" #include "PetComponent.h" -#include "User.h" #include "eMissionState.h" std::vector PetDigServer::treasures{}; @@ -110,7 +109,6 @@ void PetDigServer::HandleXBuildDig(const Entity* self, Entity* owner, Entity* pe if (!playerEntity || !playerEntity->GetCharacter()) return; - auto* player = playerEntity->GetCharacter(); const auto groupID = self->GetVar(u"groupID"); int32_t playerFlag = 0; @@ -123,15 +121,22 @@ void PetDigServer::HandleXBuildDig(const Entity* self, Entity* owner, Entity* pe playerFlag = 63; } + GameMessages::GetFlag getFlag{}; + getFlag.target = playerEntity->GetObjectID(); + getFlag.iFlagId = playerFlag; + SEND_ENTITY_MSG(getFlag); // If the player doesn't have the flag yet - if (playerFlag != 0 && !player->GetPlayerFlag(playerFlag)) { + if (playerFlag != 0 && SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { auto* petComponent = pet->GetComponent(); if (petComponent != nullptr) { // TODO: Pet state = 9 ?? } - // Shows the flag object to the player - player->SetPlayerFlag(playerFlag, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = playerEntity->GetObjectID(); + setFlag.iFlagId = playerFlag; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } auto* xObject = Game::entityManager->GetEntity(self->GetVar(u"X")); @@ -173,12 +178,17 @@ void PetDigServer::ProgressPetDigMissions(const Entity* owner, const Entity* che if (excavatorMissionState == eMissionState::ACTIVE) { if (chest->HasVar(u"PetDig")) { int32_t playerFlag = 1260 + chest->GetVarAs(u"PetDig"); - Character* player = owner->GetCharacter(); - + GameMessages::GetFlag getFlag{}; + getFlag.target = owner->GetObjectID(); + getFlag.iFlagId = playerFlag; // check if player flag is set - if (!player->GetPlayerFlag(playerFlag)) { + if (SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { missionComponent->ForceProgress(505, 767, 1); - player->SetPlayerFlag(playerFlag, 1); + GameMessages::SetFlag setFlag{}; + setFlag.target = owner->GetObjectID(); + setFlag.iFlagId = playerFlag; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } } } diff --git a/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp b/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp index 4ad78d6a..e49d675d 100644 --- a/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp +++ b/dScripts/02_server/Map/General/StoryBoxInteractServer.cpp @@ -1,7 +1,7 @@ #include "StoryBoxInteractServer.h" #include "Character.h" #include "GameMessages.h" -#include "dServer.h" +#include "dZoneManager.h" #include "Amf3.h" #include "Entity.h" @@ -36,11 +36,19 @@ void StoryBoxInteractServer::OnUse(Entity* self, Entity* user) { if(!storyValue) return; int32_t boxFlag = self->GetVar(u"altFlagID"); if (boxFlag <= 0) { - boxFlag = (10000 + Game::server->GetZoneID() + storyValue.value()); + boxFlag = (10000 + Game::zoneManager->GetZoneID().GetMapID() + storyValue.value()); } - if (user->GetCharacter()->GetPlayerFlag(boxFlag) == false) { - user->GetCharacter()->SetPlayerFlag(boxFlag, true); + GameMessages::GetFlag getFlag{}; + getFlag.target = user->GetObjectID(); + getFlag.iFlagId = boxFlag; + if (SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { + GameMessages::SetFlag setFlag{}; + setFlag.target = user->GetObjectID(); + setFlag.iFlagId = boxFlag; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); + GameMessages::SendFireEventClientSide(self->GetObjectID(), user->GetSystemAddress(), u"achieve", LWOOBJID_EMPTY, 0, -1, LWOOBJID_EMPTY); } } diff --git a/dScripts/02_server/Map/General/TokenConsoleServer.cpp b/dScripts/02_server/Map/General/TokenConsoleServer.cpp index 0a1f679c..e0de6922 100644 --- a/dScripts/02_server/Map/General/TokenConsoleServer.cpp +++ b/dScripts/02_server/Map/General/TokenConsoleServer.cpp @@ -1,15 +1,14 @@ #include "TokenConsoleServer.h" + #include "InventoryComponent.h" #include "GameMessages.h" -#include "Character.h" -#include "eReplicaComponentType.h" #include "eTerminateType.h" #include "ePlayerFlag.h" //2021-05-03 - max - added script, omitted some parts related to inheritance in lua which we don't need void TokenConsoleServer::OnUse(Entity* self, Entity* user) { - auto* inv = static_cast(user->GetComponent(eReplicaComponentType::INVENTORY)); + auto* inv = user->GetComponent(); //make sure the user has the required amount of infected bricks if (inv && inv->GetLotCount(6194) >= bricksToTake) { @@ -22,17 +21,18 @@ void TokenConsoleServer::OnUse(Entity* self, Entity* user) { } //figure out which faction the player belongs to: - auto character = user->GetCharacter(); - if (!character) return; // At this point the player has to be in a faction. + + GameMessages::GetFlag getFlag{}; + getFlag.target = user->GetObjectID(); LOT tokenLOT = 0; - if (character->GetPlayerFlag(ePlayerFlag::VENTURE_FACTION)) //venture + if (getFlag.iFlagId = ePlayerFlag::VENTURE_FACTION, SEND_ENTITY_MSG(getFlag) && getFlag.bFlag) //venture tokenLOT = 8321; - else if (character->GetPlayerFlag(ePlayerFlag::ASSEMBLY_FACTION)) //assembly + else if (getFlag.iFlagId = ePlayerFlag::ASSEMBLY_FACTION, SEND_ENTITY_MSG(getFlag) && getFlag.bFlag) //assembly tokenLOT = 8318; - else if (character->GetPlayerFlag(ePlayerFlag::PARADOX_FACTION)) //paradox + else if (getFlag.iFlagId = ePlayerFlag::PARADOX_FACTION, SEND_ENTITY_MSG(getFlag) && getFlag.bFlag) //paradox tokenLOT = 8320; - else if (character->GetPlayerFlag(ePlayerFlag::SENTINEL_FACTION)) //sentinel + else if (getFlag.iFlagId = ePlayerFlag::SENTINEL_FACTION, SEND_ENTITY_MSG(getFlag) && getFlag.bFlag) //sentinel tokenLOT = 8319; inv->AddItem(tokenLOT, tokensToGive, eLootSourceType::NONE); } diff --git a/dScripts/02_server/Map/NS/NsTokenConsoleServer.cpp b/dScripts/02_server/Map/NS/NsTokenConsoleServer.cpp index 7d825828..47744324 100644 --- a/dScripts/02_server/Map/NS/NsTokenConsoleServer.cpp +++ b/dScripts/02_server/Map/NS/NsTokenConsoleServer.cpp @@ -1,7 +1,6 @@ #include "NsTokenConsoleServer.h" #include "InventoryComponent.h" #include "GameMessages.h" -#include "Character.h" #include "MissionComponent.h" #include "QuickBuildComponent.h" #include "eTerminateType.h" @@ -24,9 +23,8 @@ void NsTokenConsoleServer::OnUse(Entity* self, Entity* user) { auto* inventoryComponent = user->GetComponent(); auto* missionComponent = user->GetComponent(); - auto* character = user->GetCharacter(); - if (inventoryComponent == nullptr || missionComponent == nullptr || character == nullptr) { + if (inventoryComponent == nullptr || missionComponent == nullptr) { return; } @@ -42,15 +40,18 @@ void NsTokenConsoleServer::OnUse(Entity* self, Entity* user) { GameMessages::SendPlayNDAudioEmitter(self, user->GetSystemAddress(), useSound); } + GameMessages::GetFlag getFlag{}; + getFlag.target = user->GetObjectID(); + // Player must be in faction to interact with this entity. LOT tokenLOT = 0; - if (character->GetPlayerFlag(ePlayerFlag::VENTURE_FACTION)) //venture + if (getFlag.iFlagId = ePlayerFlag::VENTURE_FACTION, SEND_ENTITY_MSG(getFlag) && getFlag.bFlag) //venture tokenLOT = 8321; - else if (character->GetPlayerFlag(ePlayerFlag::ASSEMBLY_FACTION)) //assembly + else if (getFlag.iFlagId = ePlayerFlag::ASSEMBLY_FACTION, SEND_ENTITY_MSG(getFlag) && getFlag.bFlag) //assembly tokenLOT = 8318; - else if (character->GetPlayerFlag(ePlayerFlag::PARADOX_FACTION)) //paradox + else if (getFlag.iFlagId = ePlayerFlag::PARADOX_FACTION, SEND_ENTITY_MSG(getFlag) && getFlag.bFlag) //paradox tokenLOT = 8320; - else if (character->GetPlayerFlag(ePlayerFlag::SENTINEL_FACTION)) //sentinel + else if (getFlag.iFlagId = ePlayerFlag::SENTINEL_FACTION, SEND_ENTITY_MSG(getFlag) && getFlag.bFlag) //sentinel tokenLOT = 8319; inventoryComponent->AddItem(tokenLOT, 5, eLootSourceType::NONE); diff --git a/dScripts/02_server/Map/NT/NTPipeVisibilityServer.cpp b/dScripts/02_server/Map/NT/NTPipeVisibilityServer.cpp index 7d39e9d9..d4a4c4d6 100644 --- a/dScripts/02_server/Map/NT/NTPipeVisibilityServer.cpp +++ b/dScripts/02_server/Map/NT/NTPipeVisibilityServer.cpp @@ -1,15 +1,15 @@ #include "NTPipeVisibilityServer.h" + #include "Entity.h" -#include "Character.h" void NTPipeVisibilityServer::OnQuickBuildComplete(Entity* self, Entity* target) { const auto flag = self->GetVar(u"flag"); if (flag == 0) return; - - auto* character = target->GetCharacter(); - if (!character) return; - - character->SetPlayerFlag(flag, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); + setFlag.iFlagId = flag; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PipeBuilt"); } diff --git a/dScripts/02_server/Map/NT/NtImagimeterVisibility.cpp b/dScripts/02_server/Map/NT/NtImagimeterVisibility.cpp index 8003f4df..03b60f40 100644 --- a/dScripts/02_server/Map/NT/NtImagimeterVisibility.cpp +++ b/dScripts/02_server/Map/NT/NtImagimeterVisibility.cpp @@ -1,12 +1,14 @@ #include "NtImagimeterVisibility.h" #include "GameMessages.h" #include "Entity.h" -#include "Character.h" #include "ePlayerFlag.h" void NTImagimeterVisibility::OnQuickBuildComplete(Entity* self, Entity* target) { - auto* character = target->GetCharacter(); - if (character) character->SetPlayerFlag(ePlayerFlag::NT_PLINTH_REBUILD, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::NT_PLINTH_REBUILD; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PlinthBuilt", 0, 0, LWOOBJID_EMPTY, "", target->GetSystemAddress()); } diff --git a/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp b/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp index 0fe97a26..8570bf35 100644 --- a/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp +++ b/dScripts/02_server/Map/NT/NtParadoxPanelServer.cpp @@ -1,8 +1,8 @@ #include "NtParadoxPanelServer.h" + #include "GameMessages.h" #include "MissionComponent.h" #include "EntityManager.h" -#include "Character.h" #include "eMissionState.h" #include "RenderComponent.h" #include "eTerminateType.h" @@ -32,8 +32,11 @@ void NtParadoxPanelServer::OnUse(Entity* self, Entity* user) { } const auto flag = self->GetVar(u"flag"); - - player->GetCharacter()->SetPlayerFlag(flag, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = playerID; + setFlag.iFlagId = flag; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); RenderComponent::PlayAnimation(player, u"rebuild-celebrate"); diff --git a/dScripts/02_server/Map/Property/AG_Small/ZoneAgProperty.cpp b/dScripts/02_server/Map/Property/AG_Small/ZoneAgProperty.cpp index 6f2f6d36..2c9ef8bb 100644 --- a/dScripts/02_server/Map/Property/AG_Small/ZoneAgProperty.cpp +++ b/dScripts/02_server/Map/Property/AG_Small/ZoneAgProperty.cpp @@ -292,34 +292,45 @@ void ZoneAgProperty::BaseTimerDone(Entity* self, const std::string& timerName) { void ZoneAgProperty::OnZonePropertyRented(Entity* self, Entity* player) { BaseZonePropertyRented(self, player); - auto* character = player->GetCharacter(); - if (character == nullptr) - return; - - character->SetPlayerFlag(108, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.iFlagId = 108; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } void ZoneAgProperty::OnZonePropertyModelPlaced(Entity* self, Entity* player) { - auto* character = player->GetCharacter(); auto* missionComponent = player->GetComponent(); + if (!missionComponent) return; - if (!character->GetPlayerFlag(101)) { + GameMessages::GetFlag getFlag{}; + getFlag.target = player->GetObjectID(); + + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.bFlag = true; + + if (getFlag.iFlagId = 101, SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { BaseZonePropertyModelPlaced(self, player); - character->SetPlayerFlag(101, true); + setFlag.iFlagId = 101; + SEND_ENTITY_MSG(setFlag); if (missionComponent->GetMissionState(871) == eMissionState::ACTIVE) { self->SetNetworkVar(u"Tooltip", u"AnotherModel"); } - } else if (!character->GetPlayerFlag(102)) { - character->SetPlayerFlag(102, true); + } else if (getFlag.iFlagId = 102, SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { + setFlag.iFlagId = 102; + SEND_ENTITY_MSG(setFlag); if (missionComponent->GetMissionState(871) == eMissionState::ACTIVE) { self->SetNetworkVar(u"Tooltip", u"TwoMoreModels"); } - } else if (!character->GetPlayerFlag(103)) { - character->SetPlayerFlag(103, true); - } else if (!character->GetPlayerFlag(104)) { - character->SetPlayerFlag(104, true); + } else if (getFlag.iFlagId = 103, SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { + setFlag.iFlagId = 103; + SEND_ENTITY_MSG(setFlag); + } else if (getFlag.iFlagId = 104, SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { + setFlag.iFlagId = 104; + SEND_ENTITY_MSG(setFlag); self->SetNetworkVar(u"Tooltip", u"TwoMoreModelsOff"); } else if (self->GetVar(u"tutorial") == "place_model") { self->SetVar(u"tutorial", ""); @@ -328,20 +339,34 @@ void ZoneAgProperty::OnZonePropertyModelPlaced(Entity* self, Entity* player) { } void ZoneAgProperty::OnZonePropertyModelPickedUp(Entity* self, Entity* player) { - auto* character = player->GetCharacter(); auto* missionComponent = player->GetComponent(); + if (!missionComponent) return; - if (!character->GetPlayerFlag(109)) { - character->SetPlayerFlag(109, true); - if (missionComponent->GetMissionState(891) == eMissionState::ACTIVE && !character->GetPlayerFlag(110)) { + GameMessages::GetFlag getFlag{}; + getFlag.target = player->GetObjectID(); + getFlag.iFlagId = 109; + + if (SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.iFlagId = 109; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); + + getFlag.iFlagId = 110; + getFlag.bFlag = false; + if (missionComponent->GetMissionState(891) == eMissionState::ACTIVE && SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { self->SetNetworkVar(u"Tooltip", u"Rotate"); } } } void ZoneAgProperty::OnZonePropertyModelRemoved(Entity* self, Entity* player) { - auto* character = player->GetCharacter(); - character->SetPlayerFlag(111, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.iFlagId = 111; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } void ZoneAgProperty::OnZonePropertyModelRemovedWhileEquipped(Entity* self, Entity* player) { @@ -349,11 +374,18 @@ void ZoneAgProperty::OnZonePropertyModelRemovedWhileEquipped(Entity* self, Entit } void ZoneAgProperty::OnZonePropertyModelRotated(Entity* self, Entity* player) { - auto* character = player->GetCharacter(); auto* missionComponent = player->GetComponent(); + if (!missionComponent) return; + GameMessages::GetFlag getFlag{}; + getFlag.target = player->GetObjectID(); + getFlag.iFlagId = 110; - if (!character->GetPlayerFlag(110)) { - character->SetPlayerFlag(110, true); + if (SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.iFlagId = 110; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); if (missionComponent->GetMissionState(891) == eMissionState::ACTIVE) { self->SetNetworkVar(u"Tooltip", u"PlaceModel"); @@ -413,7 +445,12 @@ void ZoneAgProperty::BaseOnFireEventServerSide(Entity* self, Entity* sender, std if (player == nullptr) return; - player->GetCharacter()->SetPlayerFlag(self->GetVar(defeatedProperyFlag), true); + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.iFlagId = self->GetVar(defeatedProperyFlag); + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); + GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PlayCinematic", 0, 0, LWOOBJID_EMPTY, destroyedCinematic, UNASSIGNED_SYSTEM_ADDRESS); diff --git a/dScripts/02_server/Map/VE/VeEpsilonServer.cpp b/dScripts/02_server/Map/VE/VeEpsilonServer.cpp index 4e8cb4e9..ab182d7d 100644 --- a/dScripts/02_server/Map/VE/VeEpsilonServer.cpp +++ b/dScripts/02_server/Map/VE/VeEpsilonServer.cpp @@ -1,21 +1,21 @@ #include "VeEpsilonServer.h" -#include "Character.h" + #include "EntityManager.h" #include "GameMessages.h" #include "eMissionState.h" #include "Entity.h" void VeEpsilonServer::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, eMissionState missionState) { - auto* character = target->GetCharacter(); - if (character == nullptr) - return; - // Resets the player flags that track which consoles they've used if ((missionID == m_ConsoleMissionID || missionID == m_ConsoleRepeatMissionID) && (missionState == eMissionState::AVAILABLE || missionState == eMissionState::COMPLETE_AVAILABLE)) { + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); for (auto i = 0; i < 10; i++) { - character->SetPlayerFlag(m_ConsoleBaseFlag + i, false); + setFlag.iFlagId = m_ConsoleBaseFlag + i; + setFlag.bFlag = false; + SEND_ENTITY_MSG(setFlag); } } diff --git a/dScripts/02_server/Map/VE/VeMissionConsole.cpp b/dScripts/02_server/Map/VE/VeMissionConsole.cpp index aa9abb93..341e2491 100644 --- a/dScripts/02_server/Map/VE/VeMissionConsole.cpp +++ b/dScripts/02_server/Map/VE/VeMissionConsole.cpp @@ -1,6 +1,6 @@ #include "VeMissionConsole.h" + #include "InventoryComponent.h" -#include "Character.h" #include "GameMessages.h" #include "Loot.h" #include "eTerminateType.h" @@ -17,10 +17,11 @@ void VeMissionConsole::OnUse(Entity* self, Entity* user) { const auto flagNumber = self->GetVar(m_NumberVariable); const int32_t flag = std::stoi("101" + GeneralUtils::UTF16ToWTF8(flagNumber)); - auto* character = user->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(flag, true); - } + GameMessages::SetFlag setFlag{}; + setFlag.target = user->GetObjectID(); + setFlag.iFlagId = flag; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); GameMessages::SendNotifyClientObject(self->GetObjectID(), u""); GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, self->GetObjectID()); diff --git a/dScripts/02_server/Map/njhub/CavePrisonCage.cpp b/dScripts/02_server/Map/njhub/CavePrisonCage.cpp index 8496ecfb..492540c3 100644 --- a/dScripts/02_server/Map/njhub/CavePrisonCage.cpp +++ b/dScripts/02_server/Map/njhub/CavePrisonCage.cpp @@ -1,8 +1,8 @@ #include "CavePrisonCage.h" + #include "EntityManager.h" #include "QuickBuildComponent.h" #include "GameMessages.h" -#include "Character.h" #include "dZoneManager.h" #include "RenderComponent.h" @@ -161,10 +161,14 @@ void CavePrisonCage::OnTimerDone(Entity* self, std::string timerName) { return; } + // Set the flag on the builder character const auto flagNum = 2020 + self->GetVarAs(u"myNumber"); - // Set the flag on the builder character - builder->GetCharacter()->SetPlayerFlag(flagNum, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = builder->GetObjectID(); + setFlag.iFlagId = flagNum; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); // Setup a timer named 'VillagerEscape' to be triggered in 5 seconds self->AddTimer("VillagerEscape", 5.0f); diff --git a/dScripts/02_server/Map/njhub/NjDragonEmblemChestServer.cpp b/dScripts/02_server/Map/njhub/NjDragonEmblemChestServer.cpp index 74e50b1c..f12aba1a 100644 --- a/dScripts/02_server/Map/njhub/NjDragonEmblemChestServer.cpp +++ b/dScripts/02_server/Map/njhub/NjDragonEmblemChestServer.cpp @@ -1,16 +1,15 @@ #include "NjDragonEmblemChestServer.h" -#include "Character.h" -#include "EntityInfo.h" #include "Loot.h" #include "Entity.h" #include "DestroyableComponent.h" #include "ePlayerFlag.h" void NjDragonEmblemChestServer::OnUse(Entity* self, Entity* user) { - auto* character = user->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(ePlayerFlag::NJ_WU_SHOW_DAILY_CHEST, false); - } + GameMessages::SetFlag setFlag{}; + setFlag.target = user->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::NJ_WU_SHOW_DAILY_CHEST; + setFlag.bFlag = false; + SEND_ENTITY_MSG(setFlag); auto* destroyable = self->GetComponent(); if (destroyable != nullptr) { diff --git a/dScripts/02_server/Map/njhub/NjGarmadonCelebration.cpp b/dScripts/02_server/Map/njhub/NjGarmadonCelebration.cpp index d3e54be1..6acc3be9 100644 --- a/dScripts/02_server/Map/njhub/NjGarmadonCelebration.cpp +++ b/dScripts/02_server/Map/njhub/NjGarmadonCelebration.cpp @@ -1,17 +1,19 @@ #include "NjGarmadonCelebration.h" -#include "Character.h" + #include "GameMessages.h" #include "ePlayerFlag.h" void NjGarmadonCelebration::OnCollisionPhantom(Entity* self, Entity* target) { - auto* character = target->GetCharacter(); + GameMessages::GetFlag getFlag{}; + getFlag.target = target->GetObjectID(); + getFlag.iFlagId = ePlayerFlag::NJ_GARMADON_CINEMATIC_SEEN; - if (character == nullptr) { - return; - } - - if (!character->GetPlayerFlag(ePlayerFlag::NJ_GARMADON_CINEMATIC_SEEN)) { - character->SetPlayerFlag(ePlayerFlag::NJ_GARMADON_CINEMATIC_SEEN, true); + if (SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::NJ_GARMADON_CINEMATIC_SEEN; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); GameMessages::SendStartCelebrationEffect(target, target->GetSystemAddress(), GarmadonCelebrationID); } diff --git a/dScripts/02_server/Map/njhub/NjNPCMissionSpinjitzuServer.cpp b/dScripts/02_server/Map/njhub/NjNPCMissionSpinjitzuServer.cpp index 37a5754c..ed1ed70b 100644 --- a/dScripts/02_server/Map/njhub/NjNPCMissionSpinjitzuServer.cpp +++ b/dScripts/02_server/Map/njhub/NjNPCMissionSpinjitzuServer.cpp @@ -1,6 +1,5 @@ #include "NjNPCMissionSpinjitzuServer.h" -#include "Character.h" -#include "EntityManager.h" + #include "eMissionState.h" void NjNPCMissionSpinjitzuServer::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, eMissionState missionState) { @@ -12,13 +11,11 @@ void NjNPCMissionSpinjitzuServer::OnMissionDialogueOK(Entity* self, Entity* targ // Wait for an animation to complete and flag that the player has learned spinjitzu self->AddCallbackTimer(5.0f, [targetID, element]() { - auto* target = Game::entityManager->GetEntity(targetID); - if (target != nullptr) { - auto* character = target->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(ElementFlags.at(element), true); - } - } + GameMessages::SetFlag setFlag{}; + setFlag.target = targetID; + setFlag.iFlagId = ElementFlags.at(element); + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); }); } } diff --git a/dScripts/02_server/Map/njhub/NjWuNPC.cpp b/dScripts/02_server/Map/njhub/NjWuNPC.cpp index 1a5d30fd..0c11e916 100644 --- a/dScripts/02_server/Map/njhub/NjWuNPC.cpp +++ b/dScripts/02_server/Map/njhub/NjWuNPC.cpp @@ -1,6 +1,5 @@ #include "NjWuNPC.h" #include "MissionComponent.h" -#include "Character.h" #include "EntityManager.h" #include "GameMessages.h" #include "eMissionState.h" @@ -10,10 +9,8 @@ void NjWuNPC::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, e // The Dragon statue daily mission if (missionID == m_MainDragonMissionID) { - auto* character = target->GetCharacter(); auto* missionComponent = target->GetComponent(); - if (character == nullptr || missionComponent == nullptr) - return; + if (!missionComponent) return; switch (missionState) { case eMissionState::AVAILABLE: @@ -24,8 +21,11 @@ void NjWuNPC::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, e missionComponent->RemoveMission(subMissionID); missionComponent->AcceptMission(subMissionID); } - - character->SetPlayerFlag(ePlayerFlag::NJ_WU_SHOW_DAILY_CHEST, false); + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::NJ_WU_SHOW_DAILY_CHEST; + setFlag.bFlag = false; + SEND_ENTITY_MSG(setFlag); // Hide the chest for (auto* chest : Game::entityManager->GetEntitiesInGroup(m_DragonChestGroup)) { @@ -38,7 +38,11 @@ void NjWuNPC::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, e case eMissionState::READY_TO_COMPLETE: case eMissionState::COMPLETE_READY_TO_COMPLETE: { - character->SetPlayerFlag(ePlayerFlag::NJ_WU_SHOW_DAILY_CHEST, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::NJ_WU_SHOW_DAILY_CHEST; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); // Show the chest for (auto* chest : Game::entityManager->GetEntitiesInGroup(m_DragonChestGroup)) { diff --git a/dScripts/BasePropertyServer.cpp b/dScripts/BasePropertyServer.cpp index 9048adeb..e2ed5f5d 100644 --- a/dScripts/BasePropertyServer.cpp +++ b/dScripts/BasePropertyServer.cpp @@ -127,7 +127,10 @@ void BasePropertyServer::BasePlayerLoaded(Entity* self, Entity* player) { if (player->GetObjectID() != propertyOwner) return; } else { - const auto defeatedFlag = player->GetCharacter()->GetPlayerFlag(self->GetVar(defeatedProperyFlag)); + GameMessages::GetFlag getFlag{}; + getFlag.target = player->GetObjectID(); + getFlag.iFlagId = self->GetVar(defeatedProperyFlag); + const auto defeatedFlag = SEND_ENTITY_MSG(getFlag) && getFlag.bFlag; self->SetNetworkVar(UnclaimedVariable, true); self->SetVar(PlayerIDVariable, player->GetObjectID()); @@ -184,8 +187,13 @@ void BasePropertyServer::BaseZonePropertyModelPlaced(Entity* self, Entity* playe return; auto flag = self->GetVar(placedModelFlag); - if (flag) - character->SetPlayerFlag(flag, true); + if (flag) { + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.iFlagId = flag; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); + } } void BasePropertyServer::KillClouds(Entity* self) { @@ -462,10 +470,11 @@ void BasePropertyServer::HandleOrbsTimer(Entity* self) { // Notifies the client that the property has been claimed with a flag, completes missions too auto* player = Game::entityManager->GetEntity(self->GetVar(PlayerIDVariable)); if (player != nullptr) { - auto* character = player->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(self->GetVar(defeatedProperyFlag), true); - } + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.iFlagId = self->GetVar(defeatedProperyFlag); + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } self->AddTimer(TornadoOffTimer, 0.5f); diff --git a/dScripts/Darkitect.cpp b/dScripts/Darkitect.cpp index 2881bde8..b52439ba 100644 --- a/dScripts/Darkitect.cpp +++ b/dScripts/Darkitect.cpp @@ -1,9 +1,9 @@ #include "Darkitect.h" + #include "MissionComponent.h" #include "DestroyableComponent.h" #include "EntityManager.h" #include "GameMessages.h" -#include "Character.h" #include "eMissionState.h" void Darkitect::Reveal(Entity* self, Entity* player) { @@ -18,15 +18,18 @@ void Darkitect::Reveal(Entity* self, Entity* player) { auto* destroyableComponent = player->GetComponent(); auto* missionComponent = player->GetComponent(); - auto* character = player->GetCharacter(); - if (destroyableComponent != nullptr && missionComponent != nullptr && character != nullptr) { + if (destroyableComponent != nullptr && missionComponent != nullptr) { destroyableComponent->SetArmor(0); destroyableComponent->SetHealth(1); destroyableComponent->SetImagination(0); if (missionComponent->GetMissionState(1295) == eMissionState::ACTIVE) { - character->SetPlayerFlag(1911, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.iFlagId = 1911; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } Game::entityManager->SerializeEntity(player); diff --git a/dScripts/EquipmentTriggers/TrialFactionArmorServer.cpp b/dScripts/EquipmentTriggers/TrialFactionArmorServer.cpp index b59b24aa..99168e6d 100644 --- a/dScripts/EquipmentTriggers/TrialFactionArmorServer.cpp +++ b/dScripts/EquipmentTriggers/TrialFactionArmorServer.cpp @@ -1,16 +1,20 @@ #include "TrialFactionArmorServer.h" -#include "Character.h" #include "ePlayerFlag.h" +#include "GameMessages.h" +#include "EntityManager.h" #include "DestroyableComponent.h" void TrialFactionArmorServer::OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) { - auto* character = itemOwner->GetCharacter(); - if (!character) return; + GameMessages::GetFlag flag{}; + flag.target = itemOwner->GetObjectID(); + flag.iFlagId = ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR; - auto flag = character->GetPlayerFlag(ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR); - if (!flag) { - character->SetPlayerFlag(ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR, true); + if (SEND_ENTITY_MSG(flag) && !flag.bFlag) { + GameMessages::SetFlag setFlag{}; + setFlag.iFlagId = ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); // technically a TimerWithCancel but our current implementation doesnt support this. itemOwner->AddCallbackTimer(1.0f, [itemOwner]() { diff --git a/dScripts/NtFactionSpyServer.cpp b/dScripts/NtFactionSpyServer.cpp index 2d88e4ea..0e6ac8b6 100644 --- a/dScripts/NtFactionSpyServer.cpp +++ b/dScripts/NtFactionSpyServer.cpp @@ -1,11 +1,10 @@ #include "NtFactionSpyServer.h" -#include "Character.h" + #include "ProximityMonitorComponent.h" #include "InventoryComponent.h" #include "GameMessages.h" #include "MissionComponent.h" #include "eMissionState.h" -#include "eReplicaComponentType.h" #include "eCinematicEvent.h" #include "ePlayerFlag.h" @@ -54,12 +53,14 @@ bool NtFactionSpyServer::IsSpy(Entity* self, Entity* possibleSpy) { auto* missionComponent = possibleSpy->GetComponent(); auto* inventoryComponent = possibleSpy->GetComponent(); - auto* character = possibleSpy->GetCharacter(); + GameMessages::GetFlag getFlag{}; + getFlag.target = possibleSpy->GetObjectID(); + getFlag.iFlagId = spyData.flagID; // A player is a spy if they have the spy mission, have the spy equipment equipped and don't have the spy flag set yet return missionComponent != nullptr && missionComponent->GetMissionState(spyData.missionID) == eMissionState::ACTIVE && inventoryComponent != nullptr && inventoryComponent->IsEquipped(spyData.itemID) - && character != nullptr && !character->GetPlayerFlag(spyData.flagID); + && SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag; } void NtFactionSpyServer::OnCinematicUpdate(Entity* self, Entity* sender, eCinematicEvent event, @@ -87,10 +88,11 @@ void NtFactionSpyServer::OnCinematicUpdate(Entity* self, Entity* sender, eCinema } else if (event == eCinematicEvent::ENDED && pathIndex >= dialogueTable.size() - 1) { auto spyData = self->GetVar(m_SpyDataVariable); - auto* character = sender->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(spyData.flagID, true); - } + GameMessages::SetFlag setFlag{}; + setFlag.target = sender->GetObjectID(); + setFlag.iFlagId = spyData.flagID; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } } } diff --git a/dScripts/ai/ACT/FootRace/BaseFootRaceManager.cpp b/dScripts/ai/ACT/FootRace/BaseFootRaceManager.cpp index c5954c4c..4ce9f5ad 100644 --- a/dScripts/ai/ACT/FootRace/BaseFootRaceManager.cpp +++ b/dScripts/ai/ACT/FootRace/BaseFootRaceManager.cpp @@ -1,6 +1,6 @@ #include "BaseFootRaceManager.h" + #include "EntityManager.h" -#include "Character.h" #include "Entity.h" void BaseFootRaceManager::OnStartup(Entity* self) { @@ -21,31 +21,31 @@ void BaseFootRaceManager::OnFireEventServerSide(Entity* self, Entity* sender, st if (eventName == "updatePlayer") { UpdatePlayer(self, player->GetObjectID()); } else if (IsPlayerInActivity(self, player->GetObjectID())) { + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.iFlagId = 115; if (eventName == "initialActivityScore") { - auto* character = player->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(115, true); - } + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); SetActivityScore(self, player->GetObjectID(), 1); } else if (eventName == "updatePlayerTrue") { - auto* character = player->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(115, false); - } + setFlag.bFlag = false; + SEND_ENTITY_MSG(setFlag); UpdatePlayer(self, player->GetObjectID(), true); } else if (eventName == "PlayerWon") { - auto* character = player->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(115, false); - if (param2 != -1) // Certain footraces set a flag - character->SetPlayerFlag(param2, true); + setFlag.bFlag = false; + SEND_ENTITY_MSG(setFlag); + if (param2 != -1) { + setFlag.iFlagId = param2; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } - - StopActivity(self, player->GetObjectID(), 0, param1); - SaveScore(self, player->GetObjectID(), static_cast(param1), static_cast(param2), static_cast(param3)); } + + StopActivity(self, player->GetObjectID(), 0, param1); + SaveScore(self, player->GetObjectID(), static_cast(param1), static_cast(param2), static_cast(param3)); } } } diff --git a/dScripts/ai/FV/FvFreeGfNinjas.cpp b/dScripts/ai/FV/FvFreeGfNinjas.cpp index d690a6f7..778f4ad2 100644 --- a/dScripts/ai/FV/FvFreeGfNinjas.cpp +++ b/dScripts/ai/FV/FvFreeGfNinjas.cpp @@ -1,7 +1,9 @@ #include "FvFreeGfNinjas.h" -#include "Character.h" + #include "MissionComponent.h" #include "eMissionState.h" +#include "Game.h" +#include "EntityManager.h" void FvFreeGfNinjas::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, eMissionState missionState) { if (missionID == 705 && missionState == eMissionState::AVAILABLE) { @@ -14,13 +16,17 @@ void FvFreeGfNinjas::OnMissionDialogueOK(Entity* self, Entity* target, int missi missionComponent->AcceptMission(703); missionComponent->AcceptMission(704); - auto* character = target->GetCharacter(); - if (character != nullptr) - character->SetPlayerFlag(68, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); + setFlag.iFlagId = 68; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } else if (missionID == 786) { - auto* character = target->GetCharacter(); - if (character != nullptr) - character->SetPlayerFlag(81, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); + setFlag.iFlagId = 81; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } } @@ -31,9 +37,11 @@ void FvFreeGfNinjas::OnUse(Entity* self, Entity* user) { return; if (missionComponent->GetMissionState(705) == eMissionState::ACTIVE) { - auto* character = user->GetCharacter(); - if (character != nullptr) - character->SetPlayerFlag(68, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = user->GetObjectID(); + setFlag.iFlagId = 68; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); missionComponent->AcceptMission(701, true); missionComponent->AcceptMission(702, true); diff --git a/dScripts/ai/FV/FvPandaServer.cpp b/dScripts/ai/FV/FvPandaServer.cpp index f29f7f2e..8157ce17 100644 --- a/dScripts/ai/FV/FvPandaServer.cpp +++ b/dScripts/ai/FV/FvPandaServer.cpp @@ -1,6 +1,6 @@ #include "FvPandaServer.h" + #include "PetComponent.h" -#include "Character.h" #include "ePetTamingNotifyType.h" void FvPandaServer::OnStartup(Entity* self) { @@ -19,10 +19,11 @@ void FvPandaServer::OnNotifyPetTamingMinigame(Entity* self, Entity* tamer, ePetT } else if (type == ePetTamingNotifyType::SUCCESS) { // TODO: Remove from groups - auto* character = tamer->GetCharacter(); - if (character != nullptr) { - character->SetPlayerFlag(82, true); - } + GameMessages::SetFlag setFlag{}; + setFlag.target = tamer->GetObjectID(); + setFlag.iFlagId = 82; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } } diff --git a/dScripts/ai/FV/FvPandaSpawnerServer.cpp b/dScripts/ai/FV/FvPandaSpawnerServer.cpp index bc9f1c8a..31fe0dfa 100644 --- a/dScripts/ai/FV/FvPandaSpawnerServer.cpp +++ b/dScripts/ai/FV/FvPandaSpawnerServer.cpp @@ -1,13 +1,15 @@ #include "FvPandaSpawnerServer.h" -#include "Character.h" + #include "EntityManager.h" #include "GameMessages.h" #include "EntityInfo.h" #include "ScriptedActivityComponent.h" void FvPandaSpawnerServer::OnCollisionPhantom(Entity* self, Entity* target) { - auto* character = target->GetCharacter(); - if (character != nullptr && character->GetPlayerFlag(81)) { + GameMessages::GetFlag getFlag{}; + getFlag.target = target->GetObjectID(); + getFlag.iFlagId = 81; + if (SEND_ENTITY_MSG(getFlag) && getFlag.bFlag) { auto raceObjects = Game::entityManager->GetEntitiesInGroup("PandaRaceObject"); if (raceObjects.empty()) diff --git a/dScripts/ai/GF/GfJailkeepMission.cpp b/dScripts/ai/GF/GfJailkeepMission.cpp index b8d4cd30..e835d8f5 100644 --- a/dScripts/ai/GF/GfJailkeepMission.cpp +++ b/dScripts/ai/GF/GfJailkeepMission.cpp @@ -1,6 +1,6 @@ #include "GfJailkeepMission.h" + #include "MissionComponent.h" -#include "Character.h" #include "eMissionState.h" void GfJailkeepMission::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, eMissionState missionState) { @@ -14,8 +14,11 @@ void GfJailkeepMission::OnMissionDialogueOK(Entity* self, Entity* target, int mi missionComponent->AcceptMission(388, true); missionComponent->AcceptMission(390, true); } else if (missionID == 385 && missionState == eMissionState::COMPLETE_READY_TO_COMPLETE) { - auto* character = target->GetCharacter(); - if (character != nullptr && character->GetPlayerFlag(68)) { + GameMessages::GetFlag getFlag{}; + getFlag.target = target->GetObjectID(); + getFlag.iFlagId = 68; + + if (SEND_ENTITY_MSG(getFlag) && getFlag.bFlag) { missionComponent->AcceptMission(701); missionComponent->AcceptMission(702); missionComponent->AcceptMission(703); diff --git a/dScripts/ai/GF/PirateRep.cpp b/dScripts/ai/GF/PirateRep.cpp index 33d6ab63..8b0e26c7 100644 --- a/dScripts/ai/GF/PirateRep.cpp +++ b/dScripts/ai/GF/PirateRep.cpp @@ -1,14 +1,15 @@ #include "PirateRep.h" -#include "Character.h" + #include "eMissionState.h" #include "Entity.h" #include "ePlayerFlag.h" void PirateRep::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, eMissionState missionState) { if (missionID == m_PirateRepMissionID && missionState >= eMissionState::READY_TO_COMPLETE) { - auto* character = target->GetCharacter(); - if (character) { - character->SetPlayerFlag(ePlayerFlag::GF_PIRATE_REP, true); - } + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::GF_PIRATE_REP; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } } diff --git a/dScripts/ai/NS/NsGetFactionMissionServer.cpp b/dScripts/ai/NS/NsGetFactionMissionServer.cpp index 185bd344..0b3f5ec1 100644 --- a/dScripts/ai/NS/NsGetFactionMissionServer.cpp +++ b/dScripts/ai/NS/NsGetFactionMissionServer.cpp @@ -1,7 +1,7 @@ #include "NsGetFactionMissionServer.h" + #include "GameMessages.h" #include "MissionComponent.h" -#include "Character.h" #include "eReplicaComponentType.h" #include "ePlayerFlag.h" @@ -42,11 +42,17 @@ void NsGetFactionMissionServer::OnRespondToMission(Entity* self, int missionID, } if (flagID != -1) { - player->GetCharacter()->SetPlayerFlag(ePlayerFlag::JOINED_A_FACTION, true); - player->GetCharacter()->SetPlayerFlag(flagID, true); + GameMessages::SetFlag setFlag{}; + setFlag.target = player->GetObjectID(); + setFlag.iFlagId = ePlayerFlag::JOINED_A_FACTION; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); + setFlag.iFlagId = flagID; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); } - MissionComponent* mis = static_cast(player->GetComponent(eReplicaComponentType::MISSION)); + auto* mis = player->GetComponent(); for (int mission : factionMissions) { mis->AcceptMission(mission); diff --git a/dScripts/ai/PROPERTY/AG/AgPropGuard.cpp b/dScripts/ai/PROPERTY/AG/AgPropGuard.cpp index e8e94b53..89e92fe2 100644 --- a/dScripts/ai/PROPERTY/AG/AgPropGuard.cpp +++ b/dScripts/ai/PROPERTY/AG/AgPropGuard.cpp @@ -1,6 +1,6 @@ #include "AgPropGuard.h" + #include "Entity.h" -#include "Character.h" #include "EntityManager.h" #include "InventoryComponent.h" #include "MissionComponent.h" @@ -8,13 +8,16 @@ #include "eMissionState.h" void AgPropGuard::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, eMissionState missionState) { - auto* character = target->GetCharacter(); auto* missionComponent = target->GetComponent(); auto* inventoryComponent = target->GetComponent(); + if (!missionComponent || !inventoryComponent) return; const auto state = missionComponent->GetMissionState(320); if (missionID == 768 && missionState == eMissionState::AVAILABLE) { - if (!character->GetPlayerFlag(71)) { + GameMessages::GetFlag getFlag{}; + getFlag.target = target->GetObjectID(); + getFlag.iFlagId = 71; + if (SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { // TODO: Cinematic "MissionCam" } } else if (missionID == 768 && missionState >= eMissionState::READY_TO_COMPLETE) { @@ -27,13 +30,12 @@ void AgPropGuard::OnMissionDialogueOK(Entity* self, Entity* target, int missionI inventoryComponent->RemoveItem(id->GetLot(), id->GetCount()); } } - } else if ( - (missionID == 320 && state == eMissionState::AVAILABLE) /*|| - (state == eMissionState::COMPLETE && missionID == 891 && missionState == eMissionState::READY_TO_COMPLETE)*/ - ) { - //GameMessages::SendNotifyClientObject(Game::entityManager->GetZoneControlEntity()->GetObjectID(), u"GuardChat", target->GetObjectID(), 0, target->GetObjectID(), "", target->GetSystemAddress()); - - target->GetCharacter()->SetPlayerFlag(113, true); + } else if (missionID == 320 && state == eMissionState::AVAILABLE) { + GameMessages::SetFlag setFlag{}; + setFlag.target = target->GetObjectID(); + setFlag.iFlagId = 113; + setFlag.bFlag = true; + SEND_ENTITY_MSG(setFlag); Game::entityManager->GetZoneControlEntity()->AddTimer("GuardFlyAway", 1.0f); } diff --git a/dScripts/ai/PROPERTY/AgPropguards.cpp b/dScripts/ai/PROPERTY/AgPropguards.cpp index ced7dd68..5aa978c3 100644 --- a/dScripts/ai/PROPERTY/AgPropguards.cpp +++ b/dScripts/ai/PROPERTY/AgPropguards.cpp @@ -1,21 +1,21 @@ #include "AgPropguards.h" -#include "Character.h" + #include "GameMessages.h" #include "EntityManager.h" #include "dZoneManager.h" #include "eMissionState.h" void AgPropguards::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, eMissionState missionState) { - auto* character = target->GetCharacter(); - if (character == nullptr) - return; - const auto flag = GetFlagForMission(missionID); if (flag == 0) return; + GameMessages::GetFlag getFlag{}; + getFlag.target = target->GetObjectID(); + getFlag.iFlagId = flag; + if ((missionState == eMissionState::AVAILABLE || missionState == eMissionState::ACTIVE) - && !character->GetPlayerFlag(flag)) { + && SEND_ENTITY_MSG(getFlag) && !getFlag.bFlag) { // If the player just started the mission, play a cinematic highlighting the target GameMessages::SendPlayCinematic(target->GetObjectID(), u"MissionCam", target->GetSystemAddress()); } else if (missionState == eMissionState::READY_TO_COMPLETE) { diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 0bf467de..2d4a58c8 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -1044,10 +1044,12 @@ void HandlePacket(Packet* packet) { switch (version) { case eCharacterVersion::RELEASE: // TODO: Implement, super low priority - case eCharacterVersion::LIVE: + case eCharacterVersion::LIVE: { LOG("Updating Character Flags"); - c->SetRetroactiveFlags(); + GameMessages::SetRetroactiveFlags flags{}; + SEND_ENTITY_MSG(flags); levelComponent->SetCharacterVersion(eCharacterVersion::PLAYER_FACTION_FLAGS); + } case eCharacterVersion::PLAYER_FACTION_FLAGS: LOG("Updating Vault Size"); player->RetroactiveVaultSize();