DarkflameServer/dScripts/02_server/Map/General/PetDigServer.cpp
David Markowitz f0b6ad89d9
chore: Player class removal (#1445)
* SystemAddress and destructor

* move respawn logic to character comp

Tested that respawn pos and rot can be set as per previously by crossing a respawn point and smashing to see if I would respawn at the new place.

* Move loot cheat checking

* Remove GetParentUser overload

Tested completing missions
control behaviors
collecting life crate
completing a bunch of missions using macros
loading into worlds
brick-by-brick
placing models
digging the x spot in gnarled forest
can still ban and mute players
cheat detection is still doing its thing
flags are still set (checked with flag 45)
claim codes still work (created new char, checked the lego club mail was there)

* Move player constructor logic

Its now at the bottom of Entity constructor.  Time to remove Player

* Remove Player class

Removes the Player class.  Tested that I can still login and see another player in Venture Explorer and logging out a few times still works as well as smashing enemies

* store ptr

* Update SlashCommandHandler.cpp
2024-02-04 06:29:05 -08:00

237 lines
7.7 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 = Game::zoneManager->GetSpawnersByName("PetBouncer" + bounceNumber);
auto switchSpawners = Game::zoneManager->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->GetCharacter())
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 = Game::zoneManager->GetSpawnersByName("PetBouncer" + bounceNumber);
auto switchSpawners = Game::zoneManager->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;
}