#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(); 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(); if (petComponent != nullptr && petComponent->GetOwner() == nullptr && self->GetVar(u"IsEvil")) { auto* renderComponent = self->GetComponent(); 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(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(); if (petComponent != nullptr && petComponent->GetOwner() == nullptr && self->GetVar(u"IsEvil")) { ClearEffects(self); self->AddTimer("GoEvil", 30.0f); self->SetNetworkVar(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(); // If the pet is currently not being tamed, make it hostile if (petComponent != nullptr && !petComponent->HasFlag(PetFlag::NOT_WAITING)) { self->SetNetworkVar(u"bIAmTamable", false); self->SetVar(u"IsEvil", true); petComponent->SetFlag(PetFlag::IDLE); auto* combatAIComponent = self->GetComponent(); if (combatAIComponent != nullptr) { combatAIComponent->SetDisabled(false); } // Special faction that can attack the player but the player can't attack auto* destroyableComponent = self->GetComponent(); if (destroyableComponent != nullptr) { destroyableComponent->SetFaction(114); destroyableComponent->SetHealth(5); } auto* renderComponent = self->GetComponent(); 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(u"IsEvil", false); auto* petComponent = self->GetComponent(); if (petComponent != nullptr) { petComponent->SetFlag(PetFlag::TAMEABLE, PetFlag::UNKNOWN2); } auto* combatAIComponent = self->GetComponent(); if (combatAIComponent != nullptr) { combatAIComponent->SetDisabled(true); } auto* destroyableComponent = self->GetComponent(); if (destroyableComponent != nullptr) { destroyableComponent->SetFaction(99); } auto* renderComponent = self->GetComponent(); 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 DamagingPets::petInfo = { { 5639, { /*.effect =*/ { 3170, 4058 }, /*.skill =*/ "waterspray"}}, // Red dragon { 5641, { /*.effect =*/ { 3170, 4058 }, /*.skill =*/ "waterspray"}}, // Green dragon { 3261, { /*.effect =*/ { 1490 }, /*.skill =*/ "waterspray"}}, // Skunk };