-
Notifications
You must be signed in to change notification settings - Fork 182
Expand file tree
/
Copy pathPetDigServer.cpp
More file actions
247 lines (200 loc) · 7.99 KB
/
PetDigServer.cpp
File metadata and controls
247 lines (200 loc) · 7.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#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::OnUse(Entity* self, Entity* user) {
LOG("Treasure used!");
auto* petComponent = PetComponent::GetActivePet(user->GetObjectID());
if (!petComponent) return;
if(petComponent->GetIsReadyToDig()) {
petComponent->SetTreasureTime(2.0f);
}
}
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 = 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;
}