DarkflameServer/dScripts/02_server/Pets/DamagingPets.cpp

147 lines
4.6 KiB
C++

#include "DamagingPets.h"
#include "PetComponent.h"
#include "DestroyableComponent.h"
#include "BaseCombatAIComponent.h"
#include "RenderComponent.h"
#include "ePetTamingNotifyType.h"
void DamagingPets::OnStartup(Entity* self) {
// Make the pet hostile or non-hostile based on whether or not it is tamed
const auto* petComponent = self->GetComponent<PetComponent>();
if (petComponent != nullptr && petComponent->GetOwner() == nullptr) {
self->AddTimer("GoEvil", 0.5f);
}
}
void DamagingPets::OnPlayerLoaded(Entity* self, Entity* player) {
// Makes it so that new players also see the effect
self->AddCallbackTimer(2.5f, [self]() {
if (self != nullptr) {
const auto* petComponent = self->GetComponent<PetComponent>();
if (petComponent != nullptr && petComponent->GetOwner() == nullptr && self->GetVar<bool>(u"IsEvil")) {
auto* renderComponent = self->GetComponent<RenderComponent>();
if (renderComponent != nullptr) {
auto counter = 1;
for (const auto petEffect : GetPetInfo(self).effect) {
renderComponent->PlayEffect(petEffect, u"create", "FXname" + std::to_string(counter));
counter++;
}
}
}
}
});
}
void DamagingPets::OnNotifyPetTamingMinigame(Entity* self, Entity* tamer, ePetTamingNotifyType type) {
switch (type) {
case ePetTamingNotifyType::SUCCESS:
case ePetTamingNotifyType::BEGIN:
self->CancelAllTimers();
ClearEffects(self);
break;
case ePetTamingNotifyType::FAILED:
case ePetTamingNotifyType::QUIT:
{
self->SetNetworkVar<bool>(u"bIAmTamable", false);
self->AddTimer("GoEvil", 1.0f);
break;
}
default:
break;
}
}
void DamagingPets::OnSkillEventFired(Entity* self, Entity* caster, const std::string& message) {
const auto infoForPet = GetPetInfo(self);
if (infoForPet.skill == message) {
// Only make pets tamable that aren't tamed yet
const auto* petComponent = self->GetComponent<PetComponent>();
if (petComponent != nullptr && petComponent->GetOwner() == nullptr && self->GetVar<bool>(u"IsEvil")) {
ClearEffects(self);
self->AddTimer("GoEvil", 30.0f);
self->SetNetworkVar<bool>(u"bIAmTamable", true);
}
}
}
void DamagingPets::OnTimerDone(Entity* self, std::string message) {
if (message == "GoEvil") {
MakeUntamable(self);
}
}
void DamagingPets::MakeUntamable(Entity* self) {
auto* const petComponent = self->GetComponent<PetComponent>();
// If the pet is currently not being tamed, make it hostile
if (petComponent != nullptr && !petComponent->HasFlag(PetFlag::NOT_WAITING)) {
self->SetNetworkVar<bool>(u"bIAmTamable", false);
self->SetVar<bool>(u"IsEvil", true);
petComponent->SetFlag(PetFlag::IDLE);
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
if (combatAIComponent != nullptr) {
combatAIComponent->SetDisabled(false);
}
// Special faction that can attack the player but the player can't attack
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
if (destroyableComponent != nullptr) {
destroyableComponent->SetFaction(114);
destroyableComponent->SetHealth(5);
}
auto* renderComponent = self->GetComponent<RenderComponent>();
if (renderComponent != nullptr) {
auto counter = 1;
for (const auto petEffect : GetPetInfo(self).effect) {
renderComponent->PlayEffect(petEffect, u"create", "FXname" + std::to_string(counter));
counter++;
}
}
}
}
void DamagingPets::ClearEffects(Entity* self) {
self->SetVar<bool>(u"IsEvil", false);
auto* petComponent = self->GetComponent<PetComponent>();
if (petComponent != nullptr) {
petComponent->SetFlag(PetFlag::TAMEABLE, PetFlag::UNKNOWN2);
}
auto* combatAIComponent = self->GetComponent<BaseCombatAIComponent>();
if (combatAIComponent != nullptr) {
combatAIComponent->SetDisabled(true);
}
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
if (destroyableComponent != nullptr) {
destroyableComponent->SetFaction(99);
}
auto* renderComponent = self->GetComponent<RenderComponent>();
if (renderComponent != nullptr) {
auto counter = 1;
for (const auto petEffect : GetPetInfo(self).effect) {
renderComponent->StopEffect("FXname" + std::to_string(counter));
counter++;
}
}
}
PetInfo DamagingPets::GetPetInfo(Entity* self) {
const auto infoForPet = petInfo.find(self->GetLOT());
return infoForPet != petInfo.end() ? infoForPet->second : petInfo.begin()->second;
}
// Does not compile on Win32 with name specifiers
const std::map<LOT, PetInfo> DamagingPets::petInfo = {
{ 5639, { /*.effect =*/ { 3170, 4058 }, /*.skill =*/ "waterspray"}}, // Red dragon
{ 5641, { /*.effect =*/ { 3170, 4058 }, /*.skill =*/ "waterspray"}}, // Green dragon
{ 3261, { /*.effect =*/ { 1490 }, /*.skill =*/ "waterspray"}}, // Skunk
};