diff --git a/dGame/dUtilities/VanityUtilities.cpp b/dGame/dUtilities/VanityUtilities.cpp index 95436cd30..6c0085242 100644 --- a/dGame/dUtilities/VanityUtilities.cpp +++ b/dGame/dUtilities/VanityUtilities.cpp @@ -15,6 +15,10 @@ #include "Logger.h" #include "BinaryPathFinder.h" #include "EntityInfo.h" +#include "Spawner.h" +#include "dZoneManager.h" +#include "../dWorldServer/ObjectIDManager.h" +#include "Level.h" #include @@ -29,6 +33,21 @@ void VanityUtilities::SpawnVanity() { const uint32_t zoneID = Game::server->GetZoneID(); + for (const auto& npc : m_NPCs) { + if (npc.m_ID == LWOOBJID_EMPTY) continue; + if (npc.m_LOT == 176){ + Game::zoneManager->RemoveSpawner(npc.m_ID); + } else{ + auto* entity = Game::entityManager->GetEntity(npc.m_ID); + if (!entity) continue; + entity->Smash(LWOOBJID_EMPTY, eKillType::VIOLENT); + } + } + + m_NPCs.clear(); + m_Parties.clear(); + m_PartyPhrases.clear(); + ParseXML((BinaryPathFinder::GetBinaryDir() / "vanity/NPC.xml").string()); // Loop through all parties @@ -53,7 +72,7 @@ void VanityUtilities::SpawnVanity() { // Loop through all locations for (const auto& location : party.m_Locations) { - rate = GeneralUtils::GenerateRandomNumber(0, 1); + rate = GeneralUtils::GenerateRandomNumber(0, 1); if (0.75f < rate) { continue; } @@ -66,10 +85,11 @@ void VanityUtilities::SpawnVanity() { } auto& npc = npcList[npcIndex]; - + // Skip spawners + if (npc.m_LOT == 176) continue; + taken.push_back(npcIndex); - // Spawn the NPC LOG("ldf size is %i", npc.ldf.size()); if (npc.ldf.empty()) { npc.ldf = { @@ -79,13 +99,16 @@ void VanityUtilities::SpawnVanity() { } // Spawn the NPC - auto* npcEntity = SpawnNPC(npc.m_LOT, npc.m_Name, location.m_Position, location.m_Rotation, npc.m_Equipment, npc.ldf); - if (!npc.m_Phrases.empty()) { - npcEntity->SetVar>(u"chats", m_PartyPhrases); - SetupNPCTalk(npcEntity); + if (npc.m_LOT == 176){ + npc.m_ID = SpawnSpawner(npc.m_LOT, location.m_Position, location.m_Rotation, npc.ldf); + } else { + auto* npcEntity = SpawnNPC(npc.m_LOT, npc.m_Name, location.m_Position, location.m_Rotation, npc.m_Equipment, npc.ldf); + if (!npc.m_Phrases.empty()) { + npcEntity->SetVar>(u"chats", m_PartyPhrases); + SetupNPCTalk(npcEntity); + } } } - return; } @@ -111,23 +134,28 @@ void VanityUtilities::SpawnVanity() { new LDFData(u"custom_script_client", u"scripts\\ai\\SPEC\\MISSION_MINIGAME_CLIENT.lua") }; } + if (npc.m_LOT == 176){ + npc.m_ID = SpawnSpawner(npc.m_LOT, location.m_Position, location.m_Rotation, npc.ldf); + } else { + // Spawn the NPC + auto* npcEntity = SpawnNPC(npc.m_LOT, npc.m_Name, location.m_Position, location.m_Rotation, npc.m_Equipment, npc.ldf); + if (!npcEntity) continue; + npc.m_ID = npcEntity->GetObjectID(); + if (!npc.m_Phrases.empty()){ + npcEntity->SetVar>(u"chats", npc.m_Phrases); - // Spawn the NPC - auto* npcEntity = SpawnNPC(npc.m_LOT, npc.m_Name, location.m_Position, location.m_Rotation, npc.m_Equipment, npc.ldf); - if (!npc.m_Phrases.empty()){ - npcEntity->SetVar>(u"chats", npc.m_Phrases); - - auto* scriptComponent = npcEntity->GetComponent(); + auto* scriptComponent = npcEntity->GetComponent(); - if (scriptComponent && !npc.m_Script.empty()) { - scriptComponent->SetScript(npc.m_Script); - scriptComponent->SetSerialized(false); + if (scriptComponent && !npc.m_Script.empty()) { + scriptComponent->SetScript(npc.m_Script); + scriptComponent->SetSerialized(false); - for (const auto& npc : npc.m_Flags) { - npcEntity->SetVar(GeneralUtils::ASCIIToUTF16(npc.first), npc.second); + for (const auto& npc : npc.m_Flags) { + npcEntity->SetVar(GeneralUtils::ASCIIToUTF16(npc.first), npc.second); + } } + SetupNPCTalk(npcEntity); } - SetupNPCTalk(npcEntity); } } @@ -149,8 +177,21 @@ void VanityUtilities::SpawnVanity() { } } -Entity* VanityUtilities::SpawnNPC(LOT lot, const std::string& name, const NiPoint3& position, - const NiQuaternion& rotation, const std::vector& inventory, const std::vector& ldf) { +LWOOBJID VanityUtilities::SpawnSpawner(LOT lot, const NiPoint3& position, const NiQuaternion& rotation, const std::vector& ldf){ + SceneObject obj; + obj.lot = lot; + // guratantee we have no collisions + do { + obj.id = ObjectIDManager::Instance()->GenerateObjectID(); + } while(Game::zoneManager->GetSpawner(obj.id)); + obj.position = position; + obj.rotation = rotation; + obj.settings = ldf; + Level::MakeSpawner(obj); + return obj.id; +} + +Entity* VanityUtilities::SpawnNPC(LOT lot, const std::string& name, const NiPoint3& position, const NiQuaternion& rotation, const std::vector& inventory, const std::vector& ldf) { EntityInfo info; info.lot = lot; info.pos = position; diff --git a/dGame/dUtilities/VanityUtilities.h b/dGame/dUtilities/VanityUtilities.h index 0cca0abaf..cff73bce2 100644 --- a/dGame/dUtilities/VanityUtilities.h +++ b/dGame/dUtilities/VanityUtilities.h @@ -13,6 +13,7 @@ struct VanityNPCLocation struct VanityNPC { + LWOOBJID m_ID = LWOOBJID_EMPTY; std::string m_Name; LOT m_LOT; std::vector m_Equipment; @@ -44,6 +45,13 @@ class VanityUtilities const std::vector& ldf ); + static LWOOBJID SpawnSpawner( + LOT lot, + const NiPoint3& position, + const NiQuaternion& rotation, + const std::vector& ldf + ); + static std::string ParseMarkdown( const std::string& file ); diff --git a/dZoneManager/Level.cpp b/dZoneManager/Level.cpp index 953b11e22..4c83d494a 100644 --- a/dZoneManager/Level.cpp +++ b/dZoneManager/Level.cpp @@ -38,6 +38,76 @@ Level::~Level() { } } +void Level::MakeSpawner(SceneObject obj){ + SpawnerInfo spawnInfo = SpawnerInfo(); + SpawnerNode* node = new SpawnerNode(); + spawnInfo.templateID = obj.lot; + spawnInfo.spawnerID = obj.id; + spawnInfo.templateScale = obj.scale; + node->position = obj.position; + node->rotation = obj.rotation; + node->config = obj.settings; + spawnInfo.nodes.push_back(node); + for (LDFBaseData* data : obj.settings) { + if (data) { + if (data->GetKey() == u"spawntemplate") { + spawnInfo.templateID = std::stoi(data->GetValueAsString()); + } + + if (data->GetKey() == u"spawner_node_id") { + node->nodeID = std::stoi(data->GetValueAsString()); + } + + if (data->GetKey() == u"spawner_name") { + spawnInfo.name = data->GetValueAsString(); + } + + if (data->GetKey() == u"max_to_spawn") { + spawnInfo.maxToSpawn = std::stoi(data->GetValueAsString()); + } + + if (data->GetKey() == u"spawner_active_on_load") { + spawnInfo.activeOnLoad = std::stoi(data->GetValueAsString()); + } + + if (data->GetKey() == u"active_on_load") { + spawnInfo.activeOnLoad = std::stoi(data->GetValueAsString()); + } + + if (data->GetKey() == u"respawn") { + if (data->GetValueType() == eLDFType::LDF_TYPE_FLOAT) // Floats are in seconds + { + spawnInfo.respawnTime = std::stof(data->GetValueAsString()); + } else if (data->GetValueType() == eLDFType::LDF_TYPE_U32) // Ints are in ms? + { + spawnInfo.respawnTime = std::stoul(data->GetValueAsString()) / 1000; + } + } + if (data->GetKey() == u"spawnsGroupOnSmash") { + spawnInfo.spawnsOnSmash = std::stoi(data->GetValueAsString()); + } + if (data->GetKey() == u"spawnNetNameForSpawnGroupOnSmash") { + spawnInfo.spawnOnSmashGroupName = data->GetValueAsString(); + } + if (data->GetKey() == u"groupID") { // Load object groups + std::string groupStr = data->GetValueAsString(); + spawnInfo.groups = GeneralUtils::SplitString(groupStr, ';'); + spawnInfo.groups.erase(spawnInfo.groups.end() - 1); + } + if (data->GetKey() == u"no_auto_spawn") { + spawnInfo.noAutoSpawn = static_cast*>(data)->GetValue(); + } + if (data->GetKey() == u"no_timed_spawn") { + spawnInfo.noTimedSpawn = static_cast*>(data)->GetValue(); + } + if (data->GetKey() == u"spawnActivator") { + spawnInfo.spawnActivator = static_cast*>(data)->GetValue(); + } + } + } + Game::zoneManager->MakeSpawner(spawnInfo); +} + const void Level::PrintAllObjects() { for (std::map::iterator it = m_ChunkHeaders.begin(); it != m_ChunkHeaders.end(); ++it) { if (it->second.id == Level::ChunkTypeID::SceneObjectData) { @@ -230,74 +300,7 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) { } if (obj.lot == 176) { //Spawner - SpawnerInfo spawnInfo = SpawnerInfo(); - SpawnerNode* node = new SpawnerNode(); - spawnInfo.templateID = obj.lot; - spawnInfo.spawnerID = obj.id; - spawnInfo.templateScale = obj.scale; - node->position = obj.position; - node->rotation = obj.rotation; - node->config = obj.settings; - spawnInfo.nodes.push_back(node); - for (LDFBaseData* data : obj.settings) { - if (data) { - if (data->GetKey() == u"spawntemplate") { - spawnInfo.templateID = std::stoi(data->GetValueAsString()); - } - - if (data->GetKey() == u"spawner_node_id") { - node->nodeID = std::stoi(data->GetValueAsString()); - } - - if (data->GetKey() == u"spawner_name") { - spawnInfo.name = data->GetValueAsString(); - } - - if (data->GetKey() == u"max_to_spawn") { - spawnInfo.maxToSpawn = std::stoi(data->GetValueAsString()); - } - - if (data->GetKey() == u"spawner_active_on_load") { - spawnInfo.activeOnLoad = std::stoi(data->GetValueAsString()); - } - - if (data->GetKey() == u"active_on_load") { - spawnInfo.activeOnLoad = std::stoi(data->GetValueAsString()); - } - - if (data->GetKey() == u"respawn") { - if (data->GetValueType() == eLDFType::LDF_TYPE_FLOAT) // Floats are in seconds - { - spawnInfo.respawnTime = std::stof(data->GetValueAsString()); - } else if (data->GetValueType() == eLDFType::LDF_TYPE_U32) // Ints are in ms? - { - spawnInfo.respawnTime = std::stoul(data->GetValueAsString()) / 1000; - } - } - if (data->GetKey() == u"spawnsGroupOnSmash") { - spawnInfo.spawnsOnSmash = std::stoi(data->GetValueAsString()); - } - if (data->GetKey() == u"spawnNetNameForSpawnGroupOnSmash") { - spawnInfo.spawnOnSmashGroupName = data->GetValueAsString(); - } - if (data->GetKey() == u"groupID") { // Load object groups - std::string groupStr = data->GetValueAsString(); - spawnInfo.groups = GeneralUtils::SplitString(groupStr, ';'); - spawnInfo.groups.erase(spawnInfo.groups.end() - 1); - } - if (data->GetKey() == u"no_auto_spawn") { - spawnInfo.noAutoSpawn = static_cast*>(data)->GetValue(); - } - if (data->GetKey() == u"no_timed_spawn") { - spawnInfo.noTimedSpawn = static_cast*>(data)->GetValue(); - } - if (data->GetKey() == u"spawnActivator") { - spawnInfo.spawnActivator = static_cast*>(data)->GetValue(); - } - } - } - Spawner* spawner = new Spawner(spawnInfo); - Game::zoneManager->AddSpawner(obj.id, spawner); + MakeSpawner(obj); } else { //Regular object EntityInfo info; info.spawnerID = 0; diff --git a/dZoneManager/Level.h b/dZoneManager/Level.h index 0f8fa72d6..a27326a21 100644 --- a/dZoneManager/Level.h +++ b/dZoneManager/Level.h @@ -53,6 +53,8 @@ class Level { public: Level(Zone* parentZone, const std::string& filepath); ~Level(); + + static void MakeSpawner(SceneObject obj); const void PrintAllObjects();