mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-26 07:27:18 +00:00
455f9470a5
* Move EntityManager to Game namespace * move initialization to later Need to wait for dZoneManager to be initialized. * Fix bugs - Cannot delete from a RandomAccessIterator while in a range based for loop. Touchup zone manager initialize replace magic numbers with better named constants replace magic zonecontrol id with a more readable hex alternative condense stack variables move initializers closer to their use initialize entity manager with zone control change initialize timings If zone is not zero we expect to initialize the entity manager during zone manager initialization Add constexpr for zone control LOT * Add proper error handling * revert vanity changes * Update WorldServer.cpp * Update dZoneManager.cpp
237 lines
7.8 KiB
C++
237 lines
7.8 KiB
C++
#include "dZoneManager.h"
|
|
#include "PetDigServer.h"
|
|
#include "MissionComponent.h"
|
|
#include "EntityManager.h"
|
|
#include "Character.h"
|
|
#include "PetComponent.h"
|
|
#include "User.h"
|
|
#include "eMissionState.h"
|
|
|
|
std::vector<LWOOBJID> PetDigServer::treasures{};
|
|
|
|
const DigInfo PetDigServer::defaultDigInfo = DigInfo{ 3495, -1, -1, false, false, false, false };
|
|
|
|
/**
|
|
* Summary of all the special treasure behaviors, indexed by their lot
|
|
*/
|
|
const std::map<LOT, DigInfo> PetDigServer::digInfoMap{
|
|
// Regular treasures
|
|
{3495, defaultDigInfo},
|
|
|
|
// Pet cove treasure
|
|
{7612, DigInfo { 7612, -1, -1, false, false, false, false }},
|
|
|
|
// Gnarled Forest flag treasure
|
|
{7410, DigInfo { 7410, -1, -1, false, true, false, false }},
|
|
|
|
// Gnarled Forest crab treasure
|
|
{9308, DigInfo { 9308, 7694, -1, false, false, false, false }},
|
|
|
|
// Avant Gardens mission treasure
|
|
{9307, DigInfo { 9307, -1, -1, false, true, false, true }},
|
|
|
|
// Avant Gardens bouncer treasure
|
|
{7559, DigInfo { 7559, -1, -1, false, false, true, false }},
|
|
|
|
// Crux Prime dragon treasure
|
|
{13098, DigInfo { 13098, 13067, 1298, false, false, false, false }},
|
|
|
|
// Bone treasure (can only be digged using the dragon)
|
|
{12192, DigInfo { 12192, -1, -1, true, false, false, false }},
|
|
};
|
|
|
|
void PetDigServer::OnStartup(Entity* self) {
|
|
treasures.push_back(self->GetObjectID());
|
|
const auto digInfoIterator = digInfoMap.find(self->GetLOT());
|
|
const auto digInfo = digInfoIterator != digInfoMap.end() ? digInfoIterator->second : defaultDigInfo;
|
|
|
|
// Reset any bouncers that might've been created by the previous dig
|
|
if (digInfo.bouncer) {
|
|
auto bounceNumber = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"BouncerNumber"));
|
|
auto bouncerSpawners = dZoneManager::Instance()->GetSpawnersByName("PetBouncer" + bounceNumber);
|
|
auto switchSpawners = dZoneManager::Instance()->GetSpawnersByName("PetBouncerSwitch" + bounceNumber);
|
|
|
|
for (auto* bouncerSpawner : bouncerSpawners) {
|
|
for (auto* bouncer : bouncerSpawner->m_Info.nodes)
|
|
bouncerSpawner->Deactivate();
|
|
bouncerSpawner->Reset();
|
|
}
|
|
|
|
for (auto* switchSpawner : switchSpawners) {
|
|
switchSpawner->Deactivate();
|
|
switchSpawner->Reset();
|
|
}
|
|
}
|
|
}
|
|
|
|
void PetDigServer::OnDie(Entity* self, Entity* killer) {
|
|
const auto iterator = std::find(treasures.begin(), treasures.end(), self->GetObjectID());
|
|
if (iterator != treasures.end()) {
|
|
treasures.erase(iterator);
|
|
}
|
|
|
|
auto* owner = killer->GetOwner();
|
|
const auto digInfoIterator = digInfoMap.find(self->GetLOT());
|
|
const auto digInfo = digInfoIterator != digInfoMap.end() ? digInfoIterator->second : defaultDigInfo;
|
|
|
|
if (digInfo.spawnLot >= 0) {
|
|
PetDigServer::SpawnPet(self, owner, digInfo);
|
|
} else if (digInfo.builderOnly) {
|
|
|
|
// Some treasures may only be retrieved by the player that built the diggable
|
|
auto builder = self->GetVar<LWOOBJID>(u"builder"); // Set by the pet dig build script
|
|
if (builder != owner->GetObjectID())
|
|
return;
|
|
} else if (digInfo.xBuild) {
|
|
PetDigServer::HandleXBuildDig(self, owner, killer);
|
|
return;
|
|
} else if (digInfo.bouncer) {
|
|
PetDigServer::HandleBouncerDig(self, owner);
|
|
}
|
|
|
|
PetDigServer::ProgressPetDigMissions(owner, self);
|
|
|
|
self->SetNetworkVar<bool>(u"treasure_dug", true);
|
|
// TODO: Reset other pets
|
|
|
|
// Handles smashing leftovers (edge case for the AG X)
|
|
auto* xObject = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(u"X"));
|
|
if (xObject != nullptr) {
|
|
xObject->Smash(xObject->GetObjectID(), eKillType::VIOLENT);
|
|
}
|
|
}
|
|
|
|
void PetDigServer::HandleXBuildDig(const Entity* self, Entity* owner, Entity* pet) {
|
|
auto playerID = self->GetVar<LWOOBJID>(u"builder");
|
|
if (playerID == LWOOBJID_EMPTY || playerID != owner->GetObjectID())
|
|
return;
|
|
|
|
auto* playerEntity = Game::entityManager->GetEntity(playerID);
|
|
if (!playerEntity || !playerEntity->GetParentUser() || !playerEntity->GetParentUser()->GetLastUsedChar())
|
|
return;
|
|
|
|
auto* player = playerEntity->GetCharacter();
|
|
const auto groupID = self->GetVar<std::u16string>(u"groupID");
|
|
int32_t playerFlag = 0;
|
|
|
|
// The flag that the player dug up
|
|
if (groupID == u"Flag1") {
|
|
playerFlag = 61;
|
|
} else if (groupID == u"Flag2") {
|
|
playerFlag = 62;
|
|
} else if (groupID == u"Flag3") {
|
|
playerFlag = 63;
|
|
}
|
|
|
|
// If the player doesn't have the flag yet
|
|
if (playerFlag != 0 && !player->GetPlayerFlag(playerFlag)) {
|
|
auto* petComponent = pet->GetComponent<PetComponent>();
|
|
if (petComponent != nullptr) {
|
|
// TODO: Pet state = 9 ??
|
|
}
|
|
|
|
// Shows the flag object to the player
|
|
player->SetPlayerFlag(playerFlag, true);
|
|
}
|
|
|
|
auto* xObject = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(u"X"));
|
|
if (xObject != nullptr) {
|
|
xObject->Smash(xObject->GetObjectID(), eKillType::VIOLENT);
|
|
}
|
|
}
|
|
|
|
void PetDigServer::HandleBouncerDig(const Entity* self, const Entity* owner) {
|
|
auto bounceNumber = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"BouncerNumber"));
|
|
auto bouncerSpawners = dZoneManager::Instance()->GetSpawnersByName("PetBouncer" + bounceNumber);
|
|
auto switchSpawners = dZoneManager::Instance()->GetSpawnersByName("PetBouncerSwitch" + bounceNumber);
|
|
|
|
for (auto* bouncerSpawner : bouncerSpawners) {
|
|
bouncerSpawner->Activate();
|
|
}
|
|
|
|
for (auto* switchSpawner : switchSpawners) {
|
|
switchSpawner->Activate();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Progresses the Can You Dig It mission and the Pet Excavator Achievement if the player has never completed it yet
|
|
* \param owner the owner that just made a pet dig something up
|
|
*/
|
|
void PetDigServer::ProgressPetDigMissions(const Entity* owner, const Entity* chest) {
|
|
auto* missionComponent = owner->GetComponent<MissionComponent>();
|
|
|
|
if (missionComponent != nullptr) {
|
|
// Can You Dig It progress
|
|
const auto digMissionState = missionComponent->GetMissionState(843);
|
|
if (digMissionState == eMissionState::ACTIVE) {
|
|
missionComponent->ForceProgress(843, 1216, 1);
|
|
}
|
|
|
|
// Pet Excavator progress
|
|
const auto excavatorMissionState = missionComponent->GetMissionState(505);
|
|
if (excavatorMissionState == eMissionState::ACTIVE) {
|
|
if (chest->HasVar(u"PetDig")) {
|
|
int32_t playerFlag = 1260 + chest->GetVarAs<int32_t>(u"PetDig");
|
|
Character* player = owner->GetCharacter();
|
|
|
|
// check if player flag is set
|
|
if (!player->GetPlayerFlag(playerFlag)) {
|
|
missionComponent->ForceProgress(505, 767, 1);
|
|
player->SetPlayerFlag(playerFlag, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Some treasures spawn special pets, this handles that case
|
|
* \param owner the owner that just made a pet dig something up
|
|
* \param digInfo information regarding the treasure, will also contain info about the pet to spawn
|
|
*/
|
|
void PetDigServer::SpawnPet(Entity* self, const Entity* owner, const DigInfo digInfo) {
|
|
// Some treasures require a mission to be active
|
|
if (digInfo.requiredMission >= 0) {
|
|
auto* missionComponent = owner->GetComponent<MissionComponent>();
|
|
if (missionComponent != nullptr && missionComponent->GetMissionState(digInfo.requiredMission) < eMissionState::ACTIVE) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
EntityInfo info{};
|
|
info.lot = digInfo.spawnLot;
|
|
info.pos = self->GetPosition();
|
|
info.rot = self->GetRotation();
|
|
info.spawnerID = self->GetSpawnerID();
|
|
info.settings = {
|
|
new LDFData<LWOOBJID>(u"tamer", owner->GetObjectID()),
|
|
new LDFData<std::string>(u"group", "pet" + std::to_string(owner->GetObjectID())),
|
|
new LDFData<std::string>(u"spawnAnim", "spawn-pet"),
|
|
new LDFData<float>(u"spawnTimer", 1.0)
|
|
};
|
|
|
|
auto* spawnedPet = Game::entityManager->CreateEntity(info);
|
|
Game::entityManager->ConstructEntity(spawnedPet);
|
|
}
|
|
|
|
Entity* PetDigServer::GetClosestTresure(NiPoint3 position) {
|
|
float closestDistance = 0;
|
|
Entity* closest = nullptr;
|
|
|
|
for (const auto tresureId : treasures) {
|
|
auto* tresure = Game::entityManager->GetEntity(tresureId);
|
|
|
|
if (tresure == nullptr) continue;
|
|
|
|
float distance = Vector3::DistanceSquared(tresure->GetPosition(), position);
|
|
|
|
if (closest == nullptr || distance < closestDistance) {
|
|
closestDistance = distance;
|
|
closest = tresure;
|
|
}
|
|
}
|
|
|
|
return closest;
|
|
}
|