mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-06-09 00:04:22 +00:00
fix: security vulnerabilities
Tested that all functions related to the touched files work will test sqlite on a CI build
This commit is contained in:
@@ -36,13 +36,14 @@ void AmSkullkinDrill::OnStartup(Entity* self) {
|
||||
Entity* AmSkullkinDrill::GetStandObj(Entity* self) {
|
||||
const auto& myGroup = self->GetGroups();
|
||||
|
||||
if (myGroup.empty()) {
|
||||
if (myGroup.empty() || myGroup[0].empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto& group = myGroup[0];
|
||||
|
||||
std::string groupName = "Drill_Stand_";
|
||||
|
||||
groupName.push_back(myGroup[0][myGroup[0].size() - 1]);
|
||||
groupName.push_back(group.back());
|
||||
|
||||
const auto standObjs = Game::entityManager->GetEntitiesInGroup(groupName);
|
||||
|
||||
|
||||
@@ -7,9 +7,14 @@
|
||||
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);
|
||||
const int32_t flag = GeneralUtils::TryParse(std::to_string(Game::server->GetZoneID()).substr(0, 2) + number, 0);
|
||||
GameMessages::GetFlag flagMsg;
|
||||
flagMsg.target = user->GetObjectID();
|
||||
flagMsg.flagID = flag;
|
||||
flagMsg.Send();
|
||||
if (!flagMsg.flag) {
|
||||
auto* const character = user->GetCharacter();
|
||||
if (character) character->SetPlayerFlag(flag, true);
|
||||
GameMessages::SendFireEventClientSide(self->GetObjectID(), user->GetSystemAddress(), u"achieve", LWOOBJID_EMPTY, 0, -1, LWOOBJID_EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,14 +33,18 @@ void StoryBoxInteractServer::OnUse(Entity* self, Entity* user) {
|
||||
const auto storyText = self->GetVarAsString(u"storyText");
|
||||
if (storyText.length() > 2) {
|
||||
auto storyValue = GeneralUtils::TryParse<uint32_t>(storyText.substr(storyText.length() - 2));
|
||||
if(!storyValue) return;
|
||||
if (!storyValue) return;
|
||||
int32_t boxFlag = self->GetVar<int32_t>(u"altFlagID");
|
||||
if (boxFlag <= 0) {
|
||||
boxFlag = (10000 + Game::server->GetZoneID() + storyValue.value());
|
||||
}
|
||||
|
||||
if (user->GetCharacter()->GetPlayerFlag(boxFlag) == false) {
|
||||
user->GetCharacter()->SetPlayerFlag(boxFlag, true);
|
||||
GameMessages::GetFlag flagMsg;
|
||||
flagMsg.target = user->GetObjectID();
|
||||
flagMsg.flagID = boxFlag;
|
||||
flagMsg.Send();
|
||||
if (!flagMsg.flag) {
|
||||
auto* const character = user->GetCharacter();
|
||||
if (character) user->GetCharacter()->SetPlayerFlag(boxFlag, true);
|
||||
GameMessages::SendFireEventClientSide(self->GetObjectID(), user->GetSystemAddress(), u"achieve", LWOOBJID_EMPTY, 0, -1, LWOOBJID_EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ void NsConcertChoiceBuildManager::SpawnCrate(Entity* self) {
|
||||
const auto splitGroup = GeneralUtils::SplitString(group, '_');
|
||||
if (splitGroup.size() < 2)
|
||||
return;
|
||||
const auto groupNumber = std::stoi(splitGroup.at(1));
|
||||
const auto groupNumber = GeneralUtils::TryParse(splitGroup.at(1), -1);
|
||||
if (groupNumber == -1) return;
|
||||
|
||||
EntityInfo info{};
|
||||
info.lot = crate.lot;
|
||||
|
||||
@@ -33,7 +33,8 @@ void NtParadoxPanelServer::OnUse(Entity* self, Entity* user) {
|
||||
|
||||
const auto flag = self->GetVar<int32_t>(u"flag");
|
||||
|
||||
player->GetCharacter()->SetPlayerFlag(flag, true);
|
||||
auto* const character = player->GetCharacter();
|
||||
if (character) character->SetPlayerFlag(flag, true);
|
||||
|
||||
RenderComponent::PlayAnimation(player, u"rebuild-celebrate");
|
||||
|
||||
|
||||
@@ -413,7 +413,8 @@ void ZoneAgProperty::BaseOnFireEventServerSide(Entity* self, Entity* sender, std
|
||||
if (player == nullptr)
|
||||
return;
|
||||
|
||||
player->GetCharacter()->SetPlayerFlag(self->GetVar<int32_t>(defeatedProperyFlag), true);
|
||||
auto* const character = player->GetCharacter();
|
||||
if (character) character->SetPlayerFlag(self->GetVar<int32_t>(defeatedProperyFlag), true);
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PlayCinematic", 0, 0,
|
||||
LWOOBJID_EMPTY, destroyedCinematic, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ void VeMissionConsole::OnUse(Entity* self, Entity* user) {
|
||||
|
||||
// The flag to set is 101<number>
|
||||
const auto flagNumber = self->GetVar<std::u16string>(m_NumberVariable);
|
||||
const int32_t flag = std::stoi("101" + GeneralUtils::UTF16ToWTF8(flagNumber));
|
||||
const int32_t flag = GeneralUtils::TryParse("101" + GeneralUtils::UTF16ToWTF8(flagNumber), 0);
|
||||
|
||||
auto* character = user->GetCharacter();
|
||||
if (character != nullptr) {
|
||||
|
||||
@@ -13,7 +13,10 @@ void CavePrisonCage::OnStartup(Entity* self) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* spawner = Game::zoneManager->GetSpawnersByName("PrisonCounterweight_0" + GeneralUtils::UTF16ToWTF8(myNum))[0];
|
||||
const auto spawners = Game::zoneManager->GetSpawnersByName("PrisonCounterweight_0" + GeneralUtils::UTF16ToWTF8(myNum));
|
||||
if (spawners.empty()) return;
|
||||
|
||||
auto* spawner = spawners[0];
|
||||
|
||||
self->SetVar<Spawner*>(u"CWSpawner", spawner);
|
||||
|
||||
@@ -21,6 +24,7 @@ void CavePrisonCage::OnStartup(Entity* self) {
|
||||
}
|
||||
|
||||
void CavePrisonCage::Setup(Entity* self, Spawner* spawner) {
|
||||
if (!spawner) return;
|
||||
SpawnCounterweight(self, spawner);
|
||||
|
||||
NiPoint3 mypos = self->GetPosition();
|
||||
@@ -62,6 +66,8 @@ void CavePrisonCage::OnQuickBuildNotifyState(Entity* self, eQuickBuildState stat
|
||||
}
|
||||
|
||||
void CavePrisonCage::SpawnCounterweight(Entity* self, Spawner* spawner) {
|
||||
if (!spawner) return;
|
||||
|
||||
spawner->Reset();
|
||||
|
||||
auto* counterweight = spawner->Spawn();
|
||||
@@ -164,7 +170,8 @@ void CavePrisonCage::OnTimerDone(Entity* self, std::string timerName) {
|
||||
const auto flagNum = 2020 + self->GetVarAs<int32_t>(u"myNumber");
|
||||
|
||||
// Set the flag on the builder character
|
||||
builder->GetCharacter()->SetPlayerFlag(flagNum, true);
|
||||
auto* const character = builder->GetCharacter();
|
||||
if (character) character->SetPlayerFlag(flagNum, true);
|
||||
|
||||
// Setup a timer named 'VillagerEscape' to be triggered in 5 seconds
|
||||
self->AddTimer("VillagerEscape", 5.0f);
|
||||
|
||||
@@ -408,7 +408,7 @@ void NjMonastryBossInstance::SummonWave(Entity* self, Entity* frakjaw) {
|
||||
|
||||
// Stop the music for the first, fourth and fifth wave
|
||||
const auto wave = self->GetVar<uint32_t>(WaveNumberVariable);
|
||||
if (wave >= 1 || wave < (m_Waves.size() - 1)) {
|
||||
if (wave >= 1 && wave < (m_Waves.size() - 1)) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), StopMusicNotification, 0, 0,
|
||||
LWOOBJID_EMPTY, AudioWaveAudio + std::to_string(wave - 1),
|
||||
UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
@@ -96,7 +96,7 @@ void BaseConsoleTeleportServer::TransferPlayer(Entity* self, Entity* player, int
|
||||
|
||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||
|
||||
if (characterComponent) characterComponent->SendToZone(std::stoi(GeneralUtils::UTF16ToWTF8(teleportZone)));
|
||||
if (characterComponent) characterComponent->SendToZone(GeneralUtils::TryParse(GeneralUtils::UTF16ToWTF8(teleportZone), 0));
|
||||
|
||||
UpdatePlayerTable(self, player, false);
|
||||
}
|
||||
|
||||
@@ -127,12 +127,15 @@ void BasePropertyServer::BasePlayerLoaded(Entity* self, Entity* player) {
|
||||
if (player->GetObjectID() != propertyOwner)
|
||||
return;
|
||||
} else {
|
||||
const auto defeatedFlag = player->GetCharacter()->GetPlayerFlag(self->GetVar<int32_t>(defeatedProperyFlag));
|
||||
GameMessages::GetFlag flagMsg;
|
||||
flagMsg.target = player->GetObjectID();
|
||||
flagMsg.flagID = self->GetVar<int32_t>(defeatedProperyFlag);
|
||||
flagMsg.Send();
|
||||
|
||||
self->SetNetworkVar(UnclaimedVariable, true);
|
||||
self->SetVar<LWOOBJID>(PlayerIDVariable, player->GetObjectID());
|
||||
|
||||
if (!defeatedFlag) {
|
||||
if (!flagMsg.flag) {
|
||||
StartMaelstrom(self, player);
|
||||
SpawnSpots(self);
|
||||
GameMessages::SendPlay2DAmbientSound(player, GUIDMaelstrom);
|
||||
|
||||
@@ -124,21 +124,23 @@ void BaseRandomServer::NotifySpawnerOfDeath(Entity* self, Spawner* spawner) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& sectionName = spawnerName.substr(0, spawnerName.size() - 7);
|
||||
if (spawnerName.size() >= 7) {
|
||||
const auto& sectionName = spawnerName.substr(0, spawnerName.size() - 7);
|
||||
|
||||
const auto variableName = u"mobsDead" + GeneralUtils::ASCIIToUTF16(sectionName);
|
||||
const auto variableName = u"mobsDead" + GeneralUtils::ASCIIToUTF16(sectionName);
|
||||
|
||||
auto mobDeathCount = self->GetVar<int32_t>(variableName);
|
||||
auto mobDeathCount = self->GetVar<int32_t>(variableName);
|
||||
|
||||
mobDeathCount++;
|
||||
mobDeathCount++;
|
||||
|
||||
if (mobDeathCount >= mobDeathResetNumber) {
|
||||
const auto& zoneInfo = GeneralUtils::SplitString(sectionName, '_');
|
||||
if (mobDeathCount >= mobDeathResetNumber) {
|
||||
const auto& zoneInfo = GeneralUtils::SplitString(sectionName, '_');
|
||||
|
||||
SpawnSection(self, sectionName, sectionMultipliers[zoneInfo[sectionIDConst - 1]]);
|
||||
SpawnSection(self, sectionName, sectionMultipliers[zoneInfo[sectionIDConst - 1]]);
|
||||
}
|
||||
|
||||
self->SetVar(variableName, mobDeathCount);
|
||||
}
|
||||
|
||||
self->SetVar(variableName, mobDeathCount);
|
||||
}
|
||||
|
||||
void BaseRandomServer::NamedEnemyDeath(Entity* self, Spawner* spawner) {
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
void NamedTimerDone(Entity* self, const std::string& timerName);
|
||||
|
||||
protected:
|
||||
std::vector<int32_t> namedMobs = {
|
||||
const std::vector<int32_t> namedMobs = {
|
||||
11988, // Ronin
|
||||
11984, // Spiderling
|
||||
12654, // Horsemen
|
||||
|
||||
@@ -24,7 +24,8 @@ void BaseSurvivalServer::BasePlayerLoaded(Entity* self, Entity* player) {
|
||||
|
||||
if (waitingIter != state.waitingPlayers.end() || playersIter != state.players.end()) {
|
||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||
if (characterComponent) characterComponent->SendToZone(player->GetCharacter()->GetLastNonInstanceZoneID());
|
||||
const auto* const character = player->GetCharacter();
|
||||
if (characterComponent && character) characterComponent->SendToZone(character->GetLastNonInstanceZoneID());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ void NtFactionSpyServer::OnCinematicUpdate(Entity* self, Entity* sender, eCinema
|
||||
// Make sure we have a path of type <root>_<index>
|
||||
if (pathSplit.size() >= 2) {
|
||||
auto pathRoot = pathSplit.at(0);
|
||||
auto pathIndex = std::stoi(GeneralUtils::UTF16ToWTF8(pathSplit.at(1))) - 1;
|
||||
auto pathIndex = GeneralUtils::TryParse(GeneralUtils::UTF16ToWTF8(pathSplit.at(1)), -1) - 1;
|
||||
const auto& dialogueTable = self->GetVar<std::vector<SpyDialogue>>(m_SpyDialogueTableVariable);
|
||||
|
||||
// Make sure we're listening to the root we're interested in
|
||||
|
||||
@@ -57,7 +57,7 @@ bool SpawnPetBaseServer::CheckNumberOfPets(Entity* self, Entity* user) {
|
||||
if (petID.empty())
|
||||
continue;
|
||||
|
||||
const auto* spawnedPet = Game::entityManager->GetEntity(std::stoull(petID));
|
||||
const auto* spawnedPet = Game::entityManager->GetEntity(GeneralUtils::TryParse(petID, LWOOBJID_EMPTY));
|
||||
if (spawnedPet == nullptr)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -24,8 +24,11 @@ void AgFans::OnStartup(Entity* self) {
|
||||
}
|
||||
|
||||
void AgFans::ToggleFX(Entity* self, bool hit) {
|
||||
std::string fanGroup = self->GetGroups()[0];
|
||||
std::vector<Entity*> fanVolumes = Game::entityManager->GetEntitiesInGroup(fanGroup);
|
||||
const auto groups = self->GetGroups();
|
||||
std::string fanGroup = groups.empty() ? "" : groups[0];
|
||||
const auto fanVolumes = Game::entityManager->GetEntitiesInGroup(fanGroup);
|
||||
const auto fxObjs = Game::entityManager->GetEntitiesInGroup(fanGroup + "fx");
|
||||
auto* const fxObj = fxObjs.empty() ? nullptr : fxObjs[0];
|
||||
|
||||
auto* renderComponent = static_cast<RenderComponent*>(self->GetComponent(eReplicaComponentType::RENDER));
|
||||
|
||||
@@ -47,8 +50,7 @@ void AgFans::ToggleFX(Entity* self, bool hit) {
|
||||
volumePhys->SetPhysicsEffectActive(false);
|
||||
Game::entityManager->SerializeEntity(volume);
|
||||
if (!hit) {
|
||||
Entity* fxObj = Game::entityManager->GetEntitiesInGroup(fanGroup + "fx")[0];
|
||||
RenderComponent::PlayAnimation(fxObj, u"trigger");
|
||||
if (fxObj) RenderComponent::PlayAnimation(fxObj, u"trigger");
|
||||
}
|
||||
}
|
||||
} else if (!self->GetVar<bool>(u"on") && self->GetVar<bool>(u"alive")) {
|
||||
@@ -63,8 +65,7 @@ void AgFans::ToggleFX(Entity* self, bool hit) {
|
||||
volumePhys->SetPhysicsEffectActive(true);
|
||||
Game::entityManager->SerializeEntity(volume);
|
||||
if (!hit) {
|
||||
Entity* fxObj = Game::entityManager->GetEntitiesInGroup(fanGroup + "fx")[0];
|
||||
RenderComponent::PlayAnimation(fxObj, u"idle");
|
||||
if (fxObj) RenderComponent::PlayAnimation(fxObj, u"idle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
void FvBrickPuzzleServer::OnStartup(Entity* self) {
|
||||
const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name"));
|
||||
if (myGroup.size() <= 10) return;
|
||||
|
||||
const auto pipeNum = GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1));
|
||||
if (!pipeNum) return;
|
||||
@@ -17,6 +18,7 @@ void FvBrickPuzzleServer::OnStartup(Entity* self) {
|
||||
|
||||
void FvBrickPuzzleServer::OnDie(Entity* self, Entity* killer) {
|
||||
const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name"));
|
||||
if (myGroup.size() <= 10) return;
|
||||
|
||||
const auto pipeNum = GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1));
|
||||
if (!pipeNum) return;
|
||||
|
||||
@@ -9,9 +9,12 @@ void FvFacilityBrick::OnStartup(Entity* self) {
|
||||
}
|
||||
|
||||
void FvFacilityBrick::OnNotifyObject(Entity* self, Entity* sender, const std::string& name, int32_t param1, int32_t param2) {
|
||||
auto* brickSpawner = Game::zoneManager->GetSpawnersByName("ImaginationBrick")[0];
|
||||
auto* bugSpawner = Game::zoneManager->GetSpawnersByName("MaelstromBug")[0];
|
||||
auto* canisterSpawner = Game::zoneManager->GetSpawnersByName("BrickCanister")[0];
|
||||
const auto brickObjs = Game::zoneManager->GetSpawnersByName("ImaginationBrick");
|
||||
auto* const brickSpawner = brickObjs.empty() ? nullptr : brickObjs[0];
|
||||
const auto bugObjs = Game::zoneManager->GetSpawnersByName("MaelstromBug");
|
||||
auto* const bugSpawner = bugObjs.empty() ? nullptr : bugObjs[0];
|
||||
const auto canisterObjs = Game::zoneManager->GetSpawnersByName("BrickCanister");
|
||||
auto* const canisterSpawner = canisterObjs.empty() ? nullptr : canisterObjs[0];
|
||||
|
||||
if (name == "ConsoleLeftUp") {
|
||||
GameMessages::SendStopFXEffect(self, true, "LeftPipeOff");
|
||||
@@ -62,7 +65,7 @@ void FvFacilityBrick::OnNotifyObject(Entity* self, Entity* sender, const std::st
|
||||
canisterSpawner->Reset();
|
||||
canisterSpawner->Deactivate();
|
||||
} else if (self->GetVar<bool>(u"ConsoleLEFTActive") || self->GetVar<bool>(u"ConsoleRIGHTActive")) {
|
||||
brickSpawner->Activate();
|
||||
if (brickSpawner) brickSpawner->Activate();
|
||||
|
||||
auto* object = Game::entityManager->GetEntitiesInGroup("Brick")[0];
|
||||
|
||||
@@ -70,17 +73,25 @@ void FvFacilityBrick::OnNotifyObject(Entity* self, Entity* sender, const std::st
|
||||
GameMessages::SendStopFXEffect(object, true, "bluebrick");
|
||||
}
|
||||
|
||||
bugSpawner->Reset();
|
||||
bugSpawner->Deactivate();
|
||||
if (bugSpawner) {
|
||||
bugSpawner->Reset();
|
||||
bugSpawner->Deactivate();
|
||||
}
|
||||
|
||||
canisterSpawner->Reset();
|
||||
canisterSpawner->Activate();
|
||||
if (canisterSpawner) {
|
||||
canisterSpawner->Reset();
|
||||
canisterSpawner->Activate();
|
||||
}
|
||||
} else {
|
||||
brickSpawner->Reset();
|
||||
brickSpawner->Deactivate();
|
||||
if (brickSpawner) {
|
||||
brickSpawner->Reset();
|
||||
brickSpawner->Deactivate();
|
||||
}
|
||||
|
||||
bugSpawner->Reset();
|
||||
bugSpawner->Activate();
|
||||
if (bugSpawner) {
|
||||
bugSpawner->Reset();
|
||||
bugSpawner->Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ void SGCannon::GameOverTimerFunc(Entity* self) {
|
||||
|
||||
void SGCannon::DoSpawnTimerFunc(Entity* self, const std::string& name) {
|
||||
if (self->GetVar<bool>(GameStartedVariable)) {
|
||||
const auto spawnNumber = static_cast<uint32_t>(std::stoi(name.substr(7)));
|
||||
const auto spawnNumber = GeneralUtils::TryParse(name.substr(7), 0);
|
||||
const auto& activeSpawns = self->GetVar<std::vector<SGEnemy>>(ActiveSpawnsVariable);
|
||||
if (activeSpawns.size() <= spawnNumber) {
|
||||
LOG_DEBUG("Trying to spawn %i when spawns size is only %i", spawnNumber, activeSpawns.size());
|
||||
|
||||
@@ -41,7 +41,9 @@ void NsConcertQuickBuild::OnStartup(Entity* self) {
|
||||
return;
|
||||
|
||||
// Get the manager of the crate of this quick build
|
||||
const auto groupNumber = std::stoi(splitGroup.at(3));
|
||||
const auto groupNumber = GeneralUtils::TryParse(splitGroup.at(3), -1);
|
||||
if (groupNumber == -1) return;
|
||||
|
||||
const auto managerObjects = Game::entityManager->GetEntitiesInGroup("CB_" + std::to_string(groupNumber));
|
||||
if (managerObjects.empty())
|
||||
return;
|
||||
|
||||
@@ -42,8 +42,11 @@ void NsGetFactionMissionServer::OnRespondToMission(Entity* self, int missionID,
|
||||
}
|
||||
|
||||
if (flagID != -1) {
|
||||
player->GetCharacter()->SetPlayerFlag(ePlayerFlag::JOINED_A_FACTION, true);
|
||||
player->GetCharacter()->SetPlayerFlag(flagID, true);
|
||||
auto* const character = player->GetCharacter();
|
||||
if (character) {
|
||||
character->SetPlayerFlag(ePlayerFlag::JOINED_A_FACTION, true);
|
||||
character->SetPlayerFlag(flagID, true);
|
||||
}
|
||||
}
|
||||
|
||||
MissionComponent* mis = static_cast<MissionComponent*>(player->GetComponent(eReplicaComponentType::MISSION));
|
||||
|
||||
@@ -33,7 +33,8 @@ void AgPropGuard::OnMissionDialogueOK(Entity* self, Entity* target, int missionI
|
||||
) {
|
||||
//GameMessages::SendNotifyClientObject(Game::entityManager->GetZoneControlEntity()->GetObjectID(), u"GuardChat", target->GetObjectID(), 0, target->GetObjectID(), "", target->GetSystemAddress());
|
||||
|
||||
target->GetCharacter()->SetPlayerFlag(113, true);
|
||||
auto* const character = target->GetCharacter();
|
||||
if (character) character->SetPlayerFlag(113, true);
|
||||
|
||||
Game::entityManager->GetZoneControlEntity()->AddTimer("GuardFlyAway", 1.0f);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user