mirror of
https://github.com/DarkflameUniverse/DarkflameServer
synced 2024-08-30 18:43:58 +00:00
Organize dScripts (#814)
* Organize dScripts whitespace Remove parent scope Remove parent scope from initial setter Remove debug Remove helper programs * Fix NtImagimeterVisibility script Co-authored-by: aronwk-aaron <aronwk.aaron@gmail.com>
This commit is contained in:
45
dScripts/02_server/CMakeLists.txt
Normal file
45
dScripts/02_server/CMakeLists.txt
Normal file
@ -0,0 +1,45 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER)
|
||||
|
||||
add_subdirectory(DLU)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_DLU})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER ${DSCRIPTS_SOURCES_02_SERVER} "DLU/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(Enemy)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_ENEMY})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER ${DSCRIPTS_SOURCES_02_SERVER} "Enemy/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(Equipment)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_EQUIPMENT})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER ${DSCRIPTS_SOURCES_02_SERVER} "Equipment/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(Map)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_MAP})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER ${DSCRIPTS_SOURCES_02_SERVER} "Map/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(Minigame)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_MINIGAME})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER ${DSCRIPTS_SOURCES_02_SERVER} "Minigame/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(Objects)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_OBJECTS})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER ${DSCRIPTS_SOURCES_02_SERVER} "Objects/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(Pets)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_PETS})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER ${DSCRIPTS_SOURCES_02_SERVER} "Pets/${file}")
|
||||
endforeach()
|
||||
|
||||
set(DSCRIPTS_SOURCES_02_SERVER ${DSCRIPTS_SOURCES_02_SERVER} PARENT_SCOPE)
|
3
dScripts/02_server/DLU/CMakeLists.txt
Normal file
3
dScripts/02_server/DLU/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_DLU
|
||||
"DLUVanityNPC.cpp"
|
||||
PARENT_SCOPE)
|
46
dScripts/02_server/DLU/DLUVanityNPC.cpp
Normal file
46
dScripts/02_server/DLU/DLUVanityNPC.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include "DLUVanityNPC.h"
|
||||
#include "GameMessages.h"
|
||||
#include "dServer.h"
|
||||
#include "VanityUtilities.h"
|
||||
|
||||
void DLUVanityNPC::OnStartup(Entity* self) {
|
||||
m_NPC = VanityUtilities::GetNPC("averysumner - Destroyer of Worlds");
|
||||
|
||||
if (m_NPC == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->GetVar<bool>(u"teleport")) {
|
||||
self->AddTimer("setupTeleport", 15.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void DLUVanityNPC::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "setupTeleport") {
|
||||
GameMessages::SendPlayAnimation(self, u"interact");
|
||||
GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam");
|
||||
GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings");
|
||||
|
||||
self->AddTimer("teleport", 2.0f);
|
||||
self->AddTimer("stopFX", 2.0f);
|
||||
} else if (timerName == "stopFX") {
|
||||
GameMessages::SendStopFXEffect(self, true, "teleportBeam");
|
||||
GameMessages::SendStopFXEffect(self, true, "teleportRings");
|
||||
} else if (timerName == "teleport") {
|
||||
std::vector<VanityNPCLocation>& locations = m_NPC->m_Locations[Game::server->GetZoneID()];
|
||||
|
||||
selectLocation:
|
||||
VanityNPCLocation& newLocation = locations[GeneralUtils::GenerateRandomNumber<size_t>(0, locations.size() - 1)];
|
||||
|
||||
if (self->GetPosition() == newLocation.m_Position) {
|
||||
goto selectLocation; // cry about it
|
||||
}
|
||||
|
||||
self->SetPosition(newLocation.m_Position);
|
||||
self->SetRotation(newLocation.m_Rotation);
|
||||
GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam");
|
||||
GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings");
|
||||
self->AddTimer("stopFX", 2.0f);
|
||||
self->AddTimer("setupTeleport", 15.0f);
|
||||
}
|
||||
}
|
13
dScripts/02_server/DLU/DLUVanityNPC.h
Normal file
13
dScripts/02_server/DLU/DLUVanityNPC.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class VanityNPC;
|
||||
class DLUVanityNPC : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
|
||||
private:
|
||||
VanityNPC* m_NPC;
|
||||
};
|
710
dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp
Normal file
710
dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp
Normal file
@ -0,0 +1,710 @@
|
||||
#include "BossSpiderQueenEnemyServer.h"
|
||||
|
||||
#include "GeneralUtils.h"
|
||||
|
||||
#include "MissionComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Entity.h"
|
||||
#include "dZoneManager.h"
|
||||
|
||||
#include "DestroyableComponent.h"
|
||||
#include "ControllablePhysicsComponent.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
|
||||
#include "GameMessages.h"
|
||||
#include "SkillComponent.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
//----------------------------------------------------------------
|
||||
//--On Startup, process necessary AI events
|
||||
//----------------------------------------------------------------
|
||||
void BossSpiderQueenEnemyServer::OnStartup(Entity* self) {
|
||||
// Make immune to stuns
|
||||
//self:SetStunImmunity{ StateChangeType = "PUSH", bImmuneToStunAttack = true, bImmuneToStunMove = true, bImmuneToStunTurn = true, bImmuneToStunUseItem = true, bImmuneToStunEquip = true, bImmuneToStunInteract = true, bImmuneToStunJump = true }
|
||||
|
||||
// Make immune to knockbacks and pulls
|
||||
//self:SetStatusImmunity{ StateChangeType = "PUSH", bImmuneToPullToPoint = true, bImmuneToKnockback = true, bImmuneToInterrupt = true }
|
||||
|
||||
//Get our components:
|
||||
destroyable = static_cast<DestroyableComponent*>(self->GetComponent(COMPONENT_TYPE_DESTROYABLE));
|
||||
controllable = static_cast<ControllablePhysicsComponent*>(self->GetComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS));
|
||||
combat = static_cast<BaseCombatAIComponent*>(self->GetComponent(COMPONENT_TYPE_BASE_COMBAT_AI));
|
||||
|
||||
if (!destroyable || !controllable) return;
|
||||
|
||||
// Determine Spider Boss health transition thresholds
|
||||
int spiderBossHealth = destroyable->GetMaxHealth();
|
||||
int transitionTickHealth = spiderBossHealth / 3;
|
||||
|
||||
int Stage2HealthThreshold = spiderBossHealth - transitionTickHealth;
|
||||
int Stage3HealthThreshold = spiderBossHealth - (2 * transitionTickHealth);
|
||||
ThresholdTable = { Stage2HealthThreshold, Stage3HealthThreshold };
|
||||
|
||||
originRotation = controllable->GetRotation();
|
||||
combat->SetStunImmune(true);
|
||||
|
||||
m_CurrentBossStage = 1;
|
||||
|
||||
// Obtain faction and collision group to save for subsequent resets
|
||||
//self : SetVar("SBFactionList", self:GetFaction().factionList)
|
||||
//self : SetVar("SBCollisionGroup", self:GetCollisionGroup().colGroup)
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::OnDie(Entity* self, Entity* killer) {
|
||||
if (dZoneManager::Instance()->GetZoneID().GetMapID() == instanceZoneID) {
|
||||
auto* missionComponent = killer->GetComponent<MissionComponent>();
|
||||
if (missionComponent == nullptr)
|
||||
return;
|
||||
|
||||
missionComponent->CompleteMission(instanceMissionID);
|
||||
}
|
||||
|
||||
Game::logger->Log("BossSpiderQueenEnemyServer", "Starting timer...");
|
||||
|
||||
// There is suppose to be a 0.1 second delay here but that may be admitted?
|
||||
auto* controller = EntityManager::Instance()->GetZoneControlEntity();
|
||||
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"SetColGroup", 10, 0, 0, "", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
self->SetPosition({ 10000, 0, 10000 });
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
|
||||
controller->OnFireEventServerSide(self, "ClearProperty");
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::WithdrawSpider(Entity* self, const bool withdraw) {
|
||||
const auto withdrawn = self->GetBoolean(u"isWithdrawn");
|
||||
|
||||
if (withdrawn == withdraw) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (withdraw) {
|
||||
//Move spider away from battle zone
|
||||
// Disabled because we cant option the reset collition group right now
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"SetColGroup", 10, 0, 0, "", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
//First rotate for anim
|
||||
NiQuaternion rot = NiQuaternion::IDENTITY;
|
||||
|
||||
controllable->SetStatic(false);
|
||||
|
||||
controllable->SetRotation(rot);
|
||||
|
||||
controllable->SetStatic(true);
|
||||
|
||||
controllable->SetDirtyPosition(true);
|
||||
|
||||
rot = controllable->GetRotation();
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
|
||||
auto* baseCombatAi = self->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
baseCombatAi->SetDisabled(true);
|
||||
|
||||
float animTime = PlayAnimAndReturnTime(self, spiderWithdrawAnim);
|
||||
float withdrawTime = animTime - 0.25f;
|
||||
|
||||
combat->SetStunImmune(false);
|
||||
combat->Stun(withdrawTime + 6.0f);
|
||||
combat->SetStunImmune(true);
|
||||
|
||||
//TODO: Set faction to -1 and set immunity
|
||||
destroyable->SetFaction(-1);
|
||||
destroyable->SetIsImmune(true);
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
|
||||
self->AddTimer("WithdrawComplete", withdrawTime + 1.0f);
|
||||
waitForIdle = true;
|
||||
} else {
|
||||
controllable->SetStatic(false);
|
||||
|
||||
//Cancel all remaining timers for say idle anims:
|
||||
self->CancelAllTimers();
|
||||
|
||||
auto* baseCombatAi = self->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
baseCombatAi->SetDisabled(false);
|
||||
|
||||
// Move the Spider to its ground location
|
||||
// preparing its stage attacks, and removing invulnerability
|
||||
//destroyable->SetIsImmune(false);
|
||||
|
||||
// Run the advance animation and prepare a timer for resuming AI
|
||||
float animTime = PlayAnimAndReturnTime(self, spiderAdvanceAnim);
|
||||
animTime += 1.f;
|
||||
|
||||
float attackPause = animTime - 0.4f;
|
||||
|
||||
destroyable->SetFaction(4);
|
||||
destroyable->SetIsImmune(false);
|
||||
|
||||
//Advance stage
|
||||
m_CurrentBossStage++;
|
||||
|
||||
//Reset the current wave death counter
|
||||
m_DeathCounter = 0;
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
|
||||
// Prepare a timer for post leap attack
|
||||
self->AddTimer("AdvanceAttack", attackPause);
|
||||
|
||||
// Prepare a timer for post leap
|
||||
self->AddTimer("AdvanceComplete", animTime);
|
||||
}
|
||||
|
||||
self->SetBoolean(u"isWithdrawn", withdraw);
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::SpawnSpiderWave(Entity* self, int spiderCount) {
|
||||
// The Spider Queen Boss is withdrawing and requesting the spawn
|
||||
// of a hatchling wave
|
||||
|
||||
/*auto SpiderEggNetworkID = self->GetI64(u"SpiderEggNetworkID");
|
||||
if (SpiderEggNetworkID == 0) return;*/
|
||||
|
||||
// Clamp invalid Spiderling number requests to the maximum amount of eggs available
|
||||
if ((spiderCount > maxSpiderEggCnt) || (spiderCount < 0))
|
||||
spiderCount = maxSpiderEggCnt;
|
||||
|
||||
// Reset our wave manager reference variables
|
||||
hatchCounter = spiderCount;
|
||||
hatchList = {};
|
||||
|
||||
Game::logger->Log("SpiderQueen", "Trying to spawn %i spiders", hatchCounter);
|
||||
|
||||
|
||||
// Run the wave manager
|
||||
SpiderWaveManager(self);
|
||||
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::SpiderWaveManager(Entity* self) {
|
||||
auto SpiderEggNetworkID = self->GetI64(u"SpiderEggNetworkID");
|
||||
|
||||
// Reset the spider egg spawner network to ensure a maximum number of eggs
|
||||
//SpiderEggNetworkID:SpawnerReset()
|
||||
|
||||
// Obtain a list of all the eggs on the egg spawner network
|
||||
|
||||
//auto spiderEggList = SpiderEggNetworkID:SpawnerGetAllObjectIDsSpawned().objects;
|
||||
|
||||
//if (table.maxn(spiderEggList) <= 0) {
|
||||
// self->AddTimer("PollSpiderWaveManager", 1.0f);
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//// A check for (wave mangement across multiple spawn iterations
|
||||
//if(hatchCounter < spiderWaveCnt) {
|
||||
// // We have already prepped some objects for (hatching,
|
||||
// // remove them from our list for (random egg pulls
|
||||
// for (i, sVal in ipairs(spiderEggList) {
|
||||
// if(hatchList[sVal:GetID()]) {
|
||||
// // We have found a prepped egg, remove it from the spiderEggList
|
||||
// spiderEggList[i] = nil
|
||||
// }
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
|
||||
|
||||
std::vector<LWOOBJID> spiderEggs{};
|
||||
|
||||
auto spooders = EntityManager::Instance()->GetEntitiesInGroup("EGG");
|
||||
for (auto spodder : spooders) {
|
||||
spiderEggs.push_back(spodder->GetObjectID());
|
||||
}
|
||||
|
||||
// Select a number of random spider eggs from the list equal to the
|
||||
// current number needed to complete the current wave
|
||||
for (int i = 0; i < hatchCounter; i++) {
|
||||
// Select a random spider egg
|
||||
auto randomEggLoc = GeneralUtils::GenerateRandomNumber<int>(0, spiderEggs.size() - 1);
|
||||
auto randomEgg = spiderEggs[randomEggLoc];
|
||||
|
||||
//Just a quick check to try and prevent dupes:
|
||||
for (auto en : hatchList) {
|
||||
if (en == randomEgg) {
|
||||
randomEggLoc++;
|
||||
randomEgg = spiderEggs[randomEggLoc];
|
||||
}
|
||||
}
|
||||
|
||||
if (randomEgg) {
|
||||
auto* eggEntity = EntityManager::Instance()->GetEntity(randomEgg);
|
||||
|
||||
if (eggEntity == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prep the selected spider egg
|
||||
//randomEgg:FireEvent{s}erID=self, args="prepEgg"}
|
||||
eggEntity->OnFireEventServerSide(self, "prepEgg");
|
||||
Game::logger->Log("SpiderQueen", "Prepping egg %llu", eggEntity->GetObjectID());
|
||||
|
||||
// Add the prepped egg to our hatchList
|
||||
hatchList.push_back(eggEntity->GetObjectID());
|
||||
|
||||
// Decrement the hatchCounter
|
||||
hatchCounter = hatchCounter - 1;
|
||||
}
|
||||
|
||||
// Remove it from our spider egg list
|
||||
//table.remove(spiderEggList, randomEggLoc);
|
||||
spiderEggs[randomEggLoc] = LWOOBJID_EMPTY;
|
||||
|
||||
if (spiderEggs.size() <= 0 || (hatchCounter <= 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hatchCounter > 0) {
|
||||
// We still have more eggs to hatch, poll the SpiderWaveManager again
|
||||
self->AddTimer("PollSpiderWaveManager", 1.0f);
|
||||
|
||||
} else {
|
||||
// We have successfully readied a full wave
|
||||
// initiate hatching!
|
||||
for (auto egg : hatchList) {
|
||||
auto* eggEntity = EntityManager::Instance()->GetEntity(egg);
|
||||
|
||||
if (eggEntity == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eggEntity->OnFireEventServerSide(self, "hatchEgg");
|
||||
Game::logger->Log("SpiderQueen", "hatching egg %llu", eggEntity->GetObjectID());
|
||||
|
||||
auto time = PlayAnimAndReturnTime(self, spiderWithdrawIdle);
|
||||
combat->SetStunImmune(false);
|
||||
combat->Stun(time += 6.0f);
|
||||
combat->SetStunImmune(true);
|
||||
|
||||
//self->AddTimer("disableWaitForIdle", defaultAnimPause);
|
||||
self->AddTimer("checkForSpiders", 6.0f);
|
||||
|
||||
}
|
||||
|
||||
hatchList.clear();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::ToggleForSpecial(Entity* self, const bool state) {
|
||||
self->SetBoolean(u"stoppedFlag", state);
|
||||
|
||||
combat->SetDisabled(state);
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::RunRainOfFire(Entity* self) {
|
||||
if (self->GetBoolean(u"stoppedFlag")) {
|
||||
self->AddTimer("ROF", GeneralUtils::GenerateRandomNumber<float>(10, 20));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ToggleForSpecial(self, true);
|
||||
|
||||
impactList.clear();
|
||||
|
||||
auto index = 0u;
|
||||
for (const auto& rofGroup : ROFTargetGroupIDTable) {
|
||||
const auto spawners = dZoneManager::Instance()->GetSpawnersInGroup(rofGroup);
|
||||
|
||||
std::vector<LWOOBJID> spawned;
|
||||
|
||||
for (auto* spawner : spawners) {
|
||||
for (const auto* node : spawner->m_Info.nodes) {
|
||||
spawned.insert(spawned.end(), node->entities.begin(), node->entities.end());
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
impactList.insert(impactList.end(), spawned.begin(), spawned.end());
|
||||
} else {
|
||||
const auto randomIndex = GeneralUtils::GenerateRandomNumber<int32_t>(0, spawned.size() - 1);
|
||||
|
||||
impactList.push_back(spawned[randomIndex]);
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
const auto animTime = PlayAnimAndReturnTime(self, spiderROFAnim);
|
||||
|
||||
self->AddTimer("StartROF", animTime);
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::RainOfFireManager(Entity* self) {
|
||||
if (!impactList.empty()) {
|
||||
auto* entity = EntityManager::Instance()->GetEntity(impactList[0]);
|
||||
|
||||
impactList.erase(impactList.begin());
|
||||
|
||||
if (entity == nullptr) {
|
||||
Game::logger->Log("BossSpiderQueenEnemyServer", "Failed to find impact!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* skillComponent = entity->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent == nullptr) {
|
||||
Game::logger->Log("BossSpiderQueenEnemyServer", "Failed to find impact skill component!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
skillComponent->CalculateBehavior(1376, 32168, LWOOBJID_EMPTY, true);
|
||||
|
||||
self->AddTimer("PollROFManager", 0.5f);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ToggleForSpecial(self, false);
|
||||
|
||||
self->AddTimer("ROF", GeneralUtils::GenerateRandomNumber<float>(20, 40));
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::RapidFireShooterManager(Entity* self) {
|
||||
if (attackTargetTable.empty()) {
|
||||
const auto animationTime = PlayAnimAndReturnTime(self, spiderJeerAnim);
|
||||
|
||||
self->AddTimer("RFSTauntComplete", animationTime);
|
||||
|
||||
ToggleForSpecial(self, false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto target = attackTargetTable[0];
|
||||
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
skillComponent->CalculateBehavior(1394, 32612, target, true);
|
||||
|
||||
attackTargetTable.erase(attackTargetTable.begin());
|
||||
|
||||
self->AddTimer("PollRFSManager", 0.3f);
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::RunRapidFireShooter(Entity* self) {
|
||||
/*
|
||||
const auto targets = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_CHARACTER);
|
||||
*/
|
||||
|
||||
const auto targets = self->GetTargetsInPhantom();
|
||||
|
||||
if (self->GetBoolean(u"stoppedFlag")) {
|
||||
self->AddTimer("RFS", GeneralUtils::GenerateRandomNumber<float>(5, 10));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (targets.empty()) {
|
||||
Game::logger->Log("BossSpiderQueenEnemyServer", "Failed to find RFS targets");
|
||||
|
||||
self->AddTimer("RFS", GeneralUtils::GenerateRandomNumber<float>(5, 10));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ToggleForSpecial(self, true);
|
||||
|
||||
const auto randomTarget = GeneralUtils::GenerateRandomNumber<int32_t>(0, targets.size() - 1);
|
||||
|
||||
auto attackFocus = targets[randomTarget];
|
||||
|
||||
attackTargetTable.push_back(attackFocus);
|
||||
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
skillComponent->CalculateBehavior(1480, 36652, attackFocus, true);
|
||||
|
||||
RapidFireShooterManager(self);
|
||||
|
||||
PlayAnimAndReturnTime(self, spiderSingleShot);
|
||||
|
||||
Game::logger->Log("BossSpiderQueenEnemyServer", "Ran RFS");
|
||||
|
||||
self->AddTimer("RFS", GeneralUtils::GenerateRandomNumber<float>(10, 15));
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::OnTimerDone(Entity* self, const std::string timerName) {
|
||||
if (timerName == "PollSpiderWaveManager") {
|
||||
//Call the manager again to attempt to finish prepping a Spiderling wave
|
||||
//Run the wave manager
|
||||
SpiderWaveManager(self);
|
||||
} else if (timerName == "disableWaitForIdle") { waitForIdle = false; } else if (timerName == "checkForSpiders") {
|
||||
//Don't do anything if we ain't withdrawn:
|
||||
const auto withdrawn = self->GetBoolean(u"isWithdrawn");
|
||||
if (!withdrawn) return;
|
||||
|
||||
NiQuaternion rot = NiQuaternion::IDENTITY;
|
||||
|
||||
//First rotate for anim
|
||||
controllable->SetStatic(false);
|
||||
controllable->SetRotation(rot);
|
||||
controllable->SetStatic(true);
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
|
||||
//Play the Spider Boss' mountain idle anim
|
||||
auto time = PlayAnimAndReturnTime(self, spiderWithdrawIdle);
|
||||
combat->SetStunImmune(false);
|
||||
combat->Stun(time);
|
||||
combat->SetStunImmune(true);
|
||||
|
||||
rot = controllable->GetRotation();
|
||||
|
||||
//If there are still baby spiders, don't do anyhting either
|
||||
const auto spiders = EntityManager::Instance()->GetEntitiesInGroup("BabySpider");
|
||||
if (spiders.size() > 0)
|
||||
self->AddTimer("checkForSpiders", time);
|
||||
else
|
||||
WithdrawSpider(self, false);
|
||||
} else if (timerName == "PollROFManager") {
|
||||
//Call the manager again to attempt to initiate an impact on another random location
|
||||
//Run the ROF Manager
|
||||
RainOfFireManager(self);
|
||||
|
||||
} else if (timerName == "PollRFSManager") {
|
||||
//Call the manager again to attempt to initiate a rapid fire shot at the next sequential target
|
||||
//Run the ROF Manager
|
||||
RapidFireShooterManager(self);
|
||||
|
||||
} else if (timerName == "StartROF") {
|
||||
//Re-enable Spider Boss
|
||||
//ToggleForSpecial(self, false);
|
||||
|
||||
RainOfFireManager(self);
|
||||
|
||||
} else if (timerName == "PollSpiderSkillManager") {
|
||||
//Call the skill manager again to attempt to run the current Spider Boss
|
||||
//stage's special attack again
|
||||
//SpiderSkillManager(self, true);
|
||||
PlayAnimAndReturnTime(self, spiderJeerAnim);
|
||||
|
||||
} else if (timerName == "RFS") {
|
||||
RunRapidFireShooter(self);
|
||||
} else if (timerName == "ROF") {
|
||||
RunRainOfFire(self);
|
||||
} else if (timerName == "RFSTauntComplete") {
|
||||
//Determine an appropriate random time to check our manager again
|
||||
// local spiderCooldownDelay = math.random(s1DelayMin, s1DelayMax)
|
||||
|
||||
//Set a timer based on our random cooldown determination
|
||||
//to pulse the SpiderSkillManager again
|
||||
|
||||
//GAMEOBJ:GetTimer():AddTimerWithCancel(spiderCooldownDelay, "PollSpiderSkillManager", self)
|
||||
|
||||
//Re-enable Spider Boss
|
||||
//ToggleForSpecial(self, false);
|
||||
|
||||
} else if (timerName == "WithdrawComplete") {
|
||||
//Play the Spider Boss' mountain idle anim
|
||||
PlayAnimAndReturnTime(self, spiderWithdrawIdle);
|
||||
|
||||
//The Spider Boss has retreated, hatch a wave!
|
||||
int currentStage = m_CurrentBossStage;
|
||||
|
||||
//Prepare a Spiderling wave and initiate egg hatch events
|
||||
//self->SetVar(u"SpiderWaveCount", )
|
||||
|
||||
//TODO: Actually spawn the spiders here
|
||||
hatchCounter = 2;
|
||||
if (currentStage > 1) hatchCounter++;
|
||||
|
||||
SpawnSpiderWave(self, spiderWaveCntTable[currentStage - 1]);
|
||||
|
||||
} else if (timerName == "AdvanceAttack") {
|
||||
//TODO: Can we even do knockbacks yet? @Wincent01
|
||||
// Yes ^
|
||||
|
||||
//Fire the melee smash skill to throw players back
|
||||
/*local landingTarget = self:GetVar("LandingTarget") or false
|
||||
|
||||
if((landingTarget) and (landingTarget:Exists())) {
|
||||
local advSmashFlag = landingTarget:CastSkill{skillID = bossLandingSkill}
|
||||
landingTarget:PlayEmbeddedEffectOnAllClientsNearObject{radius = 100, fromObjectID = landingTarget, effectName = "camshake-bridge"}
|
||||
}*/
|
||||
|
||||
auto landingTarget = self->GetI64(u"LandingTarget");
|
||||
auto landingEntity = EntityManager::Instance()->GetEntity(landingTarget);
|
||||
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->CalculateBehavior(bossLandingSkill, 37739, LWOOBJID_EMPTY);
|
||||
}
|
||||
|
||||
if (landingEntity) {
|
||||
auto* landingSkill = landingEntity->GetComponent<SkillComponent>();
|
||||
|
||||
if (landingSkill != nullptr) {
|
||||
landingSkill->CalculateBehavior(bossLandingSkill, 37739, LWOOBJID_EMPTY, true);
|
||||
}
|
||||
}
|
||||
|
||||
GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(self, u"camshake-bridge", self->GetObjectID(), 100.0f);
|
||||
|
||||
} else if (timerName == "AdvanceComplete") {
|
||||
//Reset faction and collision
|
||||
/*local SBFactionList = self:GetVar("SBFactionList")
|
||||
local SBCollisionGroup = self:GetVar("SBCollisionGroup")
|
||||
|
||||
for i, fVal in ipairs(SBFactionList) {
|
||||
if(i == 1) {
|
||||
//Our first faction - flush and add
|
||||
self:SetFaction{faction = fVal}
|
||||
else
|
||||
//Add
|
||||
self:ModifyFaction{factionID = fVal, bAddFaction = true}
|
||||
}
|
||||
}*/
|
||||
|
||||
/*
|
||||
auto SBCollisionGroup = self->GetI32(u"SBCollisionGroup");
|
||||
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"SetColGroup", SBCollisionGroup, 0, LWOOBJID_EMPTY, "", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
*/
|
||||
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"SetColGroup", 11, 0, 0, "", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
//Wind up, telegraphing next round
|
||||
float animTime = PlayAnimAndReturnTime(self, spiderJeerAnim);
|
||||
self->AddTimer("AdvanceTauntComplete", animTime);
|
||||
|
||||
} else if (timerName == "AdvanceTauntComplete") {
|
||||
|
||||
//Declare a default special Spider Boss skill cooldown
|
||||
int spiderCooldownDelay = 10;
|
||||
|
||||
if (m_CurrentBossStage == 2) {
|
||||
spiderCooldownDelay = GeneralUtils::GenerateRandomNumber<int>(s1DelayMin, s1DelayMax);
|
||||
} else if (m_CurrentBossStage == 3) {
|
||||
spiderCooldownDelay = GeneralUtils::GenerateRandomNumber<int>(s2DelayMin, s2DelayMax);
|
||||
}
|
||||
|
||||
//Set a timer based on our random cooldown determination
|
||||
//to pulse the SpiderSkillManager
|
||||
self->AddTimer("PollSpiderSkillManager", spiderCooldownDelay);
|
||||
|
||||
//Remove current status immunity
|
||||
/*self:SetStatusImmunity{ StateChangeType = "POP", bImmuneToSpeed = true, bImmuneToBasicAttack = true, bImmuneToDOT = true}
|
||||
|
||||
self:SetStunned{StateChangeType = "POP",
|
||||
bCantMove = true,
|
||||
bCantJump = true,
|
||||
bCantTurn = true,
|
||||
bCantAttack = true,
|
||||
bCantUseItem = true,
|
||||
bCantEquip = true,
|
||||
bCantInteract = true,
|
||||
bIgnoreImmunity = true}*/
|
||||
|
||||
destroyable->SetIsImmune(false);
|
||||
destroyable->SetFaction(4);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
|
||||
} else if (timerName == "Clear") {
|
||||
EntityManager::Instance()->FireEventServerSide(self, "ClearProperty");
|
||||
self->CancelAllTimers();
|
||||
} else if (timerName == "UnlockSpecials") {
|
||||
//We no longer need to lock specials
|
||||
self->SetBoolean(u"bSpecialLock", false);
|
||||
|
||||
//Did we queue a spcial attack?
|
||||
if (self->GetBoolean(u"bSpecialQueued")) {
|
||||
self->SetBoolean(u"bSpecialQueued", false);
|
||||
//SpiderSkillManager(self, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {
|
||||
if (m_CurrentBossStage > 0 && !self->HasTimer("RFS")) {
|
||||
self->AddTimer("RFS", 5.0f);
|
||||
}
|
||||
|
||||
if (m_CurrentBossStage > 0 && !self->HasTimer("ROF")) {
|
||||
self->AddTimer("ROF", 10.0f);
|
||||
}
|
||||
|
||||
if (m_CurrentBossStage > ThresholdTable.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int currentThreshold = ThresholdTable[m_CurrentBossStage - 1];
|
||||
|
||||
if (destroyable->GetHealth() <= currentThreshold) {
|
||||
auto isWithdrawn = self->GetBoolean(u"isWithdrawn");
|
||||
|
||||
if (!isWithdrawn) {
|
||||
self->CancelAllTimers();
|
||||
|
||||
self->SetBoolean(u"isSpecialAttacking", false);
|
||||
self->SetBoolean(u"bSpecialLock", false);
|
||||
|
||||
WithdrawSpider(self, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BossSpiderQueenEnemyServer::OnUpdate(Entity* self) {
|
||||
auto isWithdrawn = self->GetBoolean(u"isWithdrawn");
|
||||
|
||||
if (!isWithdrawn) return;
|
||||
|
||||
if (controllable->GetRotation() == NiQuaternion::IDENTITY) {
|
||||
return;
|
||||
}
|
||||
|
||||
controllable->SetStatic(false);
|
||||
controllable->SetRotation(NiQuaternion::IDENTITY);
|
||||
controllable->SetStatic(true);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
|
||||
//if (waitForIdle) return;
|
||||
|
||||
////Play the Spider Boss' mountain idle anim
|
||||
//PlayAnimAndReturnTime(self, spiderWithdrawIdle);
|
||||
|
||||
////If there are still baby spiders, don't do anyhting either
|
||||
//auto spooders = EntityManager::Instance()->GetEntitiesInGroup("BabySpider");
|
||||
//if (spooders.size() > 0) return;
|
||||
//else
|
||||
// WithdrawSpider(self, false);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
//--Utility function capable of playing a priority
|
||||
//-- animation on a targetand returning either the
|
||||
//-- anim time, or a desired default
|
||||
//----------------------------------------------
|
||||
float BossSpiderQueenEnemyServer::PlayAnimAndReturnTime(Entity* self, const std::u16string& animID) {
|
||||
//TODO: Get the actual animation time
|
||||
|
||||
// Get the anim time
|
||||
float animTimer = defaultAnimPause; //self:GetAnimationTime{animationID = animID}.time
|
||||
|
||||
// If we have an animation play it
|
||||
if (animTimer > 0) {
|
||||
GameMessages::SendPlayAnimation(self, animID);
|
||||
}
|
||||
|
||||
// If the anim time is less than the the default time use default
|
||||
if (animTimer < defaultAnimPause) {
|
||||
animTimer = defaultAnimPause;
|
||||
}
|
||||
|
||||
return animTimer;
|
||||
}
|
126
dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.h
Normal file
126
dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.h
Normal file
@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------
|
||||
|
||||
--L_BOSS_SPIDER_QUEEN_ENEMY_SERVER.lua
|
||||
|
||||
-- Server side Spider Queen Boss fight behavior script
|
||||
-- created abeechler ... 5 / 12 / 11
|
||||
|
||||
-- ported by Wincent01 & Max, July 2020
|
||||
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
class DestroyableComponent;
|
||||
class ControllablePhysicsComponent;
|
||||
class BaseCombatAIComponent;
|
||||
class BossSpiderQueenEnemyServer final : public CppScripts::Script {
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
|
||||
void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override;
|
||||
|
||||
void OnUpdate(Entity* self) override;
|
||||
|
||||
void WithdrawSpider(Entity* self, bool withdraw);
|
||||
|
||||
void SpawnSpiderWave(Entity* self, int spiderCount);
|
||||
|
||||
void SpiderWaveManager(Entity* self);
|
||||
|
||||
void ToggleForSpecial(Entity* self, bool state);
|
||||
|
||||
void RunRainOfFire(Entity* self);
|
||||
|
||||
void RainOfFireManager(Entity* self);
|
||||
|
||||
void RapidFireShooterManager(Entity* self);
|
||||
|
||||
void RunRapidFireShooter(Entity* self);
|
||||
|
||||
float PlayAnimAndReturnTime(Entity* self, const std::u16string& animId);
|
||||
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
|
||||
private:
|
||||
//Regular variables:
|
||||
DestroyableComponent* destroyable = nullptr;
|
||||
ControllablePhysicsComponent* controllable = nullptr;
|
||||
BaseCombatAIComponent* combat = nullptr;
|
||||
|
||||
NiQuaternion originRotation;
|
||||
|
||||
int m_CurrentBossStage = 0;
|
||||
int m_DeathCounter = 0;
|
||||
std::vector<int> ThresholdTable;
|
||||
bool waitForIdle = false;
|
||||
|
||||
//Const variables:
|
||||
|
||||
const std::vector<int> spiderWaveCntTable = { 2, 3 }; //The number of Dark Spiderling enemies to spawn per indexed wave number
|
||||
|
||||
const int ROFImpactCnt = 2; //The number of ROF impacts in each quadrant of the arena selected at random
|
||||
|
||||
const LOT SpiderlingID = 16197; //Reference obj ID for hatched Spiderlings
|
||||
|
||||
const int maxSpiderEggCnt = 3;
|
||||
int hatchCounter = 0; //Global counter mainting visibility over how many eggs we have prepped to hatch per wave
|
||||
std::vector<LWOOBJID> hatchList = {}; //Global list maintaining a record of all the eggs we have prepped to hatch for a wave
|
||||
|
||||
const std::string defaultFacingZone = "Zone3Vol"; //Maintains a default facing to ensure appropriate Spider Boss positioning for teleported players
|
||||
std::vector<int> inZoneTable = {}; //Keeps track through player ID index what quadrant of the zone the player is in now
|
||||
std::vector<int> fromZoneTable = {}; //Keeps track through player ID index what quadrant of the zone the player was last in
|
||||
|
||||
const float defaultAnimPause = 2.5f; //Default period of time to pause between missing animation actions
|
||||
const std::u16string spiderJeerAnim = u"taunt"; //Animation Spider Boss plays to antagonize the player
|
||||
const std::u16string spiderROFAnim = u"attack-fire"; //Animation Spider Boss plays to telegraph the ROF attack
|
||||
const std::u16string spiderWithdrawAnim = u"withdraw"; //Animation Spider Boss plays to withdraw to the top of the mountain
|
||||
const std::u16string spiderAdvanceAnim = u"advance"; //Animation Spider Boss plays to come back down from the mountain
|
||||
const std::u16string spiderWithdrawIdle = u"idle-withdrawn"; //Animation Spider Boss plays to idle on the mountain
|
||||
const std::u16string spiderShootLeft = u"attack-shoot-left"; //Animation Spider Boss plays to RFS shoot CCW
|
||||
const std::u16string spiderShootRght = u"attack-shoot-right"; //Animation Spider Boss plays to RFS shoot CW
|
||||
const std::u16string spiderSingleShot = u"attack-fire-single"; //Animation Spider Boss plays for a single shot
|
||||
|
||||
const uint32_t bossBulletSkill = 303; //Generic Spider Boss long range attack
|
||||
const uint32_t bossSmashSkill = 322; //Generic Spider Boss short range attack
|
||||
const uint32_t bossQueueSkill = 1568; //Empty skill to queue for special attack timing
|
||||
const uint32_t bossLandingSkill = 1539; //Generic Spider Boss landing attack
|
||||
const uint32_t bossSwipeSkill = 1573; //Generic Spider Boss landing attack
|
||||
|
||||
const float smashSkillLength = 3.1f; //Time (in seconds) the boss smash skill lasts
|
||||
|
||||
const float s1DelayMin = 10.0f; //Minimum time until calling for another Rapid Fire Shot
|
||||
const float s1DelayMax = 15.0f; //Maximum time until calling for another Rapid Fire Shot
|
||||
const float s2DelayMin = 10.0f; //Minimum time until calling for another Rain Of Fire
|
||||
const float s2DelayMax = 15.0f; //Maximum time until calling for another Rain Of Fire
|
||||
|
||||
const unsigned int instanceZoneID = 1102; //Zone ID for the Spider Queen fight instance
|
||||
const unsigned int instanceMissionID = 1941; //Achievement to update for beating the instanced Boss
|
||||
|
||||
//Establishes a link for the Spider to identify rapid fire targets based on zone reference
|
||||
const std::map<std::string, std::vector<std::string>> rapidFireTargetTable = {
|
||||
{"Zone1Vol", {"Zone8Targets", "Zone1Targets", "Zone2Targets"}},
|
||||
{"Zone2Vol", {"Zone1Targets", "Zone2Targets", "Zone3Targets"}},
|
||||
{"Zone3Vol", {"Zone2Targets", "Zone3Targets", "Zone4Targets"}},
|
||||
{"Zone4Vol", {"Zone3Targets", "Zone4Targets", "Zone5Targets"}},
|
||||
{"Zone5Vol", {"Zone4Targets", "Zone5Targets", "Zone6Targets"}},
|
||||
{"Zone6Vol", {"Zone5Targets", "Zone6Targets", "Zone7Targets"}},
|
||||
{"Zone7Vol", {"Zone6Targets", "Zone7Targets", "Zone8Targets"}},
|
||||
{"Zone8Vol", {"Zone7Targets", "Zone8Targets", "Zone1Targets"}}
|
||||
};
|
||||
|
||||
const std::vector<std::string> ROFTargetGroupIDTable = {
|
||||
"ROF_Targets_00",
|
||||
"ROF_Targets_01",
|
||||
"ROF_Targets_02",
|
||||
"ROF_Targets_03",
|
||||
"ROF_Targets_04"
|
||||
};
|
||||
|
||||
std::vector<LWOOBJID> attackTargetTable;
|
||||
std::vector<LWOOBJID> impactList;
|
||||
};
|
3
dScripts/02_server/Enemy/AG/CMakeLists.txt
Normal file
3
dScripts/02_server/Enemy/AG/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY_AG
|
||||
"BossSpiderQueenEnemyServer.cpp"
|
||||
PARENT_SCOPE)
|
152
dScripts/02_server/Enemy/AM/AmDarklingDragon.cpp
Normal file
152
dScripts/02_server/Enemy/AM/AmDarklingDragon.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
#include "AmDarklingDragon.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
|
||||
void AmDarklingDragon::OnStartup(Entity* self) {
|
||||
self->SetVar<int32_t>(u"weakspot", 0);
|
||||
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
if (baseCombatAIComponent != nullptr) {
|
||||
baseCombatAIComponent->SetStunImmune(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AmDarklingDragon::OnDie(Entity* self, Entity* killer) {
|
||||
if (self->GetVar<bool>(u"bDied")) {
|
||||
return;
|
||||
}
|
||||
|
||||
self->SetVar<bool>(u"bDied", true);
|
||||
|
||||
auto golemId = self->GetVar<LWOOBJID>(u"Golem");
|
||||
|
||||
auto* golem = EntityManager::Instance()->GetEntity(golemId);
|
||||
|
||||
if (golem != nullptr) {
|
||||
golem->Smash(self->GetObjectID());
|
||||
}
|
||||
}
|
||||
|
||||
void AmDarklingDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {
|
||||
GameMessages::SendPlayFXEffect(self, -1, u"gothit", "", LWOOBJID_EMPTY, 1, 1, true);
|
||||
|
||||
if (true) {
|
||||
auto weakpoint = self->GetVar<int32_t>(u"weakspot");
|
||||
|
||||
if (weakpoint == 1) {
|
||||
self->Smash(attacker->GetObjectID());
|
||||
}
|
||||
}
|
||||
|
||||
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent != nullptr) {
|
||||
if (destroyableComponent->GetArmor() > 0) return;
|
||||
|
||||
auto weakpoint = self->GetVar<int32_t>(u"weakpoint");
|
||||
|
||||
if (weakpoint == 0) {
|
||||
self->AddTimer("ReviveTimer", 12);
|
||||
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
if (baseCombatAIComponent != nullptr) {
|
||||
baseCombatAIComponent->SetDisabled(true);
|
||||
baseCombatAIComponent->SetStunned(true);
|
||||
}
|
||||
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->Interrupt();
|
||||
}
|
||||
|
||||
self->SetVar<int32_t>(u"weakpoint", 2);
|
||||
|
||||
GameMessages::SendPlayAnimation(self, u"stunstart", 1.7f);
|
||||
|
||||
self->AddTimer("timeToStunLoop", 1);
|
||||
|
||||
auto position = self->GetPosition();
|
||||
auto forward = self->GetRotation().GetForwardVector();
|
||||
auto backwards = forward * -1;
|
||||
|
||||
forward.x *= 10;
|
||||
forward.z *= 10;
|
||||
|
||||
auto rotation = self->GetRotation();
|
||||
|
||||
auto objectPosition = NiPoint3();
|
||||
|
||||
objectPosition.y = position.y;
|
||||
objectPosition.x = position.x - (backwards.x * 8);
|
||||
objectPosition.z = position.z - (backwards.z * 8);
|
||||
|
||||
auto golem = self->GetVar<int32_t>(u"DragonSmashingGolem");
|
||||
|
||||
EntityInfo info{};
|
||||
info.lot = golem != 0 ? golem : 8340;
|
||||
info.pos = objectPosition;
|
||||
info.rot = rotation;
|
||||
info.spawnerID = self->GetObjectID();
|
||||
info.settings = {
|
||||
new LDFData<std::string>(u"rebuild_activators",
|
||||
std::to_string(objectPosition.x + forward.x) + "\x1f" +
|
||||
std::to_string(objectPosition.y) + "\x1f" +
|
||||
std::to_string(objectPosition.z + forward.z)
|
||||
),
|
||||
new LDFData<int32_t>(u"respawn", 100000),
|
||||
new LDFData<float>(u"rebuild_reset_time", 15),
|
||||
new LDFData<bool>(u"no_timed_spawn", true),
|
||||
new LDFData<LWOOBJID>(u"Dragon", self->GetObjectID())
|
||||
};
|
||||
|
||||
auto* golemObject = EntityManager::Instance()->CreateEntity(info);
|
||||
|
||||
EntityManager::Instance()->ConstructEntity(golemObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AmDarklingDragon::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "ReviveHeldTimer") {
|
||||
self->AddTimer("backToAttack", 2.5);
|
||||
} else if (timerName == "ExposeWeakSpotTimer") {
|
||||
self->SetVar<int32_t>(u"weakspot", 1);
|
||||
} else if (timerName == "timeToStunLoop") {
|
||||
GameMessages::SendPlayAnimation(self, u"stunloop", 1.8f);
|
||||
} else if (timerName == "ReviveTimer") {
|
||||
GameMessages::SendPlayAnimation(self, u"stunend", 2.0f);
|
||||
self->AddTimer("backToAttack", 1);
|
||||
} else if (timerName == "backToAttack") {
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
if (baseCombatAIComponent != nullptr) {
|
||||
baseCombatAIComponent->SetDisabled(false);
|
||||
baseCombatAIComponent->SetStunned(false);
|
||||
}
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->Interrupt();
|
||||
}
|
||||
self->SetVar<int32_t>(u"weakspot", -1);
|
||||
GameMessages::SendNotifyObject(self->GetObjectID(), self->GetObjectID(), u"DragonRevive", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
}
|
||||
|
||||
void AmDarklingDragon::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) {
|
||||
if (args != "rebuildDone") return;
|
||||
|
||||
self->AddTimer("ExposeWeakSpotTimer", 3.8f);
|
||||
|
||||
self->CancelTimer("ReviveTimer");
|
||||
|
||||
self->AddTimer("ReviveHeldTimer", 10.5f);
|
||||
|
||||
self->SetVar<LWOOBJID>(u"Golem", sender->GetObjectID());
|
||||
|
||||
GameMessages::SendPlayAnimation(self, u"quickbuildhold", 1.9f);
|
||||
}
|
48
dScripts/02_server/Enemy/AM/AmDarklingDragon.h
Normal file
48
dScripts/02_server/Enemy/AM/AmDarklingDragon.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AmDarklingDragon : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief When called, this function will make self immune to stuns and initialize a weakspot boolean to false.
|
||||
*
|
||||
* @param self The Entity that called this function.
|
||||
*/
|
||||
void OnStartup(Entity* self) override;
|
||||
/**
|
||||
* @brief When called, this function will destroy the golem if it was alive, otherwise returns immediately.
|
||||
*
|
||||
* @param self The Entity that called this function.
|
||||
* @param killer The Entity that killed self.
|
||||
*/
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
/**
|
||||
* @brief When self is hit or healed, this function will check if self is at zero armor. If self is at zero armor, a golem Entity Quick Build
|
||||
* is spawned that, when built, will reveal a weakpoint on the dragon that if hit will smash the dragon instantly. If at more than zero armor,
|
||||
* this function returns early.
|
||||
*
|
||||
* @param self The Entity that was hit.
|
||||
* @param attacker The Entity that attacked self.
|
||||
* @param damage The amount of damage attacker did to self.
|
||||
*/
|
||||
void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override;
|
||||
/**
|
||||
* @brief Called when self has a timer that ended.
|
||||
*
|
||||
* @param self The Entity who owns a timer that finished.
|
||||
* @param timerName The name of a timer attacked to self that has ended.
|
||||
*/
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
/**
|
||||
* @brief When the Client has finished rebuilding the Golem for the dragon, this function exposes the weak spot for a set amount of time.
|
||||
*
|
||||
* @param self The Entity that called this script.
|
||||
* @param sender The Entity that sent a fired event.
|
||||
* @param args The argument that tells us what event has been fired off.
|
||||
* @param param1 Unused in this script.
|
||||
* @param param2 Unused in this script.
|
||||
* @param param3 Unused in this script.
|
||||
*/
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override;
|
||||
};
|
6
dScripts/02_server/Enemy/AM/AmDarklingMech.cpp
Normal file
6
dScripts/02_server/Enemy/AM/AmDarklingMech.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "AmDarklingMech.h"
|
||||
|
||||
void AmDarklingMech::OnStartup(Entity* self) {
|
||||
BaseEnemyMech::OnStartup(self);
|
||||
qbTurretLOT = 13171;
|
||||
}
|
9
dScripts/02_server/Enemy/AM/AmDarklingMech.h
Normal file
9
dScripts/02_server/Enemy/AM/AmDarklingMech.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
#include "BaseEnemyMech.h"
|
||||
|
||||
class AmDarklingMech : public BaseEnemyMech
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
};
|
24
dScripts/02_server/Enemy/AM/AmSkeletonEngineer.cpp
Normal file
24
dScripts/02_server/Enemy/AM/AmSkeletonEngineer.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "AmSkeletonEngineer.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "SkillComponent.h"
|
||||
|
||||
void AmSkeletonEngineer::OnHit(Entity* self, Entity* attacker) {
|
||||
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
if (destroyableComponent == nullptr || skillComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (destroyableComponent->GetHealth() < 12 && !self->GetVar<bool>(u"injured")) {
|
||||
self->SetVar(u"injured", true);
|
||||
|
||||
skillComponent->CalculateBehavior(953, 19864, self->GetObjectID(), true);
|
||||
|
||||
const auto attackerID = attacker->GetObjectID();
|
||||
|
||||
self->AddCallbackTimer(4.5f, [this, self, attackerID]() {
|
||||
self->Smash(attackerID);
|
||||
});
|
||||
}
|
||||
}
|
9
dScripts/02_server/Enemy/AM/AmSkeletonEngineer.h
Normal file
9
dScripts/02_server/Enemy/AM/AmSkeletonEngineer.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
#include "EnemyNjBuff.h"
|
||||
|
||||
class AmSkeletonEngineer : public EnemyNjBuff
|
||||
{
|
||||
public:
|
||||
void OnHit(Entity* self, Entity* attacker) override;
|
||||
};
|
5
dScripts/02_server/Enemy/AM/CMakeLists.txt
Normal file
5
dScripts/02_server/Enemy/AM/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY_AM
|
||||
"AmDarklingMech.cpp"
|
||||
"AmSkeletonEngineer.cpp"
|
||||
"AmDarklingDragon.cpp"
|
||||
PARENT_SCOPE)
|
45
dScripts/02_server/Enemy/CMakeLists.txt
Normal file
45
dScripts/02_server/Enemy/CMakeLists.txt
Normal file
@ -0,0 +1,45 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY)
|
||||
|
||||
add_subdirectory(AG)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_ENEMY_AG})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY ${DSCRIPTS_SOURCES_02_SERVER_ENEMY} "AG/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(AM)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_ENEMY_AM})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY ${DSCRIPTS_SOURCES_02_SERVER_ENEMY} "AM/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(FV)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_ENEMY_FV})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY ${DSCRIPTS_SOURCES_02_SERVER_ENEMY} "FV/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(General)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_ENEMY_GENERAL})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY ${DSCRIPTS_SOURCES_02_SERVER_ENEMY} "General/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(Survival)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_ENEMY_SURVIVAL})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY ${DSCRIPTS_SOURCES_02_SERVER_ENEMY} "Survival/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(VE)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_ENEMY_VE})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY ${DSCRIPTS_SOURCES_02_SERVER_ENEMY} "VE/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(Waves)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_02_SERVER_ENEMY_WAVES})
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY ${DSCRIPTS_SOURCES_02_SERVER_ENEMY} "Waves/${file}")
|
||||
endforeach()
|
||||
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY ${DSCRIPTS_SOURCES_02_SERVER_ENEMY} PARENT_SCOPE)
|
4
dScripts/02_server/Enemy/FV/CMakeLists.txt
Normal file
4
dScripts/02_server/Enemy/FV/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY_FV
|
||||
"FvMaelstromCavalry.cpp"
|
||||
"FvMaelstromDragon.cpp"
|
||||
PARENT_SCOPE)
|
30
dScripts/02_server/Enemy/FV/FvMaelstromCavalry.cpp
Normal file
30
dScripts/02_server/Enemy/FV/FvMaelstromCavalry.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "FvMaelstromCavalry.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
void FvMaelstromCavalry::OnStartup(Entity* self) {
|
||||
for (const auto& group : self->GetGroups()) {
|
||||
const auto& objects = EntityManager::Instance()->GetEntitiesInGroup(group);
|
||||
|
||||
for (auto* obj : objects) {
|
||||
if (obj->GetLOT() != 8551) continue;
|
||||
|
||||
obj->OnFireEventServerSide(self, "ISpawned");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FvMaelstromCavalry::OnDie(Entity* self, Entity* killer) {
|
||||
if (killer == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (killer->GetLOT() != 8665) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& triggers = EntityManager::Instance()->GetEntitiesInGroup("HorsemenTrigger");
|
||||
|
||||
for (auto* trigger : triggers) {
|
||||
trigger->OnFireEventServerSide(self, "HorsemenDeath");
|
||||
}
|
||||
}
|
9
dScripts/02_server/Enemy/FV/FvMaelstromCavalry.h
Normal file
9
dScripts/02_server/Enemy/FV/FvMaelstromCavalry.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class FvMaelstromCavalry : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self);
|
||||
void OnDie(Entity* self, Entity* killer);
|
||||
};
|
175
dScripts/02_server/Enemy/FV/FvMaelstromDragon.cpp
Normal file
175
dScripts/02_server/Enemy/FV/FvMaelstromDragon.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
#include "FvMaelstromDragon.h"
|
||||
#include "EntityManager.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void FvMaelstromDragon::OnStartup(Entity* self) {
|
||||
self->SetVar<int32_t>(u"weakspot", 0);
|
||||
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
if (baseCombatAIComponent != nullptr) {
|
||||
baseCombatAIComponent->SetStunImmune(true);
|
||||
}
|
||||
}
|
||||
|
||||
void FvMaelstromDragon::OnDie(Entity* self, Entity* killer) {
|
||||
if (self->GetVar<bool>(u"bDied")) {
|
||||
return;
|
||||
}
|
||||
|
||||
self->SetVar<bool>(u"bDied", true);
|
||||
|
||||
auto position = self->GetPosition();
|
||||
auto rotation = self->GetRotation();
|
||||
|
||||
auto chestObject = 11229;
|
||||
|
||||
EntityInfo info{};
|
||||
info.lot = chestObject;
|
||||
info.pos = position;
|
||||
info.rot = rotation;
|
||||
info.spawnerID = self->GetObjectID();
|
||||
|
||||
auto* chest = EntityManager::Instance()->CreateEntity(info);
|
||||
|
||||
EntityManager::Instance()->ConstructEntity(chest);
|
||||
|
||||
auto golemId = self->GetVar<LWOOBJID>(u"Golem");
|
||||
|
||||
auto* golem = EntityManager::Instance()->GetEntity(golemId);
|
||||
|
||||
if (golem != nullptr) {
|
||||
golem->Smash(self->GetObjectID());
|
||||
}
|
||||
}
|
||||
|
||||
void FvMaelstromDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {
|
||||
GameMessages::SendPlayFXEffect(self, -1, u"gothit", "", LWOOBJID_EMPTY, 1, 1, true);
|
||||
|
||||
if (true) {
|
||||
auto weakpoint = self->GetVar<int32_t>(u"weakspot");
|
||||
|
||||
if (weakpoint == 1) {
|
||||
self->Smash(attacker->GetObjectID());
|
||||
}
|
||||
}
|
||||
|
||||
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent != nullptr) {
|
||||
Game::logger->Log("FvMaelstromDragon", "Hit %i", destroyableComponent->GetArmor());
|
||||
|
||||
if (destroyableComponent->GetArmor() > 0) return;
|
||||
|
||||
auto weakpoint = self->GetVar<int32_t>(u"weakpoint");
|
||||
|
||||
if (weakpoint == 0) {
|
||||
Game::logger->Log("FvMaelstromDragon", "Activating weakpoint");
|
||||
|
||||
self->AddTimer("ReviveTimer", 12);
|
||||
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
if (baseCombatAIComponent != nullptr) {
|
||||
baseCombatAIComponent->SetDisabled(true);
|
||||
baseCombatAIComponent->SetStunned(true);
|
||||
}
|
||||
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->Interrupt();
|
||||
}
|
||||
|
||||
self->SetVar<int32_t>(u"weakpoint", 2);
|
||||
|
||||
GameMessages::SendPlayAnimation(self, u"stunstart", 1.7f);
|
||||
|
||||
self->AddTimer("timeToStunLoop", 1);
|
||||
|
||||
auto position = self->GetPosition();
|
||||
auto forward = self->GetRotation().GetForwardVector();
|
||||
auto backwards = forward * -1;
|
||||
|
||||
forward.x *= 10;
|
||||
forward.z *= 10;
|
||||
|
||||
auto rotation = self->GetRotation();
|
||||
|
||||
auto objectPosition = NiPoint3();
|
||||
|
||||
objectPosition.y = position.y;
|
||||
objectPosition.x = position.x - (backwards.x * 8);
|
||||
objectPosition.z = position.z - (backwards.z * 8);
|
||||
|
||||
auto golem = self->GetVar<int32_t>(u"DragonSmashingGolem");
|
||||
|
||||
EntityInfo info{};
|
||||
info.lot = golem != 0 ? golem : 8340;
|
||||
info.pos = objectPosition;
|
||||
info.rot = rotation;
|
||||
info.spawnerID = self->GetObjectID();
|
||||
info.settings = {
|
||||
new LDFData<std::string>(u"rebuild_activators",
|
||||
std::to_string(objectPosition.x + forward.x) + "\x1f" +
|
||||
std::to_string(objectPosition.y) + "\x1f" +
|
||||
std::to_string(objectPosition.z + forward.z)
|
||||
),
|
||||
new LDFData<int32_t>(u"respawn", 100000),
|
||||
new LDFData<float>(u"rebuild_reset_time", 15),
|
||||
new LDFData<bool>(u"no_timed_spawn", true),
|
||||
new LDFData<LWOOBJID>(u"Dragon", self->GetObjectID())
|
||||
};
|
||||
|
||||
auto* golemObject = EntityManager::Instance()->CreateEntity(info);
|
||||
|
||||
EntityManager::Instance()->ConstructEntity(golemObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FvMaelstromDragon::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "ReviveHeldTimer") {
|
||||
self->AddTimer("backToAttack", 2.5);
|
||||
} else if (timerName == "ExposeWeakSpotTimer") {
|
||||
self->SetVar<int32_t>(u"weakspot", 1);
|
||||
} else if (timerName == "timeToStunLoop") {
|
||||
GameMessages::SendPlayAnimation(self, u"stunloop", 1.8f);
|
||||
} else if (timerName == "ReviveTimer") {
|
||||
GameMessages::SendPlayAnimation(self, u"stunend", 2.0f);
|
||||
self->AddTimer("backToAttack", 1);
|
||||
} else if (timerName == "backToAttack") {
|
||||
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
if (baseCombatAIComponent != nullptr) {
|
||||
baseCombatAIComponent->SetDisabled(false);
|
||||
baseCombatAIComponent->SetStunned(false);
|
||||
}
|
||||
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->Interrupt();
|
||||
}
|
||||
|
||||
self->SetVar<int32_t>(u"weakspot", -1);
|
||||
|
||||
GameMessages::SendNotifyObject(self->GetObjectID(), self->GetObjectID(), u"DragonRevive", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FvMaelstromDragon::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) {
|
||||
if (args != "rebuildDone") return;
|
||||
|
||||
self->AddTimer("ExposeWeakSpotTimer", 3.8f);
|
||||
|
||||
self->CancelTimer("ReviveTimer");
|
||||
|
||||
self->AddTimer("ReviveHeldTimer", 10.5f);
|
||||
|
||||
self->SetVar<LWOOBJID>(u"Golem", sender->GetObjectID());
|
||||
|
||||
GameMessages::SendPlayAnimation(self, u"quickbuildhold", 1.9f);
|
||||
}
|
13
dScripts/02_server/Enemy/FV/FvMaelstromDragon.h
Normal file
13
dScripts/02_server/Enemy/FV/FvMaelstromDragon.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class FvMaelstromDragon : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) override;
|
||||
};
|
134
dScripts/02_server/Enemy/General/BaseEnemyApe.cpp
Normal file
134
dScripts/02_server/Enemy/General/BaseEnemyApe.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
#include "BaseEnemyApe.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "EntityManager.h"
|
||||
#include "SkillComponent.h"
|
||||
|
||||
void BaseEnemyApe::OnStartup(Entity* self) {
|
||||
self->SetVar<uint32_t>(u"timesStunned", 2);
|
||||
self->SetVar<bool>(u"knockedOut", false);
|
||||
}
|
||||
|
||||
void BaseEnemyApe::OnDie(Entity* self, Entity* killer) {
|
||||
auto* anchor = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"QB"));
|
||||
if (anchor != nullptr && !anchor->GetIsDead()) {
|
||||
anchor->Smash(self->GetObjectID(), SILENT);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseEnemyApe::OnSkillCast(Entity* self, uint32_t skillID) {
|
||||
const auto groundPoundSkill = self->GetVar<uint32_t>(u"GroundPoundSkill") != 0 ? self->GetVar<uint32_t>(u"GroundPoundSkill") : 725;
|
||||
const auto spawnQuickBuildTime = self->GetVar<float_t>(u"spawnQBTime") != 0.0f ? self->GetVar<float_t>(u"spawnQBTime") : 5.0f;
|
||||
|
||||
if (skillID == groundPoundSkill && self->GetVar<LWOOBJID>(u"QB") == LWOOBJID_EMPTY) {
|
||||
self->AddTimer("spawnQBTime", spawnQuickBuildTime);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseEnemyApe::OnHit(Entity* self, Entity* attacker) {
|
||||
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||
if (destroyableComponent != nullptr && destroyableComponent->GetArmor() < 1 && !self->GetBoolean(u"knockedOut")) {
|
||||
StunApe(self, true);
|
||||
self->CancelTimer("spawnQBTime");
|
||||
|
||||
GameMessages::SendPlayAnimation(self, u"disable", 1.7f);
|
||||
|
||||
const auto reviveTime = self->GetVar<float_t>(u"reviveTime") != 0.0f
|
||||
? self->GetVar<float_t>(u"reviveTime") : 12.0f;
|
||||
self->AddTimer("reviveTime", reviveTime);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseEnemyApe::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "reviveTime") {
|
||||
|
||||
// Revives the ape, giving it back some armor
|
||||
const auto timesStunned = self->GetVar<uint32_t>(u"timesStunned");
|
||||
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||
if (destroyableComponent != nullptr) {
|
||||
destroyableComponent->SetArmor(destroyableComponent->GetMaxArmor() / timesStunned);
|
||||
}
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
self->SetVar<uint32_t>(u"timesStunned", timesStunned + 1);
|
||||
StunApe(self, false);
|
||||
|
||||
} else if (timerName == "spawnQBTime" && self->GetVar<LWOOBJID>(u"QB") == LWOOBJID_EMPTY) {
|
||||
// Spawn QB in front of ape.
|
||||
const auto position = self->GetPosition();
|
||||
const auto rotation = self->GetRotation();
|
||||
|
||||
const auto backwardVector = rotation.GetForwardVector() * -1;
|
||||
const auto objectPosition = NiPoint3(
|
||||
position.GetX() - (backwardVector.GetX() * 8),
|
||||
position.GetY(),
|
||||
position.GetZ() - (backwardVector.GetZ() * 8)
|
||||
);
|
||||
|
||||
EntityInfo entityInfo{};
|
||||
|
||||
entityInfo.pos = position;
|
||||
entityInfo.rot = rotation;
|
||||
entityInfo.pos.SetY(entityInfo.pos.GetY() + 13.0f);
|
||||
|
||||
entityInfo.spawnerID = self->GetObjectID();
|
||||
entityInfo.lot = self->GetVar<LOT>(u"QuickbuildAnchorLOT") != 0
|
||||
? self->GetVar<LOT>(u"QuickbuildAnchorLOT") : 7549;
|
||||
entityInfo.settings = {
|
||||
new LDFData<std::string>(u"rebuild_activators",
|
||||
std::to_string(objectPosition.GetX()) + "\x1f" +
|
||||
std::to_string(objectPosition.GetY()) + "\x1f" +
|
||||
std::to_string(objectPosition.GetZ())
|
||||
),
|
||||
new LDFData<bool>(u"no_timed_spawn", true),
|
||||
new LDFData<LWOOBJID>(u"ape", self->GetObjectID())
|
||||
};
|
||||
|
||||
auto* anchor = EntityManager::Instance()->CreateEntity(entityInfo);
|
||||
EntityManager::Instance()->ConstructEntity(anchor);
|
||||
self->SetVar<LWOOBJID>(u"QB", anchor->GetObjectID());
|
||||
|
||||
} else if (timerName == "anchorDamageTimer") {
|
||||
|
||||
// Attacks the ape with some god skill
|
||||
const auto* player = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"smasher"));
|
||||
if (player == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->CalculateBehavior(1273, 29446, self->GetObjectID(), true, false, player->GetObjectID());
|
||||
}
|
||||
|
||||
self->SetVar<LWOOBJID>(u"QB", LWOOBJID_EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseEnemyApe::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) {
|
||||
if (args == "rebuildDone" && sender != nullptr) {
|
||||
self->SetVar<LWOOBJID>(u"smasher", sender->GetObjectID());
|
||||
const auto anchorDamageDelayTime = self->GetVar<float_t>(u"AnchorDamageDelayTime") != 0.0f ? self->GetVar<float_t>(u"AnchorDamageDelayTime") : 0.5f;
|
||||
self->AddTimer("anchorDamageTimer", anchorDamageDelayTime);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseEnemyApe::StunApe(Entity* self, bool stunState) {
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetDisabled(stunState);
|
||||
combatAIComponent->SetStunned(stunState);
|
||||
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->Interrupt();
|
||||
}
|
||||
|
||||
GameMessages::SendSetStunned(self->GetObjectID(), stunState ? PUSH : POP, UNASSIGNED_SYSTEM_ADDRESS, self->GetObjectID(),
|
||||
true, true, true, true, true,
|
||||
true, true, true, true);
|
||||
|
||||
self->SetBoolean(u"knockedOut", stunState);
|
||||
}
|
||||
}
|
15
dScripts/02_server/Enemy/General/BaseEnemyApe.h
Normal file
15
dScripts/02_server/Enemy/General/BaseEnemyApe.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class BaseEnemyApe : public CppScripts::Script {
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
void OnSkillCast(Entity* self, uint32_t skillID) override;
|
||||
void OnHit(Entity* self, Entity* attacker) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) override;
|
||||
private:
|
||||
static void StunApe(Entity* self, bool stunState);
|
||||
};
|
43
dScripts/02_server/Enemy/General/BaseEnemyMech.cpp
Normal file
43
dScripts/02_server/Enemy/General/BaseEnemyMech.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "BaseEnemyMech.h"
|
||||
#include "Entity.h"
|
||||
#include "ControllablePhysicsComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "dpWorld.h"
|
||||
#include "GeneralUtils.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void BaseEnemyMech::OnStartup(Entity* self) {
|
||||
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||
if (destroyableComponent != nullptr) {
|
||||
destroyableComponent->SetFaction(4);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseEnemyMech::OnDie(Entity* self, Entity* killer) {
|
||||
ControllablePhysicsComponent* controlPhys = static_cast<ControllablePhysicsComponent*>(self->GetComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS));
|
||||
if (!controlPhys) return;
|
||||
|
||||
NiPoint3 newLoc = { controlPhys->GetPosition().x, dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(controlPhys->GetPosition()), controlPhys->GetPosition().z };
|
||||
|
||||
EntityInfo info = EntityInfo();
|
||||
std::vector<LDFBaseData*> cfg;
|
||||
std::u16string activatorPosStr;
|
||||
activatorPosStr += (GeneralUtils::to_u16string(controlPhys->GetPosition().x));
|
||||
activatorPosStr.push_back(0x1f);
|
||||
activatorPosStr += (GeneralUtils::to_u16string(controlPhys->GetPosition().y));
|
||||
activatorPosStr.push_back(0x1f);
|
||||
activatorPosStr += (GeneralUtils::to_u16string(controlPhys->GetPosition().z));
|
||||
|
||||
LDFBaseData* activatorPos = new LDFData<std::u16string>(u"rebuild_activators", activatorPosStr);
|
||||
cfg.push_back(activatorPos);
|
||||
info.lot = qbTurretLOT;
|
||||
info.pos = newLoc;
|
||||
info.rot = controlPhys->GetRotation();
|
||||
info.spawnerID = self->GetObjectID();
|
||||
info.settings = cfg;
|
||||
|
||||
Entity* turret = EntityManager::Instance()->CreateEntity(info, nullptr);
|
||||
if (turret) {
|
||||
EntityManager::Instance()->ConstructEntity(turret);
|
||||
}
|
||||
}
|
12
dScripts/02_server/Enemy/General/BaseEnemyMech.h
Normal file
12
dScripts/02_server/Enemy/General/BaseEnemyMech.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class BaseEnemyMech : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
protected:
|
||||
LOT qbTurretLOT = 6254;
|
||||
};
|
||||
|
7
dScripts/02_server/Enemy/General/CMakeLists.txt
Normal file
7
dScripts/02_server/Enemy/General/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY_GENERAL
|
||||
"BaseEnemyMech.cpp"
|
||||
"BaseEnemyApe.cpp"
|
||||
"GfApeSmashingQB.cpp"
|
||||
"TreasureChestDragonServer.cpp"
|
||||
"EnemyNjBuff.cpp"
|
||||
PARENT_SCOPE)
|
12
dScripts/02_server/Enemy/General/EnemyNjBuff.cpp
Normal file
12
dScripts/02_server/Enemy/General/EnemyNjBuff.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "EnemyNjBuff.h"
|
||||
#include "SkillComponent.h"
|
||||
|
||||
void EnemyNjBuff::OnStartup(Entity* self) {
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
skillComponent->CalculateBehavior(1127, 24812, self->GetObjectID(), true);
|
||||
}
|
9
dScripts/02_server/Enemy/General/EnemyNjBuff.h
Normal file
9
dScripts/02_server/Enemy/General/EnemyNjBuff.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class EnemyNjBuff : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
};
|
||||
|
22
dScripts/02_server/Enemy/General/GfApeSmashingQB.cpp
Normal file
22
dScripts/02_server/Enemy/General/GfApeSmashingQB.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "GfApeSmashingQB.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
void GfApeSmashingQB::OnStartup(Entity* self) {
|
||||
self->SetNetworkVar<LWOOBJID>(u"lootTagOwner", self->GetVar<LWOOBJID>(u"lootTagOwner"));
|
||||
}
|
||||
|
||||
void GfApeSmashingQB::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "anchorBreakTime") {
|
||||
self->Smash();
|
||||
}
|
||||
}
|
||||
|
||||
void GfApeSmashingQB::OnRebuildComplete(Entity* self, Entity* target) {
|
||||
auto* ape = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"ape"));
|
||||
if (ape != nullptr) {
|
||||
ape->OnFireEventServerSide(target, "rebuildDone");
|
||||
GameMessages::SendPlayAnimation(self, u"smash", 1.7f);
|
||||
self->AddTimer("anchorBreakTime", 1.0f);
|
||||
}
|
||||
}
|
8
dScripts/02_server/Enemy/General/GfApeSmashingQB.h
Normal file
8
dScripts/02_server/Enemy/General/GfApeSmashingQB.h
Normal file
@ -0,0 +1,8 @@
|
||||
# pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class GfApeSmashingQB : public CppScripts::Script {
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
void OnRebuildComplete(Entity* self, Entity* target) override;
|
||||
};
|
@ -0,0 +1,42 @@
|
||||
#include "TreasureChestDragonServer.h"
|
||||
#include "ScriptedActivityComponent.h"
|
||||
#include "TeamManager.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
void TreasureChestDragonServer::OnStartup(Entity* self) {
|
||||
|
||||
}
|
||||
|
||||
void TreasureChestDragonServer::OnUse(Entity* self, Entity* user) {
|
||||
if (self->GetVar<bool>(u"bUsed")) {
|
||||
return;
|
||||
}
|
||||
|
||||
self->SetVar<bool>(u"bUsed", true);
|
||||
|
||||
auto* scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
|
||||
if (scriptedActivityComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto rating = 1;
|
||||
|
||||
auto* team = TeamManager::Instance()->GetTeam(user->GetObjectID());
|
||||
|
||||
if (team != nullptr) {
|
||||
rating = team->members.size();
|
||||
|
||||
for (const auto member : team->members) {
|
||||
auto* memberObject = EntityManager::Instance()->GetEntity(member);
|
||||
|
||||
if (memberObject == nullptr) continue;
|
||||
|
||||
LootGenerator::Instance().DropActivityLoot(memberObject, self, scriptedActivityComponent->GetActivityID(), rating);
|
||||
}
|
||||
} else {
|
||||
LootGenerator::Instance().DropActivityLoot(user, self, scriptedActivityComponent->GetActivityID(), rating);
|
||||
}
|
||||
|
||||
self->Smash(self->GetObjectID());
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class TreasureChestDragonServer : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnUse(Entity* self, Entity* user) override;
|
||||
};
|
15
dScripts/02_server/Enemy/Survival/AgSurvivalMech.cpp
Normal file
15
dScripts/02_server/Enemy/Survival/AgSurvivalMech.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "AgSurvivalMech.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void AgSurvivalMech::OnStartup(Entity* self) {
|
||||
BaseWavesGenericEnemy::OnStartup(self);
|
||||
|
||||
auto* destroyable = self->GetComponent<DestroyableComponent>();
|
||||
if (destroyable != nullptr) {
|
||||
destroyable->SetFaction(4);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t AgSurvivalMech::GetPoints() {
|
||||
return 200;
|
||||
}
|
7
dScripts/02_server/Enemy/Survival/AgSurvivalMech.h
Normal file
7
dScripts/02_server/Enemy/Survival/AgSurvivalMech.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "BaseWavesGenericEnemy.h"
|
||||
|
||||
class AgSurvivalMech : public BaseWavesGenericEnemy {
|
||||
void OnStartup(Entity* self) override;
|
||||
uint32_t GetPoints() override;
|
||||
};
|
15
dScripts/02_server/Enemy/Survival/AgSurvivalSpiderling.cpp
Normal file
15
dScripts/02_server/Enemy/Survival/AgSurvivalSpiderling.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "AgSurvivalSpiderling.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
|
||||
void AgSurvivalSpiderling::OnStartup(Entity* self) {
|
||||
BaseWavesGenericEnemy::OnStartup(self);
|
||||
|
||||
auto* combatAI = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAI != nullptr) {
|
||||
combatAI->SetStunImmune(true);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t AgSurvivalSpiderling::GetPoints() {
|
||||
return 300;
|
||||
}
|
7
dScripts/02_server/Enemy/Survival/AgSurvivalSpiderling.h
Normal file
7
dScripts/02_server/Enemy/Survival/AgSurvivalSpiderling.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "BaseWavesGenericEnemy.h"
|
||||
|
||||
class AgSurvivalSpiderling : public BaseWavesGenericEnemy {
|
||||
void OnStartup(Entity* self) override;
|
||||
uint32_t GetPoints() override;
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
#include "AgSurvivalStromling.h"
|
||||
|
||||
uint32_t AgSurvivalStromling::GetPoints() {
|
||||
return 100;
|
||||
}
|
6
dScripts/02_server/Enemy/Survival/AgSurvivalStromling.h
Normal file
6
dScripts/02_server/Enemy/Survival/AgSurvivalStromling.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "BaseWavesGenericEnemy.h"
|
||||
|
||||
class AgSurvivalStromling : public BaseWavesGenericEnemy {
|
||||
uint32_t GetPoints() override;
|
||||
};
|
5
dScripts/02_server/Enemy/Survival/CMakeLists.txt
Normal file
5
dScripts/02_server/Enemy/Survival/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY_SURVIVAL
|
||||
"AgSurvivalStromling.cpp"
|
||||
"AgSurvivalMech.cpp"
|
||||
"AgSurvivalSpiderling.cpp"
|
||||
PARENT_SCOPE)
|
3
dScripts/02_server/Enemy/VE/CMakeLists.txt
Normal file
3
dScripts/02_server/Enemy/VE/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY_VE
|
||||
"VeMech.cpp"
|
||||
PARENT_SCOPE)
|
6
dScripts/02_server/Enemy/VE/VeMech.cpp
Normal file
6
dScripts/02_server/Enemy/VE/VeMech.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "VeMech.h"
|
||||
|
||||
void VeMech::OnStartup(Entity* self) {
|
||||
BaseEnemyMech::OnStartup(self);
|
||||
qbTurretLOT = 8432;
|
||||
}
|
7
dScripts/02_server/Enemy/VE/VeMech.h
Normal file
7
dScripts/02_server/Enemy/VE/VeMech.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "BaseEnemyMech.h"
|
||||
|
||||
class VeMech : public BaseEnemyMech {
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
};
|
6
dScripts/02_server/Enemy/Waves/CMakeLists.txt
Normal file
6
dScripts/02_server/Enemy/Waves/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY_WAVES
|
||||
"WaveBossHammerling.cpp"
|
||||
"WaveBossApe.cpp"
|
||||
"WaveBossSpiderling.cpp"
|
||||
"WaveBossHorsemen.cpp"
|
||||
PARENT_SCOPE)
|
41
dScripts/02_server/Enemy/Waves/WaveBossApe.cpp
Normal file
41
dScripts/02_server/Enemy/Waves/WaveBossApe.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include "WaveBossApe.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "Entity.h"
|
||||
|
||||
void WaveBossApe::OnStartup(Entity* self) {
|
||||
BaseWavesGenericEnemy::OnStartup(self);
|
||||
|
||||
self->SetVar<LOT>(u"QuickbuildAnchorLOT", 12900);
|
||||
self->SetVar<uint32_t>(u"GroundPoundSkill", 725);
|
||||
self->SetVar<float_t>(u"reviveTime", 12);
|
||||
self->SetVar<float_t>(u"AnchorDamageDelayTime", 0.5f);
|
||||
self->SetVar<float_t>(u"spawnQBTime", 5.0f);
|
||||
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetDisabled(true);
|
||||
combatAIComponent->SetStunImmune(true);
|
||||
}
|
||||
|
||||
self->AddToGroup("boss");
|
||||
|
||||
BaseEnemyApe::OnStartup(self);
|
||||
}
|
||||
|
||||
void WaveBossApe::OnDie(Entity* self, Entity* killer) {
|
||||
BaseWavesGenericEnemy::OnDie(self, killer);
|
||||
BaseEnemyApe::OnDie(self, killer);
|
||||
}
|
||||
|
||||
void WaveBossApe::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) {
|
||||
if (args == "startAI") {
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetDisabled(false);
|
||||
combatAIComponent->SetStunImmune(false);
|
||||
}
|
||||
} else {
|
||||
BaseEnemyApe::OnFireEventServerSide(self, sender, args, param1, param2, param3);
|
||||
}
|
||||
}
|
10
dScripts/02_server/Enemy/Waves/WaveBossApe.h
Normal file
10
dScripts/02_server/Enemy/Waves/WaveBossApe.h
Normal file
@ -0,0 +1,10 @@
|
||||
#include "BaseWavesGenericEnemy.h"
|
||||
#include "BaseEnemyApe.h"
|
||||
|
||||
class WaveBossApe : public BaseEnemyApe, public BaseWavesGenericEnemy {
|
||||
uint32_t GetPoints() override { return 5000; }
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) override;
|
||||
};
|
25
dScripts/02_server/Enemy/Waves/WaveBossHammerling.cpp
Normal file
25
dScripts/02_server/Enemy/Waves/WaveBossHammerling.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "WaveBossHammerling.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "Entity.h"
|
||||
|
||||
void WaveBossHammerling::OnStartup(Entity* self) {
|
||||
BaseWavesGenericEnemy::OnStartup(self);
|
||||
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetDisabled(true);
|
||||
combatAIComponent->SetStunImmune(true);
|
||||
}
|
||||
|
||||
self->AddToGroup("boss");
|
||||
}
|
||||
|
||||
void WaveBossHammerling::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1,
|
||||
int32_t param2, int32_t param3) {
|
||||
if (args == "startAI") {
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetDisabled(false);
|
||||
}
|
||||
}
|
||||
}
|
9
dScripts/02_server/Enemy/Waves/WaveBossHammerling.h
Normal file
9
dScripts/02_server/Enemy/Waves/WaveBossHammerling.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "BaseWavesGenericEnemy.h"
|
||||
|
||||
class WaveBossHammerling : public BaseWavesGenericEnemy {
|
||||
void OnStartup(Entity* self) override;
|
||||
uint32_t GetPoints() override { return 1000; }
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) override;
|
||||
};
|
26
dScripts/02_server/Enemy/Waves/WaveBossHorsemen.cpp
Normal file
26
dScripts/02_server/Enemy/Waves/WaveBossHorsemen.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "WaveBossHorsemen.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "Entity.h"
|
||||
|
||||
void WaveBossHorsemen::OnStartup(Entity* self) {
|
||||
BaseWavesGenericEnemy::OnStartup(self);
|
||||
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetDisabled(true);
|
||||
combatAIComponent->SetStunImmune(true);
|
||||
}
|
||||
|
||||
self->AddToGroup("boss");
|
||||
}
|
||||
|
||||
void
|
||||
WaveBossHorsemen::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) {
|
||||
if (args == "startAI") {
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetDisabled(false);
|
||||
}
|
||||
}
|
||||
}
|
9
dScripts/02_server/Enemy/Waves/WaveBossHorsemen.h
Normal file
9
dScripts/02_server/Enemy/Waves/WaveBossHorsemen.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "BaseWavesGenericEnemy.h"
|
||||
|
||||
class WaveBossHorsemen : public BaseWavesGenericEnemy {
|
||||
uint32_t GetPoints() override { return 5000; }
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) override;
|
||||
};
|
26
dScripts/02_server/Enemy/Waves/WaveBossSpiderling.cpp
Normal file
26
dScripts/02_server/Enemy/Waves/WaveBossSpiderling.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "WaveBossSpiderling.h"
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "Entity.h"
|
||||
|
||||
void WaveBossSpiderling::OnStartup(Entity* self) {
|
||||
BaseWavesGenericEnemy::OnStartup(self);
|
||||
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetDisabled(true);
|
||||
combatAIComponent->SetStunImmune(true);
|
||||
}
|
||||
|
||||
self->AddToGroup("boss");
|
||||
}
|
||||
|
||||
void WaveBossSpiderling::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1,
|
||||
int32_t param2, int32_t param3) {
|
||||
if (args == "startAI") {
|
||||
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
|
||||
if (combatAIComponent != nullptr) {
|
||||
combatAIComponent->SetDisabled(false);
|
||||
combatAIComponent->SetStunImmune(false);
|
||||
}
|
||||
}
|
||||
}
|
9
dScripts/02_server/Enemy/Waves/WaveBossSpiderling.h
Normal file
9
dScripts/02_server/Enemy/Waves/WaveBossSpiderling.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "BaseWavesGenericEnemy.h"
|
||||
|
||||
class WaveBossSpiderling : public BaseWavesGenericEnemy {
|
||||
uint32_t GetPoints() override { return 5000; }
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) override;
|
||||
};
|
52
dScripts/02_server/Equipment/BootyDigServer.cpp
Normal file
52
dScripts/02_server/Equipment/BootyDigServer.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "BootyDigServer.h"
|
||||
#include "EntityManager.h"
|
||||
#include "RenderComponent.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "MissionTaskType.h"
|
||||
|
||||
void BootyDigServer::OnStartup(Entity* self) {
|
||||
auto* zoneControlObject = EntityManager::Instance()->GetZoneControlEntity();
|
||||
if (zoneControlObject != nullptr) {
|
||||
zoneControlObject->OnFireEventServerSide(self, "CheckForPropertyOwner");
|
||||
}
|
||||
}
|
||||
|
||||
void BootyDigServer::OnPlayerLoaded(Entity* self, Entity* player) {
|
||||
auto* zoneControlObject = EntityManager::Instance()->GetZoneControlEntity();
|
||||
if (zoneControlObject != nullptr) {
|
||||
zoneControlObject->OnFireEventServerSide(self, "CheckForPropertyOwner");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BootyDigServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) {
|
||||
|
||||
auto propertyOwner = self->GetNetworkVar<std::string>(u"PropertyOwnerID");
|
||||
auto* player = self->GetParentEntity();
|
||||
if (player == nullptr)
|
||||
return;
|
||||
|
||||
if (args == "ChestReady" && (propertyOwner == std::to_string(LWOOBJID_EMPTY) || player->GetVar<bool>(u"bootyDug"))) {
|
||||
self->Smash(self->GetObjectID(), SILENT);
|
||||
} else if (args == "ChestOpened") {
|
||||
// Make sure players only dig up one booty per instance
|
||||
player->SetVar<bool>(u"bootyDug", true);
|
||||
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) {
|
||||
auto* mission = missionComponent->GetMission(1881);
|
||||
if (mission != nullptr && (mission->GetMissionState() == MissionState::MISSION_STATE_ACTIVE || mission->GetMissionState() == MissionState::MISSION_STATE_COMPLETE_ACTIVE)) {
|
||||
mission->Progress(MissionTaskType::MISSION_TASK_TYPE_SCRIPT, self->GetLOT());
|
||||
|
||||
auto* renderComponent = self->GetComponent<RenderComponent>();
|
||||
if (renderComponent != nullptr)
|
||||
renderComponent->PlayEffect(7730, u"cast", "bootyshine");
|
||||
|
||||
LootGenerator::Instance().DropLoot(player, self, 231, 75, 75);
|
||||
}
|
||||
}
|
||||
} else if (args == "ChestDead") {
|
||||
self->Smash(player->GetObjectID(), SILENT);
|
||||
}
|
||||
}
|
8
dScripts/02_server/Equipment/BootyDigServer.h
Normal file
8
dScripts/02_server/Equipment/BootyDigServer.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class BootyDigServer : public CppScripts::Script {
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnPlayerLoaded(Entity* self, Entity* player) override;
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override;
|
||||
};
|
4
dScripts/02_server/Equipment/CMakeLists.txt
Normal file
4
dScripts/02_server/Equipment/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_EQUIPMENT
|
||||
"MaestromExtracticatorServer.cpp"
|
||||
"BootyDigServer.cpp"
|
||||
PARENT_SCOPE)
|
50
dScripts/02_server/Equipment/MaestromExtracticatorServer.cpp
Normal file
50
dScripts/02_server/Equipment/MaestromExtracticatorServer.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "MaestromExtracticatorServer.h"
|
||||
#include "GameMessages.h"
|
||||
#include "GeneralUtils.h"
|
||||
#include "EntityManager.h"
|
||||
#include "MissionComponent.h"
|
||||
|
||||
void MaestromExtracticatorServer::OnStartup(Entity* self) {
|
||||
//self:SetNetworkVar("current_anim", failAnim)
|
||||
GameMessages::SendPlayAnimation(self, GeneralUtils::ASCIIToUTF16(failAnim));
|
||||
|
||||
self->AddTimer("PlayFail", defaultTime);
|
||||
self->AddTimer("RemoveSample", destroyAfterNoSampleTime);
|
||||
}
|
||||
|
||||
void MaestromExtracticatorServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1,
|
||||
int32_t param2, int32_t param3) {
|
||||
if (sender == nullptr)
|
||||
return;
|
||||
|
||||
if (args == "attemptCollection") {
|
||||
Entity* player = EntityManager::Instance()->GetEntity(self->GetSpawnerID());
|
||||
if (!player) return;
|
||||
|
||||
auto missionComponent = player->GetComponent<MissionComponent>();
|
||||
if (missionComponent == nullptr) return;
|
||||
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_SMASH, 14718);
|
||||
CollectSample(self, sender->GetObjectID());
|
||||
sender->ScheduleKillAfterUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void MaestromExtracticatorServer::CollectSample(Entity* self, LWOOBJID sampleObj) {
|
||||
PlayAnimAndReturnTime(self, collectAnim);
|
||||
self->AddTimer("RemoveSample", defaultTime);
|
||||
}
|
||||
|
||||
void MaestromExtracticatorServer::PlayAnimAndReturnTime(Entity* self, std::string animID) {
|
||||
GameMessages::SendPlayAnimation(self, GeneralUtils::ASCIIToUTF16(animID));
|
||||
}
|
||||
|
||||
void MaestromExtracticatorServer::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "RemoveSample") {
|
||||
self->ScheduleKillAfterUpdate();
|
||||
}
|
||||
|
||||
if (timerName == "PlayFail") {
|
||||
GameMessages::SendPlayAnimation(self, GeneralUtils::ASCIIToUTF16(failAnim));
|
||||
}
|
||||
}
|
18
dScripts/02_server/Equipment/MaestromExtracticatorServer.h
Normal file
18
dScripts/02_server/Equipment/MaestromExtracticatorServer.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class MaestromExtracticatorServer : public CppScripts::Script {
|
||||
public:
|
||||
void OnStartup(Entity* self);
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3);
|
||||
void CollectSample(Entity* self, LWOOBJID sampleObj);
|
||||
void PlayAnimAndReturnTime(Entity* self, std::string animID);
|
||||
void OnTimerDone(Entity* self, std::string timerName);
|
||||
|
||||
private:
|
||||
const std::string failAnim = "idle_maelstrom";
|
||||
const std::string collectAnim = "collect_maelstrom";
|
||||
const float defaultTime = 4.0f;
|
||||
const float destroyAfterNoSampleTime = 8.0f;
|
||||
};
|
17
dScripts/02_server/Map/AG/AgBugsprayer.cpp
Normal file
17
dScripts/02_server/Map/AG/AgBugsprayer.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "AgBugsprayer.h"
|
||||
#include "SkillComponent.h"
|
||||
|
||||
void AgBugsprayer::OnRebuildComplete(Entity* self, Entity* target) {
|
||||
self->AddTimer("castSkill", 1);
|
||||
self->SetOwnerOverride(target->GetObjectID());
|
||||
}
|
||||
|
||||
void AgBugsprayer::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "castSkill") {
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent == nullptr) return;
|
||||
|
||||
skillComponent->CalculateBehavior(1435, 36581, LWOOBJID_EMPTY);
|
||||
}
|
||||
}
|
10
dScripts/02_server/Map/AG/AgBugsprayer.h
Normal file
10
dScripts/02_server/Map/AG/AgBugsprayer.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AgBugsprayer : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnRebuildComplete(Entity* self, Entity* target) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
};
|
||||
|
27
dScripts/02_server/Map/AG/AgCagedBricksServer.cpp
Normal file
27
dScripts/02_server/Map/AG/AgCagedBricksServer.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "AgCagedBricksServer.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "Character.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
void AgCagedBricksServer::OnUse(Entity* self, Entity* user) {
|
||||
//Tell the client to spawn the baby spiderling:
|
||||
auto spooders = EntityManager::Instance()->GetEntitiesInGroup("cagedSpider");
|
||||
for (auto spodder : spooders) {
|
||||
GameMessages::SendFireEventClientSide(spodder->GetObjectID(), user->GetSystemAddress(), u"toggle", LWOOBJID_EMPTY, 0, 0, user->GetObjectID());
|
||||
}
|
||||
|
||||
//Set the flag & mission status:
|
||||
auto character = user->GetCharacter();
|
||||
|
||||
if (!character) return;
|
||||
|
||||
character->SetPlayerFlag(74, true);
|
||||
|
||||
//Remove the maelstrom cube:
|
||||
auto inv = static_cast<InventoryComponent*>(user->GetComponent(COMPONENT_TYPE_INVENTORY));
|
||||
|
||||
if (inv) {
|
||||
inv->RemoveItem(14553, 1);
|
||||
}
|
||||
}
|
6
dScripts/02_server/Map/AG/AgCagedBricksServer.h
Normal file
6
dScripts/02_server/Map/AG/AgCagedBricksServer.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AgCagedBricksServer : public CppScripts::Script {
|
||||
void OnUse(Entity* self, Entity* user);
|
||||
};
|
55
dScripts/02_server/Map/AG/AgLaserSensorServer.cpp
Normal file
55
dScripts/02_server/Map/AG/AgLaserSensorServer.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "AgLaserSensorServer.h"
|
||||
|
||||
#include "PhantomPhysicsComponent.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "AgMonumentLaserServer.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
void AgLaserSensorServer::OnStartup(Entity* self) {
|
||||
|
||||
PhantomPhysicsComponent* physComp = static_cast<PhantomPhysicsComponent*>(self->GetComponent(COMPONENT_TYPE_PHANTOM_PHYSICS));
|
||||
physComp->SetPhysicsEffectActive(true);
|
||||
physComp->SetEffectType(2); // repulse (prolly should make definitions of these are in Entity.cpp)
|
||||
physComp->SetDirectionalMultiplier(static_cast<float>(m_RepelForce));
|
||||
physComp->SetDirection(NiPoint3::UNIT_Y);
|
||||
|
||||
m_Skill = self->GetComponent<SkillComponent>();
|
||||
}
|
||||
|
||||
|
||||
void AgLaserSensorServer::OnCollisionPhantom(Entity* self, Entity* target) {
|
||||
|
||||
if (!m_Skill) return;
|
||||
|
||||
|
||||
Entity* laser = nullptr;
|
||||
|
||||
for (auto script : EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_SCRIPT)) {
|
||||
|
||||
AgMonumentLaserServer* hasLaser = (AgMonumentLaserServer*)script;
|
||||
|
||||
if (hasLaser) {
|
||||
const auto source = script->GetPosition();
|
||||
const auto obj = self->GetObjectID();
|
||||
|
||||
if (obj == 76690936093053 && Vector3::DistanceSquared(source, NiPoint3(149.007f, 417.083f, 218.346f)) <= 1.0f) {
|
||||
laser = script;
|
||||
break;
|
||||
} else if (obj == 75866302318824 && Vector3::DistanceSquared(source, NiPoint3(48.6403f, 403.803f, 196.711f)) <= 1.0f) {
|
||||
laser = script;
|
||||
break;
|
||||
} else if (obj == 75866302318822 && Vector3::DistanceSquared(source, NiPoint3(19.2155f, 420.083f, 249.226f)) <= 1.0f) {
|
||||
laser = script;
|
||||
break;
|
||||
} else if (obj == 75866302318823 && Vector3::DistanceSquared(source, NiPoint3(-6.61596f, 404.633f, 274.323f)) <= 1.0f) {
|
||||
laser = script;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (laser != nullptr) {
|
||||
m_Skill->CalculateBehavior(m_SkillCastID, 15714, target->GetObjectID());
|
||||
}
|
||||
}
|
15
dScripts/02_server/Map/AG/AgLaserSensorServer.h
Normal file
15
dScripts/02_server/Map/AG/AgLaserSensorServer.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class SkillComponent;
|
||||
|
||||
class AgLaserSensorServer : public CppScripts::Script {
|
||||
public:
|
||||
void OnStartup(Entity* self);
|
||||
void OnCollisionPhantom(Entity* self, Entity* target);
|
||||
private:
|
||||
SkillComponent* m_Skill;
|
||||
int m_RepelForce = -25;
|
||||
int m_SkillCastID = 163;
|
||||
};
|
||||
|
33
dScripts/02_server/Map/AG/AgMonumentBirds.cpp
Normal file
33
dScripts/02_server/Map/AG/AgMonumentBirds.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "AgMonumentBirds.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
//--------------------------------------------------------------
|
||||
//Makes the ag birds fly away when you get close and smashes them.
|
||||
//Created mrb... 6 / 3 / 11
|
||||
//Ported Max 20/07/2020
|
||||
//--------------------------------------------------------------
|
||||
|
||||
void AgMonumentBirds::OnStartup(Entity* self) {
|
||||
self->SetProximityRadius(flyRadius, "MonumentBirds");
|
||||
}
|
||||
|
||||
void AgMonumentBirds::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) {
|
||||
if (self->GetVar<bool>(u"IsFlying")) return;
|
||||
|
||||
if (name == "MonumentBirds" && status == "ENTER") {
|
||||
self->AddTimer("killBird", 1.0f);
|
||||
GameMessages::SendPlayAnimation(self, sOnProximityAnim);
|
||||
self->SetVar<bool>(u"IsFlying", true);
|
||||
self->SetVar<LWOOBJID>(u"PlayerID", entering->GetObjectID());
|
||||
}
|
||||
}
|
||||
|
||||
void AgMonumentBirds::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName != "killBird") return;
|
||||
|
||||
auto* player = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"PlayerID"));
|
||||
|
||||
if (player == nullptr) return;
|
||||
|
||||
self->ScheduleKillAfterUpdate(player);
|
||||
}
|
13
dScripts/02_server/Map/AG/AgMonumentBirds.h
Normal file
13
dScripts/02_server/Map/AG/AgMonumentBirds.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AgMonumentBirds : public CppScripts::Script {
|
||||
public:
|
||||
void OnStartup(Entity* self);
|
||||
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status);
|
||||
void OnTimerDone(Entity* self, std::string timerName);
|
||||
|
||||
private:
|
||||
std::u16string sOnProximityAnim = u"fly1";
|
||||
float flyRadius = 5.0f;
|
||||
};
|
20
dScripts/02_server/Map/AG/AgMonumentLaserServer.cpp
Normal file
20
dScripts/02_server/Map/AG/AgMonumentLaserServer.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include "AgMonumentLaserServer.h"
|
||||
|
||||
void AgMonumentLaserServer::OnStartup(Entity* self) {
|
||||
/*
|
||||
self->SetProximityRadius(m_Radius, "MonumentLaser");
|
||||
|
||||
std::cout << "Monument Laser " << self->GetObjectID() << " is at " << self->GetPosition().GetX()
|
||||
<< ","<< self->GetPosition().GetY() << "," << self->GetPosition().GetZ() << std::endl;
|
||||
*/
|
||||
}
|
||||
|
||||
void AgMonumentLaserServer::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) {
|
||||
/*
|
||||
if (status == "ENTER") {
|
||||
|
||||
std::cout << "Monument laser ID: " << self->GetObjectID() << std::endl;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
10
dScripts/02_server/Map/AG/AgMonumentLaserServer.h
Normal file
10
dScripts/02_server/Map/AG/AgMonumentLaserServer.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AgMonumentLaserServer : public CppScripts::Script {
|
||||
public:
|
||||
void OnStartup(Entity* self);
|
||||
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status);
|
||||
private:
|
||||
float m_Radius = 25.0f;
|
||||
};
|
9
dScripts/02_server/Map/AG/AgMonumentRaceCancel.cpp
Normal file
9
dScripts/02_server/Map/AG/AgMonumentRaceCancel.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "AgMonumentRaceCancel.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
void AgMonumentRaceCancel::OnCollisionPhantom(Entity* self, Entity* target) {
|
||||
auto managers = EntityManager::Instance()->GetEntitiesInGroup("race_manager");
|
||||
if (!managers.empty()) {
|
||||
managers[0]->OnFireEventServerSide(target, "course_cancel");
|
||||
}
|
||||
}
|
6
dScripts/02_server/Map/AG/AgMonumentRaceCancel.h
Normal file
6
dScripts/02_server/Map/AG/AgMonumentRaceCancel.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AgMonumentRaceCancel : public CppScripts::Script {
|
||||
void OnCollisionPhantom(Entity* self, Entity* target) override;
|
||||
};
|
15
dScripts/02_server/Map/AG/AgMonumentRaceGoal.cpp
Normal file
15
dScripts/02_server/Map/AG/AgMonumentRaceGoal.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "AgMonumentRaceGoal.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
|
||||
void AgMonumentRaceGoal::OnStartup(Entity* self) {
|
||||
self->SetProximityRadius(15, "RaceGoal");
|
||||
}
|
||||
|
||||
void AgMonumentRaceGoal::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) {
|
||||
if (name == "RaceGoal" && entering->IsPlayer() && status == "ENTER") {
|
||||
auto* manager = EntityManager::Instance()->GetEntitiesInGroup("race_manager")[0];
|
||||
|
||||
manager->OnFireEventServerSide(entering, "course_finish");
|
||||
}
|
||||
}
|
9
dScripts/02_server/Map/AG/AgMonumentRaceGoal.h
Normal file
9
dScripts/02_server/Map/AG/AgMonumentRaceGoal.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AgMonumentRaceGoal : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override;
|
||||
};
|
16
dScripts/02_server/Map/AG/CMakeLists.txt
Normal file
16
dScripts/02_server/Map/AG/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_MAP_AG
|
||||
"AgCagedBricksServer.cpp"
|
||||
"NpcWispServer.cpp"
|
||||
"NpcEpsilonServer.cpp"
|
||||
"AgLaserSensorServer.cpp"
|
||||
"AgMonumentLaserServer.cpp"
|
||||
"AgMonumentBirds.cpp"
|
||||
"RemoveRentalGear.cpp"
|
||||
"NpcNjAssistantServer.cpp"
|
||||
"AgBugsprayer.cpp"
|
||||
"NpcAgCourseStarter.cpp"
|
||||
"AgMonumentRaceGoal.cpp"
|
||||
"AgMonumentRaceCancel.cpp"
|
||||
"NpcCowboyServer.cpp"
|
||||
"NpcPirateServer.cpp"
|
||||
PARENT_SCOPE)
|
108
dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp
Normal file
108
dScripts/02_server/Map/AG/NpcAgCourseStarter.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
#include "NpcAgCourseStarter.h"
|
||||
#include "EntityManager.h"
|
||||
#include "ScriptedActivityComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "LeaderboardManager.h"
|
||||
#include "MissionComponent.h"
|
||||
#include <ctime>
|
||||
|
||||
void NpcAgCourseStarter::OnStartup(Entity* self) {
|
||||
|
||||
}
|
||||
|
||||
void NpcAgCourseStarter::OnUse(Entity* self, Entity* user) {
|
||||
auto* scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
|
||||
if (scriptedActivityComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (scriptedActivityComponent->GetActivityPlayerData(user->GetObjectID()) != nullptr) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"exit", 0, 0, LWOOBJID_EMPTY, "", user->GetSystemAddress());
|
||||
} else {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"start", 0, 0, LWOOBJID_EMPTY, "", user->GetSystemAddress());
|
||||
}
|
||||
}
|
||||
|
||||
void NpcAgCourseStarter::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) {
|
||||
auto* scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
|
||||
if (scriptedActivityComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (identifier == u"player_dialog_cancel_course" && button == 1) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"cancel_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID());
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
} else if (identifier == u"player_dialog_start_course" && button == 1) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"start_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
|
||||
GameMessages::SendActivityStart(self->GetObjectID(), sender->GetSystemAddress());
|
||||
|
||||
auto* data = scriptedActivityComponent->AddActivityPlayerData(sender->GetObjectID());
|
||||
|
||||
if (data->values[1] != 0) return;
|
||||
|
||||
time_t startTime = std::time(0) + 4; // Offset for starting timer
|
||||
|
||||
data->values[1] = *(float*)&startTime;
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
} else if (identifier == u"FootRaceCancel") {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_timer", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
|
||||
if (scriptedActivityComponent->GetActivityPlayerData(sender->GetObjectID()) != nullptr) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"exit", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
} else {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"start", 0, 0, LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
}
|
||||
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID());
|
||||
}
|
||||
}
|
||||
|
||||
void NpcAgCourseStarter::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) {
|
||||
auto* scriptedActivityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
if (scriptedActivityComponent == nullptr)
|
||||
return;
|
||||
|
||||
auto* data = scriptedActivityComponent->GetActivityPlayerData(sender->GetObjectID());
|
||||
if (data == nullptr)
|
||||
return;
|
||||
|
||||
if (args == "course_cancel") {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"cancel_timer", 0, 0,
|
||||
LWOOBJID_EMPTY, "", sender->GetSystemAddress());
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID());
|
||||
} else if (args == "course_finish") {
|
||||
time_t endTime = std::time(0);
|
||||
time_t finish = (endTime - *(time_t*)&data->values[1]);
|
||||
|
||||
data->values[2] = *(float*)&finish;
|
||||
|
||||
auto* missionComponent = sender->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) {
|
||||
missionComponent->ForceProgressTaskType(1884, 1, 1, false);
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_MINIGAME, -finish, self->GetObjectID(),
|
||||
"performact_time");
|
||||
}
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
LeaderboardManager::SaveScore(sender->GetObjectID(), scriptedActivityComponent->GetActivityID(),
|
||||
0, (uint32_t)finish);
|
||||
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"ToggleLeaderBoard",
|
||||
scriptedActivityComponent->GetActivityID(), 0, sender->GetObjectID(),
|
||||
"", sender->GetSystemAddress());
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stop_timer", 1, finish, LWOOBJID_EMPTY, "",
|
||||
sender->GetSystemAddress());
|
||||
|
||||
scriptedActivityComponent->RemoveActivityPlayerData(sender->GetObjectID());
|
||||
}
|
||||
}
|
13
dScripts/02_server/Map/AG/NpcAgCourseStarter.h
Normal file
13
dScripts/02_server/Map/AG/NpcAgCourseStarter.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NpcAgCourseStarter : public CppScripts::Script {
|
||||
void OnStartup(Entity* self) override;
|
||||
|
||||
void OnUse(Entity* self, Entity* user) override;
|
||||
|
||||
void OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) override;
|
||||
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) override;
|
||||
};
|
26
dScripts/02_server/Map/AG/NpcCowboyServer.cpp
Normal file
26
dScripts/02_server/Map/AG/NpcCowboyServer.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "NpcCowboyServer.h"
|
||||
#include "MissionState.h"
|
||||
#include "InventoryComponent.h"
|
||||
|
||||
void NpcCowboyServer::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) {
|
||||
if (missionID != 1880) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* inventoryComponent = target->GetComponent<InventoryComponent>();
|
||||
|
||||
if (inventoryComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (missionState == MissionState::MISSION_STATE_COMPLETE_ACTIVE ||
|
||||
missionState == MissionState::MISSION_STATE_ACTIVE ||
|
||||
missionState == MissionState::MISSION_STATE_AVAILABLE ||
|
||||
missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE) {
|
||||
if (inventoryComponent->GetLotCount(14378) == 0) {
|
||||
inventoryComponent->AddItem(14378, 1, eLootSourceType::LOOT_SOURCE_NONE);
|
||||
}
|
||||
} else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) {
|
||||
inventoryComponent->RemoveItem(14378, 1);
|
||||
}
|
||||
}
|
7
dScripts/02_server/Map/AG/NpcCowboyServer.h
Normal file
7
dScripts/02_server/Map/AG/NpcCowboyServer.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NpcCowboyServer : public CppScripts::Script
|
||||
{
|
||||
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) override;
|
||||
};
|
10
dScripts/02_server/Map/AG/NpcEpsilonServer.cpp
Normal file
10
dScripts/02_server/Map/AG/NpcEpsilonServer.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "NpcEpsilonServer.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
void NpcEpsilonServer::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) {
|
||||
|
||||
//If we are completing the Nexus Force join mission, play the celebration for it:
|
||||
if (missionID == 1851) {
|
||||
GameMessages::SendStartCelebrationEffect(target, target->GetSystemAddress(), 22);
|
||||
}
|
||||
}
|
7
dScripts/02_server/Map/AG/NpcEpsilonServer.h
Normal file
7
dScripts/02_server/Map/AG/NpcEpsilonServer.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NpcEpsilonServer : public CppScripts::Script {
|
||||
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState);
|
||||
};
|
||||
|
27
dScripts/02_server/Map/AG/NpcNjAssistantServer.cpp
Normal file
27
dScripts/02_server/Map/AG/NpcNjAssistantServer.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "NpcNjAssistantServer.h"
|
||||
#include "GameMessages.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "Item.h"
|
||||
|
||||
void NpcNjAssistantServer::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) {
|
||||
if (missionID != mailMission) return;
|
||||
|
||||
if (missionState == MissionState::MISSION_STATE_COMPLETE || missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"switch", 0, 0, LWOOBJID_EMPTY, "", target->GetSystemAddress());
|
||||
|
||||
auto* inv = static_cast<InventoryComponent*>(target->GetComponent(COMPONENT_TYPE_INVENTORY));
|
||||
|
||||
// If we are ready to complete our missions, we take the kit from you:
|
||||
if (inv && missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE) {
|
||||
auto* id = inv->FindItemByLot(14397); //the kit's lot
|
||||
|
||||
if (id != nullptr) {
|
||||
inv->RemoveItem(id->GetLot(), id->GetCount());
|
||||
}
|
||||
}
|
||||
} else if (missionState == MissionState::MISSION_STATE_AVAILABLE) {
|
||||
auto* missionComponent = static_cast<MissionComponent*>(target->GetComponent(COMPONENT_TYPE_MISSION));
|
||||
missionComponent->CompleteMission(mailAchievement, true);
|
||||
}
|
||||
}
|
10
dScripts/02_server/Map/AG/NpcNjAssistantServer.h
Normal file
10
dScripts/02_server/Map/AG/NpcNjAssistantServer.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NpcNjAssistantServer : public CppScripts::Script {
|
||||
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState);
|
||||
|
||||
private:
|
||||
int mailMission = 1728; //mission to get the item out of your mailbox
|
||||
int mailAchievement = 1729; // fun fact: spelled "Achivement" in the actual script
|
||||
};
|
17
dScripts/02_server/Map/AG/NpcPirateServer.cpp
Normal file
17
dScripts/02_server/Map/AG/NpcPirateServer.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "NpcPirateServer.h"
|
||||
#include "InventoryComponent.h"
|
||||
|
||||
void NpcPirateServer::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) {
|
||||
auto* inventory = target->GetComponent<InventoryComponent>();
|
||||
if (inventory != nullptr && missionID == 1881) {
|
||||
auto* luckyShovel = inventory->FindItemByLot(14591);
|
||||
|
||||
// Add or remove the lucky shovel based on whether the mission was completed or started
|
||||
if ((missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE)
|
||||
&& luckyShovel == nullptr) {
|
||||
inventory->AddItem(14591, 1, eLootSourceType::LOOT_SOURCE_NONE);
|
||||
} else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) {
|
||||
inventory->RemoveItem(14591, 1);
|
||||
}
|
||||
}
|
||||
}
|
6
dScripts/02_server/Map/AG/NpcPirateServer.h
Normal file
6
dScripts/02_server/Map/AG/NpcPirateServer.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NpcPirateServer : public CppScripts::Script {
|
||||
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) override;
|
||||
};
|
43
dScripts/02_server/Map/AG/NpcWispServer.cpp
Normal file
43
dScripts/02_server/Map/AG/NpcWispServer.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "NpcWispServer.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Entity.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
void NpcWispServer::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) {
|
||||
if (missionID != 1849 && missionID != 1883)
|
||||
return;
|
||||
|
||||
auto* inventory = target->GetComponent<InventoryComponent>();
|
||||
if (inventory == nullptr)
|
||||
return;
|
||||
|
||||
LOT maelstromVacuumLot = 14592;
|
||||
auto* maelstromVacuum = inventory->FindItemByLot(maelstromVacuumLot);
|
||||
|
||||
// For the daily we add the maelstrom vacuum if the player doesn't have it yet
|
||||
if (missionID == 1883 && (missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE)
|
||||
&& maelstromVacuum == nullptr) {
|
||||
inventory->AddItem(maelstromVacuumLot, 1, eLootSourceType::LOOT_SOURCE_NONE);
|
||||
} else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) {
|
||||
inventory->RemoveItem(maelstromVacuumLot, 1);
|
||||
}
|
||||
|
||||
// Next up hide or show the samples based on the mission state
|
||||
auto visible = 1;
|
||||
if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) {
|
||||
visible = 0;
|
||||
}
|
||||
|
||||
auto groups = missionID == 1849
|
||||
? std::vector<std::string> { "MaelstromSamples" }
|
||||
: std::vector<std::string>{ "MaelstromSamples", "MaelstromSamples2ndary1", "MaelstromSamples2ndary2" };
|
||||
|
||||
for (const auto& group : groups) {
|
||||
auto samples = EntityManager::Instance()->GetEntitiesInGroup(group);
|
||||
for (auto* sample : samples) {
|
||||
GameMessages::SendNotifyClientObject(sample->GetObjectID(), u"SetVisibility", visible, 0,
|
||||
target->GetObjectID(), "", target->GetSystemAddress());
|
||||
}
|
||||
}
|
||||
}
|
6
dScripts/02_server/Map/AG/NpcWispServer.h
Normal file
6
dScripts/02_server/Map/AG/NpcWispServer.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NpcWispServer : public CppScripts::Script {
|
||||
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState);
|
||||
};
|
39
dScripts/02_server/Map/AG/RemoveRentalGear.cpp
Normal file
39
dScripts/02_server/Map/AG/RemoveRentalGear.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "RemoveRentalGear.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "Item.h"
|
||||
#include "Character.h"
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------
|
||||
--Removes the rental gear from the player on mission turn in
|
||||
--
|
||||
--created mrb ... 5 / 25 / 11
|
||||
--updated abeechler 6 / 27 / 11 ... Add session flag resetting for set equips
|
||||
--ported Max 21/07/2020
|
||||
--------------------------------------------------------------
|
||||
--add missionID configData to the object in HF to remove this
|
||||
--gear what the specified mission is completed
|
||||
--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void RemoveRentalGear::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) {
|
||||
if (missionID != defaultMission && missionID != 313) return;
|
||||
|
||||
if (missionState == MissionState::MISSION_STATE_COMPLETE || missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE) {
|
||||
auto inv = static_cast<InventoryComponent*>(target->GetComponent(COMPONENT_TYPE_INVENTORY));
|
||||
if (!inv) return;
|
||||
|
||||
//remove the inventory items
|
||||
for (int item : gearSets) {
|
||||
auto* id = inv->FindItemByLot(item);
|
||||
if (id) {
|
||||
inv->UnEquipItem(id);
|
||||
inv->RemoveItem(id->GetLot(), id->GetCount());
|
||||
}
|
||||
}
|
||||
|
||||
//reset the equipment flag
|
||||
auto character = target->GetCharacter();
|
||||
if (character) character->SetPlayerFlag(equipFlag, false);
|
||||
}
|
||||
}
|
12
dScripts/02_server/Map/AG/RemoveRentalGear.h
Normal file
12
dScripts/02_server/Map/AG/RemoveRentalGear.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class RemoveRentalGear : public CppScripts::Script {
|
||||
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState);
|
||||
|
||||
private:
|
||||
int defaultMission = 768; //mission to remove gearSets on completion
|
||||
std::vector<int> gearSets = { 14359,14321,14353,14315 }; //inventory items to remove
|
||||
int equipFlag = 126; //Set upon wearing trial faction armor for the first time in a session
|
||||
};
|
||||
|
4
dScripts/02_server/Map/AG_Spider_Queen/CMakeLists.txt
Normal file
4
dScripts/02_server/Map/AG_Spider_Queen/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
set(DSCRIPTS_SOURCES_02_SERVER_MAP_AG_SPIDER_QUEEN
|
||||
"ZoneAgSpiderQueen.cpp"
|
||||
"SpiderBossTreasureChestServer.cpp"
|
||||
PARENT_SCOPE)
|
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include "MinigameTreasureChestServer.h"
|
||||
|
||||
class SpiderBossTreasureChestServer : public MinigameTreasureChestServer {
|
||||
};
|
83
dScripts/02_server/Map/AG_Spider_Queen/ZoneAgSpiderQueen.cpp
Normal file
83
dScripts/02_server/Map/AG_Spider_Queen/ZoneAgSpiderQueen.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include "ZoneAgSpiderQueen.h"
|
||||
#include "GameMessages.h"
|
||||
#include "EntityManager.h"
|
||||
#include "ZoneAgProperty.h"
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
void ZoneAgSpiderQueen::SetGameVariables(Entity* self) {
|
||||
ZoneAgProperty::SetGameVariables(self);
|
||||
|
||||
// Disable property flags
|
||||
self->SetVar<uint32_t>(defeatedProperyFlag, 0);
|
||||
self->SetVar<uint32_t>(placedModelFlag, 0);
|
||||
self->SetVar<uint32_t>(guardFirstMissionFlag, 0);
|
||||
self->SetVar<uint32_t>(guardMissionFlag, 0);
|
||||
self->SetVar<uint32_t>(brickLinkMissionIDFlag, 0);
|
||||
}
|
||||
|
||||
void ZoneAgSpiderQueen::OnStartup(Entity* self) {
|
||||
LoadInstance(self);
|
||||
|
||||
SpawnSpots(self);
|
||||
StartMaelstrom(self, nullptr);
|
||||
}
|
||||
|
||||
void ZoneAgSpiderQueen::BasePlayerLoaded(Entity* self, Entity* player) {
|
||||
ActivityManager::UpdatePlayer(self, player->GetObjectID());
|
||||
ActivityManager::TakeActivityCost(self, player->GetObjectID());
|
||||
|
||||
// Make sure the player has full stats when they join
|
||||
auto* playerDestroyableComponent = player->GetComponent<DestroyableComponent>();
|
||||
if (playerDestroyableComponent != nullptr) {
|
||||
playerDestroyableComponent->SetImagination(playerDestroyableComponent->GetMaxImagination());
|
||||
playerDestroyableComponent->SetArmor(playerDestroyableComponent->GetMaxArmor());
|
||||
playerDestroyableComponent->SetHealth(playerDestroyableComponent->GetMaxHealth());
|
||||
}
|
||||
|
||||
self->SetNetworkVar(u"unclaimed", true);
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"maelstromSkyOn", 0, 0, LWOOBJID_EMPTY,
|
||||
"", player->GetSystemAddress());
|
||||
}
|
||||
|
||||
void
|
||||
ZoneAgSpiderQueen::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) {
|
||||
if (args == "ClearProperty") {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PlayCinematic", 0, 0,
|
||||
LWOOBJID_EMPTY, destroyedCinematic, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
self->AddTimer("tornadoOff", 0.5f);
|
||||
} else {
|
||||
ZoneAgProperty::BaseOnFireEventServerSide(self, sender, args);
|
||||
}
|
||||
}
|
||||
|
||||
void ZoneAgSpiderQueen::OnPlayerExit(Entity* self, Entity* player) {
|
||||
UpdatePlayer(self, player->GetObjectID(), true);
|
||||
}
|
||||
|
||||
void ZoneAgSpiderQueen::OnTimerDone(Entity* self, std::string timerName) {
|
||||
|
||||
// Disable some stuff from the regular property
|
||||
if (timerName == "BoundsVisOn" || timerName == "GuardFlyAway" || timerName == "ShowVendor")
|
||||
return;
|
||||
|
||||
if (timerName == "killSpider") {
|
||||
auto spawnTargets = EntityManager::Instance()->GetEntitiesInGroup(self->GetVar<std::string>(LandTargetGroup));
|
||||
for (auto* spawnTarget : spawnTargets) {
|
||||
EntityInfo info{};
|
||||
|
||||
info.spawnerID = spawnTarget->GetObjectID();
|
||||
info.pos = spawnTarget->GetPosition();
|
||||
info.rot = spawnTarget->GetRotation();
|
||||
info.lot = chestObject;
|
||||
info.settings = {
|
||||
new LDFData<LWOOBJID>(u"parent_tag", self->GetObjectID())
|
||||
};
|
||||
|
||||
auto* chest = EntityManager::Instance()->CreateEntity(info);
|
||||
EntityManager::Instance()->ConstructEntity(chest);
|
||||
}
|
||||
}
|
||||
|
||||
ZoneAgProperty::BaseTimerDone(self, timerName);
|
||||
}
|
17
dScripts/02_server/Map/AG_Spider_Queen/ZoneAgSpiderQueen.h
Normal file
17
dScripts/02_server/Map/AG_Spider_Queen/ZoneAgSpiderQueen.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "ActivityManager.h"
|
||||
#include "ZoneAgProperty.h"
|
||||
|
||||
class ZoneAgSpiderQueen : ZoneAgProperty, ActivityManager {
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
|
||||
int32_t param3) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
void OnPlayerExit(Entity* self, Entity* player) override;
|
||||
void BasePlayerLoaded(Entity* self, Entity* player) override;
|
||||
void SetGameVariables(Entity* self) override;
|
||||
protected:
|
||||
std::string destroyedCinematic = "DesMaelstromInstance";
|
||||
const LOT chestObject = 16318;
|
||||
};
|
55
dScripts/02_server/Map/AM/AmBlueX.cpp
Normal file
55
dScripts/02_server/Map/AM/AmBlueX.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "AmBlueX.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Character.h"
|
||||
|
||||
void AmBlueX::OnUse(Entity* self, Entity* user) {
|
||||
auto* skillComponent = user->GetComponent<SkillComponent>();
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->CalculateBehavior(m_SwordSkill, m_SwordBehavior, self->GetObjectID());
|
||||
}
|
||||
}
|
||||
|
||||
void AmBlueX::OnSkillEventFired(Entity* self, Entity* caster, const std::string& message) {
|
||||
if (message == "FireDukesStrike") {
|
||||
self->SetNetworkVar<bool>(m_XUsedVariable, true);
|
||||
self->SetNetworkVar<bool>(m_StartEffectVariable, true);
|
||||
|
||||
auto* character = caster->GetCharacter();
|
||||
if (character != nullptr) {
|
||||
character->SetPlayerFlag(self->GetVar<int32_t>(m_FlagVariable), true);
|
||||
}
|
||||
|
||||
EntityInfo info{};
|
||||
info.lot = m_FXObject;
|
||||
info.pos = self->GetPosition();
|
||||
info.rot = self->GetRotation();
|
||||
info.spawnerID = self->GetObjectID();
|
||||
|
||||
auto* fxObject = EntityManager::Instance()->CreateEntity(info, nullptr, self);
|
||||
EntityManager::Instance()->ConstructEntity(fxObject);
|
||||
|
||||
auto fxObjectID = fxObject->GetObjectID();
|
||||
auto playerID = caster->GetObjectID();
|
||||
|
||||
// Add a callback for the bomb to explode
|
||||
self->AddCallbackTimer(m_BombTime, [this, self, fxObjectID, playerID]() {
|
||||
auto* fxObject = EntityManager::Instance()->GetEntity(fxObjectID);
|
||||
auto* player = EntityManager::Instance()->GetEntity(playerID);
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
|
||||
if (skillComponent == nullptr)
|
||||
return;
|
||||
|
||||
// Cast the skill that destroys the object
|
||||
if (player != nullptr) {
|
||||
skillComponent->CalculateBehavior(m_AOESkill, m_AOEBehavior, LWOOBJID_EMPTY, false, false, playerID);
|
||||
} else {
|
||||
skillComponent->CalculateBehavior(m_AOESkill, m_AOEBehavior, LWOOBJID_EMPTY);
|
||||
}
|
||||
|
||||
fxObject->Smash();
|
||||
self->Smash();
|
||||
});
|
||||
}
|
||||
}
|
20
dScripts/02_server/Map/AM/AmBlueX.h
Normal file
20
dScripts/02_server/Map/AM/AmBlueX.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AmBlueX : public CppScripts::Script {
|
||||
void OnUse(Entity* self, Entity* user) override;
|
||||
void OnSkillEventFired(Entity* self, Entity* caster, const std::string& message) override;
|
||||
private:
|
||||
const float_t m_BombTime = 3.3f;
|
||||
const uint32_t m_MissionID = 1448;
|
||||
const uint32_t m_SwordSkill = 1259;
|
||||
const uint32_t m_SwordBehavior = 29305;
|
||||
const uint32_t m_AOESkill = 1258;
|
||||
const uint32_t m_AOEBehavior = 29301;
|
||||
const LOT m_FXObject = 13808;
|
||||
|
||||
// Variables
|
||||
const std::u16string m_XUsedVariable = u"XUsed";
|
||||
const std::u16string m_FlagVariable = u"flag";
|
||||
const std::u16string m_StartEffectVariable = u"startEffect";
|
||||
};
|
28
dScripts/02_server/Map/AM/AmBridge.cpp
Normal file
28
dScripts/02_server/Map/AM/AmBridge.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "AmBridge.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
void AmBridge::OnStartup(Entity* self) {
|
||||
|
||||
}
|
||||
|
||||
void AmBridge::OnRebuildComplete(Entity* self, Entity* target) {
|
||||
const auto consoles = EntityManager::Instance()->GetEntitiesInGroup("Console" + GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"bridge")));
|
||||
|
||||
if (consoles.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* console = consoles[0];
|
||||
|
||||
console->NotifyObject(self, "BridgeBuilt");
|
||||
|
||||
self->AddTimer("SmashBridge", 50);
|
||||
}
|
||||
|
||||
void AmBridge::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName != "SmashBridge") {
|
||||
return;
|
||||
}
|
||||
|
||||
self->Smash(self->GetObjectID(), VIOLENT);
|
||||
}
|
10
dScripts/02_server/Map/AM/AmBridge.h
Normal file
10
dScripts/02_server/Map/AM/AmBridge.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AmBridge : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnRebuildComplete(Entity* self, Entity* target) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
};
|
30
dScripts/02_server/Map/AM/AmConsoleTeleportServer.cpp
Normal file
30
dScripts/02_server/Map/AM/AmConsoleTeleportServer.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "AmConsoleTeleportServer.h"
|
||||
#include "ChooseYourDestinationNsToNt.h"
|
||||
#include "AMFFormat.h"
|
||||
|
||||
void AmConsoleTeleportServer::OnStartup(Entity* self) {
|
||||
self->SetVar(u"teleportAnim", m_TeleportAnim);
|
||||
self->SetVar(u"teleportString", m_TeleportString);
|
||||
self->SetVar(u"teleportEffectID", m_TeleportEffectID);
|
||||
self->SetVar(u"teleportEffectTypes", m_TeleportEffectTypes);
|
||||
}
|
||||
|
||||
void AmConsoleTeleportServer::OnUse(Entity* self, Entity* user) {
|
||||
BaseOnUse(self, user);
|
||||
}
|
||||
|
||||
void AmConsoleTeleportServer::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) {
|
||||
BaseOnMessageBoxResponse(self, sender, button, identifier, userData);
|
||||
}
|
||||
|
||||
void AmConsoleTeleportServer::OnChoiceBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier) {
|
||||
|
||||
}
|
||||
|
||||
void AmConsoleTeleportServer::OnTimerDone(Entity* self, std::string timerName) {
|
||||
BaseOnTimerDone(self, timerName);
|
||||
}
|
||||
|
||||
void AmConsoleTeleportServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) {
|
||||
BaseOnFireEventServerSide(self, sender, args, param1, param2, param3);
|
||||
}
|
22
dScripts/02_server/Map/AM/AmConsoleTeleportServer.h
Normal file
22
dScripts/02_server/Map/AM/AmConsoleTeleportServer.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
#include "BaseConsoleTeleportServer.h"
|
||||
|
||||
class AmConsoleTeleportServer : public CppScripts::Script, BaseConsoleTeleportServer
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnUse(Entity* self, Entity* user) override;
|
||||
void OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) override;
|
||||
void OnChoiceBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override;
|
||||
|
||||
private:
|
||||
int32_t m_ChoiceZoneID = 1900;
|
||||
std::string m_SpawnPoint = "NS_LW";
|
||||
std::u16string m_TeleportAnim = u"nexus-teleport";
|
||||
std::u16string m_TeleportString = u"UI_TRAVEL_TO_NEXUS_TOWER";
|
||||
int32_t m_TeleportEffectID = 6478;
|
||||
std::vector<std::u16string> m_TeleportEffectTypes = { u"teleportRings", u"teleportBeam" };
|
||||
};
|
121
dScripts/02_server/Map/AM/AmDrawBridge.cpp
Normal file
121
dScripts/02_server/Map/AM/AmDrawBridge.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
#include "AmDrawBridge.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
#include "SimplePhysicsComponent.h"
|
||||
|
||||
void AmDrawBridge::OnStartup(Entity* self) {
|
||||
self->SetNetworkVar(u"InUse", false);
|
||||
self->SetVar(u"BridgeDown", false);
|
||||
}
|
||||
|
||||
void AmDrawBridge::OnUse(Entity* self, Entity* user) {
|
||||
auto* bridge = GetBridge(self);
|
||||
|
||||
if (bridge == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->GetNetworkVar<bool>(u"InUse")) {
|
||||
self->SetNetworkVar(u"startEffect", 5);
|
||||
|
||||
self->AddTimer("ChangeBridge", 5);
|
||||
|
||||
self->SetNetworkVar(u"InUse", true);
|
||||
}
|
||||
|
||||
auto* player = user;
|
||||
|
||||
GameMessages::SendTerminateInteraction(player->GetObjectID(), FROM_INTERACTION, self->GetObjectID());
|
||||
}
|
||||
|
||||
void AmDrawBridge::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "ChangeBridge") {
|
||||
auto* bridge = GetBridge(self);
|
||||
|
||||
if (bridge == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->GetVar<bool>(u"BridgeDown")) {
|
||||
self->SetVar(u"BridgeDown", true);
|
||||
|
||||
MoveBridgeDown(self, bridge, true);
|
||||
} else {
|
||||
self->SetVar(u"BridgeDown", false);
|
||||
|
||||
MoveBridgeDown(self, bridge, false);
|
||||
}
|
||||
|
||||
self->SetNetworkVar(u"BridgeLeaving", true);
|
||||
self->SetVar(u"BridgeDown", false);
|
||||
} else if (timerName == "SmashEffectBridge") {
|
||||
self->SetNetworkVar(u"SmashBridge", 5);
|
||||
} else if (timerName == "rotateBridgeDown") {
|
||||
auto* bridge = GetBridge(self);
|
||||
|
||||
if (bridge == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
self->SetNetworkVar(u"BridgeLeaving", false);
|
||||
|
||||
auto* simplePhysicsComponent = bridge->GetComponent<SimplePhysicsComponent>();
|
||||
|
||||
if (simplePhysicsComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
simplePhysicsComponent->SetAngularVelocity(NiPoint3::ZERO);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(bridge);
|
||||
}
|
||||
}
|
||||
|
||||
void AmDrawBridge::OnNotifyObject(Entity* self, Entity* sender, const std::string& name, int32_t param1, int32_t param2) {
|
||||
if (name == "BridgeBuilt") {
|
||||
self->SetVar(u"BridgeID", sender->GetObjectID());
|
||||
|
||||
self->AddTimer("SmashEffectBridge", 45);
|
||||
|
||||
self->SetNetworkVar(u"BridgeDead", true);
|
||||
|
||||
sender->AddDieCallback([this, self, sender]() {
|
||||
NotifyDie(self, sender);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void AmDrawBridge::MoveBridgeDown(Entity* self, Entity* bridge, bool down) {
|
||||
auto* simplePhysicsComponent = bridge->GetComponent<SimplePhysicsComponent>();
|
||||
|
||||
if (simplePhysicsComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto forwardVect = simplePhysicsComponent->GetRotation().GetForwardVector();
|
||||
|
||||
auto degrees = down ? 90.0f : -90.0f;
|
||||
|
||||
const auto travelTime = 2.0f;
|
||||
|
||||
forwardVect = forwardVect * (float)((degrees / travelTime) * (3.14f / 180.0f));
|
||||
|
||||
simplePhysicsComponent->SetAngularVelocity(forwardVect);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(bridge);
|
||||
|
||||
self->AddTimer("rotateBridgeDown", travelTime);
|
||||
}
|
||||
|
||||
void AmDrawBridge::NotifyDie(Entity* self, Entity* other) {
|
||||
self->SetNetworkVar(u"InUse", false);
|
||||
self->SetVar(u"BridgeDown", false);
|
||||
|
||||
self->CancelAllTimers();
|
||||
}
|
||||
|
||||
Entity* AmDrawBridge::GetBridge(Entity* self) {
|
||||
const auto bridgeID = self->GetVar<LWOOBJID>(u"BridgeID");
|
||||
|
||||
return EntityManager::Instance()->GetEntity(bridgeID);
|
||||
}
|
16
dScripts/02_server/Map/AM/AmDrawBridge.h
Normal file
16
dScripts/02_server/Map/AM/AmDrawBridge.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AmDrawBridge : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnUse(Entity* self, Entity* user) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
void OnNotifyObject(Entity* self, Entity* sender, const std::string& name, int32_t param1 = 0, int32_t param2 = 0) override;
|
||||
|
||||
void MoveBridgeDown(Entity* self, Entity* bridge, bool down);
|
||||
void NotifyDie(Entity* self, Entity* other);
|
||||
|
||||
Entity* GetBridge(Entity* self);
|
||||
};
|
81
dScripts/02_server/Map/AM/AmDropshipComputer.cpp
Normal file
81
dScripts/02_server/Map/AM/AmDropshipComputer.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "AmDropshipComputer.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "RebuildComponent.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "dZoneManager.h"
|
||||
|
||||
void AmDropshipComputer::OnStartup(Entity* self) {
|
||||
self->AddTimer("reset", 45.0f);
|
||||
}
|
||||
|
||||
void AmDropshipComputer::OnUse(Entity* self, Entity* user) {
|
||||
auto* rebuildComponent = self->GetComponent<RebuildComponent>();
|
||||
|
||||
if (rebuildComponent == nullptr || rebuildComponent->GetState() != REBUILD_COMPLETED) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* missionComponent = user->GetComponent<MissionComponent>();
|
||||
auto* inventoryComponent = user->GetComponent<InventoryComponent>();
|
||||
|
||||
if (missionComponent == nullptr || inventoryComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (inventoryComponent->GetLotCount(m_NexusTalonDataCard) != 0 || missionComponent->GetMission(979)->GetMissionState() == MissionState::MISSION_STATE_COMPLETE) {
|
||||
return;
|
||||
}
|
||||
|
||||
inventoryComponent->AddItem(m_NexusTalonDataCard, 1, eLootSourceType::LOOT_SOURCE_NONE);
|
||||
}
|
||||
|
||||
void AmDropshipComputer::OnDie(Entity* self, Entity* killer) {
|
||||
const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name"));
|
||||
|
||||
int32_t pipeNum = 0;
|
||||
if (!GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1), pipeNum)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto pipeGroup = myGroup.substr(0, 10);
|
||||
|
||||
const auto nextPipeNum = pipeNum + 1;
|
||||
|
||||
const auto samePipeSpawners = dZoneManager::Instance()->GetSpawnersByName(myGroup);
|
||||
|
||||
if (!samePipeSpawners.empty()) {
|
||||
samePipeSpawners[0]->SoftReset();
|
||||
|
||||
samePipeSpawners[0]->Deactivate();
|
||||
}
|
||||
|
||||
if (killer != nullptr && killer->IsPlayer()) {
|
||||
const auto nextPipe = pipeGroup + std::to_string(nextPipeNum);
|
||||
|
||||
const auto nextPipeSpawners = dZoneManager::Instance()->GetSpawnersByName(nextPipe);
|
||||
|
||||
if (!nextPipeSpawners.empty()) {
|
||||
nextPipeSpawners[0]->Activate();
|
||||
}
|
||||
} else {
|
||||
const auto nextPipe = pipeGroup + "1";
|
||||
|
||||
const auto firstPipeSpawners = dZoneManager::Instance()->GetSpawnersByName(nextPipe);
|
||||
|
||||
if (!firstPipeSpawners.empty()) {
|
||||
firstPipeSpawners[0]->Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AmDropshipComputer::OnTimerDone(Entity* self, std::string timerName) {
|
||||
auto* rebuildComponent = self->GetComponent<RebuildComponent>();
|
||||
|
||||
if (rebuildComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (timerName == "reset" && rebuildComponent->GetState() == REBUILD_OPEN) {
|
||||
self->Smash(self->GetObjectID(), SILENT);
|
||||
}
|
||||
}
|
13
dScripts/02_server/Map/AM/AmDropshipComputer.h
Normal file
13
dScripts/02_server/Map/AM/AmDropshipComputer.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class AmDropshipComputer : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnUse(Entity* self, Entity* user) override;
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
private:
|
||||
const LOT m_NexusTalonDataCard = 12323;
|
||||
};
|
14
dScripts/02_server/Map/AM/AmScrollReaderServer.cpp
Normal file
14
dScripts/02_server/Map/AM/AmScrollReaderServer.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "AmScrollReaderServer.h"
|
||||
#include "MissionComponent.h"
|
||||
|
||||
void AmScrollReaderServer::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) {
|
||||
if (identifier == u"story_end") {
|
||||
auto* missionComponent = sender->GetComponent<MissionComponent>();
|
||||
|
||||
if (missionComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
missionComponent->ForceProgressTaskType(969, 1, 1, false);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user