pet bouncer minimum functionality

This commit is contained in:
jadebenn 2023-12-27 19:39:07 -06:00
parent d7d5202c17
commit 6edd42d37c
3 changed files with 159 additions and 117 deletions

View File

@ -76,7 +76,7 @@ std::map<LOT, int32_t> PetComponent::petFlags = {
{ 13067, 838 }, // Skeleton dragon { 13067, 838 }, // Skeleton dragon
}; };
PetComponent::PetComponent(Entity* parent, uint32_t componentId): Component(parent) { PetComponent::PetComponent(Entity* parent, uint32_t componentId) : Component(parent) {
m_ComponentId = componentId; m_ComponentId = componentId;
m_Interaction = LWOOBJID_EMPTY; m_Interaction = LWOOBJID_EMPTY;
@ -104,30 +104,18 @@ PetComponent::PetComponent(Entity* parent, uint32_t componentId): Component(pare
if (!checkPreconditions.empty()) { if (!checkPreconditions.empty()) {
SetPreconditions(checkPreconditions); SetPreconditions(checkPreconditions);
} }
// Load database values // Load database values
m_FollowRadius = Game::zoneManager->GetPetFollowRadius(); m_FollowRadius = Game::zoneManager->GetPetFollowRadius();
} }
bool PetComponent::LoadPetInfo(uint32_t petId, CDPetComponent& result) {
CDPetComponentTable* petTable;
petTable = CDClientManager::Instance().GetTable<CDPetComponentTable>();
const auto pet = petTable->GetByID(petId);
if (!pet) return false;
result = pet[0];
return true;
}
void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
const bool tamed = m_Owner != LWOOBJID_EMPTY; const bool tamed = m_Owner != LWOOBJID_EMPTY;
outBitStream->Write1(); // Always serialize as dirty for now outBitStream->Write1(); // Always serialize as dirty for now
outBitStream->Write<uint32_t>(static_cast<unsigned int>(m_Flags)); outBitStream->Write<uint32_t>(static_cast<unsigned int>(m_Flags));
outBitStream->Write<uint32_t>(static_cast<uint32_t>(tamed ? m_Ability : ePetAbilityType::Invalid)); // Something with the overhead icon? outBitStream->Write(tamed ? m_Ability : ePetAbilityType::Invalid); // Something with the overhead icon?
const bool interacting = m_Interaction != LWOOBJID_EMPTY; const bool interacting = m_Interaction != LWOOBJID_EMPTY;
@ -172,15 +160,15 @@ void PetComponent::OnUse(Entity* originator) {
if (IsReadyToInteract()) { if (IsReadyToInteract()) {
switch (GetAbility()) { switch (GetAbility()) {
case ePetAbilityType::DigAtPosition: // Treasure dig TODO: FIX ICON case ePetAbilityType::DigAtPosition: // Treasure dig TODO: FIX ICON
StartInteractTreasureDig(); StartInteractTreasureDig();
break;
case ePetAbilityType::JumpOnObject: // Bouncer
//StartInteractBouncer();
break; break;
default: case ePetAbilityType::JumpOnObject: // Bouncer
StartInteractBouncer();
break;
default:
break; break;
} }
} }
@ -350,12 +338,6 @@ void PetComponent::OnUse(Entity* originator) {
} }
void PetComponent::Update(float deltaTime) { void PetComponent::Update(float deltaTime) {
// If pet does not have an owner, use the UpdateUnowned() loop
/*if (m_Owner == LWOOBJID_EMPTY) {
UpdateUnowned(deltaTime);
return;
}*/
// Update timers // Update timers
m_TimerBounce -= deltaTime; m_TimerBounce -= deltaTime;
@ -392,14 +374,13 @@ void PetComponent::Update(float deltaTime) {
case PetAiState::follow: case PetAiState::follow:
OnFollow(deltaTime); OnFollow(deltaTime);
break; break;
case PetAiState::goToObj: case PetAiState::goToObj:
if (m_MovementAI->AtFinalWaypoint()) { if (m_MovementAI->AtFinalWaypoint()) {
LOG_DEBUG("Reached object!"); LOG_DEBUG("Reached object!");
m_MovementAI->Stop(); m_MovementAI->Stop();
SetPetAiState(PetAiState::interact); SetPetAiState(PetAiState::interact);
} } else {
else {
m_Timer += 0.5f; m_Timer += 0.5f;
} }
break; break;
@ -412,24 +393,6 @@ void PetComponent::Update(float deltaTime) {
LOG_DEBUG("Unknown state: %d!", m_Flags); LOG_DEBUG("Unknown state: %d!", m_Flags);
break; break;
} }
/*
SwitchComponent* closestSwitch = SwitchComponent::GetClosestSwitch(position);
float haltDistance = 5;
if (closestSwitch != nullptr && !closestSwitch->GetActive()) {
NiPoint3 switchPosition = closestSwitch->GetParentEntity()->GetPosition();
float distance = Vector3::DistanceSquared(position, switchPosition);
if (distance < 3 * 3) {
m_Interaction = closestSwitch->GetParentEntity()->GetObjectID();
closestSwitch->EntityEnter(m_Parent);
} else if (distance < 20 * 20) {
haltDistance = 1;
destination = switchPosition;
}
}
*/
} }
void PetComponent::UpdateUnowned(float deltaTime) { //TODO: CURRENTLY UNUSED void PetComponent::UpdateUnowned(float deltaTime) { //TODO: CURRENTLY UNUSED
@ -443,8 +406,7 @@ void PetComponent::UpdateUnowned(float deltaTime) { //TODO: CURRENTLY UNUSED
ClientFailTamingMinigame(); ClientFailTamingMinigame();
} }
} }
} } else {
else {
if (m_Timer > 0) { if (m_Timer > 0) {
m_Timer -= deltaTime; m_Timer -= deltaTime;
@ -551,7 +513,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
GameMessages::SendRegisterPetDBID(m_Tamer, petSubKey, tamer->GetSystemAddress()); GameMessages::SendRegisterPetDBID(m_Tamer, petSubKey, tamer->GetSystemAddress());
inventoryComponent->AddItem(m_Parent->GetLOT(), 1, eLootSourceType::ACTIVITY, eInventoryType::MODELS, {}, LWOOBJID_EMPTY, true, false, petSubKey); inventoryComponent->AddItem(m_Parent->GetLOT(), 1, eLootSourceType::ACTIVITY, eInventoryType::MODELS, {}, LWOOBJID_EMPTY, true, false, petSubKey);
auto* item = inventoryComponent->FindItemBySubKey(petSubKey, MODELS); auto* item = inventoryComponent->FindItemBySubKey(petSubKey, MODELS);
if (!item) return; if (!item) return;
@ -798,35 +760,34 @@ void PetComponent::Wander() {
return; return;
} }
m_MovementAI->SetMaxSpeed(m_PetInfo.sprintSpeed); //info.wanderSpeed); m_MovementAI->SetMaxSpeed(m_PetInfo->sprintSpeed); //info.wanderSpeed);
m_MovementAI->SetDestination(destination); m_MovementAI->SetDestination(destination);
m_Timer += (m_MovementAI->GetParent()->GetPosition().x - destination.x) / m_PetInfo.sprintSpeed; m_Timer += (m_MovementAI->GetParent()->GetPosition().x - destination.x) / m_PetInfo->sprintSpeed;
} }
void PetComponent::OnSpawn() { void PetComponent::OnSpawn() {
if (!LoadPetInfo(m_ComponentId, m_PetInfo)) { m_PetInfo = CDClientManager::Instance().GetTable<CDPetComponentTable>()->GetByID(m_ComponentId);
LOG("Failed to load PetComponent (id: %d) information from CDClient!", m_ComponentId); if (!m_PetInfo) LOG("Failed to load PetComponent (id: %d) information from CDClient!", m_ComponentId);
}
m_MovementAI = m_Parent->GetComponent<MovementAIComponent>(); m_MovementAI = m_Parent->GetComponent<MovementAIComponent>();
if (m_StartPosition == NiPoint3::ZERO) { if (m_StartPosition == NiPoint3::ZERO) {
m_StartPosition = m_Parent->GetPosition(); m_StartPosition = m_Parent->GetPosition();
} }
if (m_Owner != LWOOBJID_EMPTY) { if (m_Owner != LWOOBJID_EMPTY) {
m_Parent->SetOwnerOverride(m_Owner); m_Parent->SetOwnerOverride(m_Owner);
m_MovementAI->SetMaxSpeed(m_PetInfo.sprintSpeed); m_MovementAI->SetMaxSpeed(m_PetInfo->sprintSpeed);
m_MovementAI->SetHaltDistance(m_FollowRadius); m_MovementAI->SetHaltDistance(m_FollowRadius);
//SetOnlyFlag(IDLE); //SetStatus(PetFlag::NONE); //SetOnlyFlag(IDLE); //SetStatus(PetFlag::NONE);
SetPetAiState(PetAiState::follow); SetPetAiState(PetAiState::follow);
} } else {
else {
SetFlag(TAMEABLE); SetFlag(TAMEABLE);
SetPetAiState(PetAiState::idle); SetPetAiState(PetAiState::idle);
} }
SetFlag(IDLE); SetFlag(IDLE);
UnsetFlag(SPAWNING); UnsetFlag(SPAWNING);
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
@ -873,8 +834,7 @@ void PetComponent::OnFollow(const float& deltaTime) {
// If the player's position is within range, stop moving // If the player's position is within range, stop moving
if (distanceToOwner <= m_FollowRadius * m_FollowRadius) { if (distanceToOwner <= m_FollowRadius * m_FollowRadius) {
m_MovementAI->Stop(); m_MovementAI->Stop();
} } else { // Chase the player's new position
else { // Chase the player's new position
m_MovementAI->SetDestination(ownerPos); m_MovementAI->SetDestination(ownerPos);
} }
@ -886,8 +846,7 @@ void PetComponent::OnFollow(const float& deltaTime) {
m_TimerAway = 0; m_TimerAway = 0;
return; return;
} } else if (distanceToOwner > 15 * 15 || std::abs(ownerPos.y - currentPos.y) >= 3) {
else if (distanceToOwner > 15 * 15 || std::abs(ownerPos.y - currentPos.y) >= 3) {
m_TimerAway += deltaTime; m_TimerAway += deltaTime;
} }
@ -909,17 +868,17 @@ void PetComponent::OnInteract() {
} }
switch (GetInteractType()) { switch (GetInteractType()) {
case PetInteractType::bouncer: case PetInteractType::bouncer:
if (IsReadyToInteract()) LOG_DEBUG("Add the HandleInteractBouncer()!"); if (IsReadyToInteract()) HandleInteractBouncer();
else SetupInteractBouncer(); else SetupInteractBouncer();
break; break;
case PetInteractType::treasure: case PetInteractType::treasure:
if (IsReadyToInteract()) HandleInteractTreasureDig(); if (IsReadyToInteract()) HandleInteractTreasureDig();
else SetupInteractTreasureDig(); else SetupInteractTreasureDig();
break; break;
default: default:
LOG_DEBUG("INTERACT = NONE! RETURNING!"); LOG_DEBUG("INTERACT = NONE! RETURNING!");
StopInteract(); StopInteract();
m_Timer += 0.5f; m_Timer += 0.5f;
@ -932,7 +891,7 @@ void PetComponent::StartInteract(const NiPoint3 position, const PetInteractType
SetInteractType(interactType); SetInteractType(interactType);
SetAbility(ePetAbilityType::GoToObject); SetAbility(ePetAbilityType::GoToObject);
SetPetAiState(PetAiState::goToObj); SetPetAiState(PetAiState::goToObj);
m_MovementAI->SetMaxSpeed(m_PetInfo.runSpeed); m_MovementAI->SetMaxSpeed(m_PetInfo->runSpeed);
m_MovementAI->SetHaltDistance(0.0f); m_MovementAI->SetHaltDistance(0.0f);
m_MovementAI->SetDestination(position); m_MovementAI->SetDestination(position);
LOG_DEBUG("Starting interaction!"); LOG_DEBUG("Starting interaction!");
@ -952,7 +911,7 @@ void PetComponent::StopInteract(bool bDontSerialize) {
SetOnlyFlag(IDLE); //SetStatus(PetFlag::NONE); SetOnlyFlag(IDLE); //SetStatus(PetFlag::NONE);
SetIsReadyToInteract(false); SetIsReadyToInteract(false);
SetIsHandlingInteraction(false); // Needed? SetIsHandlingInteraction(false); // Needed?
m_MovementAI->SetMaxSpeed(m_PetInfo.sprintSpeed); m_MovementAI->SetMaxSpeed(m_PetInfo->sprintSpeed);
m_MovementAI->SetHaltDistance(m_FollowRadius); m_MovementAI->SetHaltDistance(m_FollowRadius);
LOG_DEBUG("Stopping interaction!"); LOG_DEBUG("Stopping interaction!");
@ -964,44 +923,38 @@ void PetComponent::StopInteract(bool bDontSerialize) {
} }
void PetComponent::SetupInteractBouncer() { void PetComponent::SetupInteractBouncer() {
// THIS IS ALL BAD, BAD, BAD! FIX IT, ME! >:( const auto* owner = GetOwner();
/*SetAbility(ePetAbilityType::JumpOnObject);
NiPoint3 destination = m_MovementAI->GetDestination();
SwitchComponent* closestSwitch = SwitchComponent::GetClosestSwitch(destination);
m_Interaction = closestSwitch->GetParentEntity()->GetObjectID();
Game::entityManager->SerializeEntity(m_Parent);
closestSwitch->EntityEnter(m_Parent);*/
}
void PetComponent::SetupInteractTreasureDig() {
auto* owner = GetOwner();
if (!owner) return; if (!owner) return;
LOG_DEBUG("Setting up dig interaction!"); LOG_DEBUG("Setting up bouncer interaction!");
SetIsReadyToInteract(true); SetIsReadyToInteract(true);
auto petAbility = ePetAbilityType::DigAtPosition; const auto petAbility = ePetAbilityType::JumpOnObject;
SetAbility(petAbility); SetAbility(petAbility);
UnsetFlag(IDLE); UnsetFlag(IDLE);
SetFlag(UNKNOWN256, NOT_WAITING); //SetStatus(PetFlag::NOT_WAITING); // TODO: Double-check this is the right flag being set SetFlag(ON_SWITCH, NOT_WAITING); //SetStatus(PetFlag::NOT_WAITING); // TODO: Double-check this is the right flag being set
LOG_DEBUG("m_Flags = %d", m_Flags); LOG_DEBUG("m_Flags = %d", m_Flags);
Game::entityManager->SerializeEntity(m_Parent); // TODO: Double-check pet packet captures Game::entityManager->SerializeEntity(m_Parent); // TODO: Double-check pet packet captures
const auto sysAddr = owner->GetSystemAddress(); const auto sysAddr = owner->GetSystemAddress();
GameMessages::SendHelp(m_Owner, eHelpType::PR_DIG_TUTORIAL_01, sysAddr); GameMessages::SendHelp(m_Owner, eHelpType::PR_BOUNCER_TUTORIAL_03, sysAddr);
GameMessages::SendShowPetActionButton(m_Owner, petAbility, true, sysAddr); GameMessages::SendShowPetActionButton(m_Owner, petAbility, true, sysAddr);
SwitchComponent* closestSwitch = SwitchComponent::GetClosestSwitch(m_MovementAI->GetDestination()); // TODO: Find a better way to do this
closestSwitch->EntityEnter(m_Parent);
m_Timer += 0.5f; m_Timer += 0.5f;
} }
void PetComponent::StartInteractTreasureDig() { void PetComponent::StartInteractBouncer() {
Entity* user = GetOwner(); Entity* user = GetOwner();
if (IsHandlingInteraction() || !user) return; if (IsHandlingInteraction() || !user) return;
auto* destroyableComponent = user->GetComponent<DestroyableComponent>(); auto* destroyableComponent = user->GetComponent<DestroyableComponent>();
if (!destroyableComponent) return; if (!destroyableComponent) return;
auto imagination = destroyableComponent->GetImagination(); auto imagination = destroyableComponent->GetImagination();
int32_t imaginationCost = 1; // TODO: Get rid of this magic number - make static variable from lookup const int32_t imaginationCost = 2; // TODO: Get rid of this magic number - make static variable from lookup
if (imagination < imaginationCost) { if (imagination < imaginationCost) {
//GameMessages::SendHelp(user->GetObjectID(), eHelpType::PR_NEED_IMAGINATION, user->GetSystemAddress()); // Check if right message! //GameMessages::SendHelp(user->GetObjectID(), eHelpType::PR_NEED_IMAGINATION, user->GetSystemAddress()); // Check if right message!
return; return;
@ -1009,12 +962,93 @@ void PetComponent::StartInteractTreasureDig() {
GameMessages::SendShowPetActionButton(m_Owner, ePetAbilityType::Invalid, false, user->GetSystemAddress()); GameMessages::SendShowPetActionButton(m_Owner, ePetAbilityType::Invalid, false, user->GetSystemAddress());
imagination -= imaginationCost; imagination -= imaginationCost;
destroyableComponent->SetImagination(imagination);
Game::entityManager->SerializeEntity(user);
// THIS IS ALL BAD, BAD, BAD! FIX IT, ME! >:(
SetIsHandlingInteraction(true);
SwitchComponent* closestSwitch = SwitchComponent::GetClosestSwitch(m_MovementAI->GetDestination()); // TODO: Find a better way to do this
closestSwitch->EntityEnter(m_Parent);
//m_Timer += 0.5;
}
void PetComponent::HandleInteractBouncer() {
if (IsHandlingInteraction()) {
auto* const owner = GetOwner();
if (!owner) return;
auto* const petSwitch = SwitchComponent::GetClosestSwitch(m_MovementAI->GetDestination()); // TODO: Find a better way to do this
if (!petSwitch) return;
auto* const petSwitchEntity = petSwitch->GetParentEntity();
if (!petSwitchEntity) return;
m_Parent->AddCallbackTimer(2.0f, [petSwitch, petSwitchEntity]() {
LOG_DEBUG("Callback start!");
petSwitch->GetPetBouncer()->SetPetBouncerEnabled(false);
RenderComponent::PlayAnimation(petSwitchEntity, u"up");
LOG_DEBUG("Callback end!");
});
RenderComponent::PlayAnimation(petSwitchEntity, u"launch"); //u"engaged");
auto* const petBouncer = petSwitch->GetPetBouncer();
petBouncer->SetPetBouncerEnabled(true);
Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 1, PetEmote::ActivateSwitch, true); // Plays 'jump on switch' animation
StopInteract();
}
m_Timer += 0.5f;
}
void PetComponent::SetupInteractTreasureDig() {
const auto* owner = GetOwner();
if (!owner) return;
LOG_DEBUG("Setting up dig interaction!");
SetIsReadyToInteract(true);
const auto petAbility = ePetAbilityType::DigAtPosition;
SetAbility(petAbility);
UnsetFlag(IDLE);
SetFlag(ON_SWITCH, NOT_WAITING); //SetStatus(PetFlag::NOT_WAITING); // TODO: Double-check this is the right flag being set
LOG_DEBUG("m_Flags = %d", m_Flags);
Game::entityManager->SerializeEntity(m_Parent); // TODO: Double-check pet packet captures
const auto sysAddr = owner->GetSystemAddress();
GameMessages::SendHelp(m_Owner, eHelpType::PR_DIG_TUTORIAL_01, sysAddr);
GameMessages::SendShowPetActionButton(m_Owner, petAbility, true, sysAddr);
m_Timer += 0.5f;
}
void PetComponent::StartInteractTreasureDig() {
Entity* user = GetOwner();
if (IsHandlingInteraction() || !user) return;
auto* destroyableComponent = user->GetComponent<DestroyableComponent>();
if (!destroyableComponent) return;
auto imagination = destroyableComponent->GetImagination();
const int32_t imaginationCost = 1; // TODO: Get rid of this magic number - make static variable from lookup
if (imagination < imaginationCost) {
//GameMessages::SendHelp(user->GetObjectID(), eHelpType::PR_NEED_IMAGINATION, user->GetSystemAddress()); // Check if right message!
return;
}
GameMessages::SendShowPetActionButton(m_Owner, ePetAbilityType::Invalid, false, user->GetSystemAddress());
imagination -= imaginationCost;
destroyableComponent->SetImagination(imagination); destroyableComponent->SetImagination(imagination);
Game::entityManager->SerializeEntity(user); Game::entityManager->SerializeEntity(user);
SetIsHandlingInteraction(true); SetIsHandlingInteraction(true);
UnsetFlag(UNKNOWN256, NOT_WAITING); // TODO: FIND THE CORRECT STATUS TO USE HERE UnsetFlag(ON_SWITCH, NOT_WAITING); // TODO: FIND THE CORRECT STATUS TO USE HERE
SetFlag(IDLE); SetFlag(IDLE);
LOG_DEBUG("StartInteractTreasureDig() m_Flags = %d", m_Flags); LOG_DEBUG("StartInteractTreasureDig() m_Flags = %d", m_Flags);
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
@ -1025,10 +1059,10 @@ void PetComponent::StartInteractTreasureDig() {
void PetComponent::HandleInteractTreasureDig() { void PetComponent::HandleInteractTreasureDig() {
if (IsHandlingInteraction()) { if (IsHandlingInteraction()) {
auto* owner = GetOwner(); auto* const owner = GetOwner();
if (!owner) return; if (!owner) return;
auto* treasure = PetDigServer::GetClosestTresure(m_MovementAI->GetDestination()); // TODO: Find a better way to do this auto* const treasure = PetDigServer::GetClosestTresure(m_MovementAI->GetDestination()); // TODO: Find a better way to do this
treasure->Smash(m_Parent->GetObjectID()); treasure->Smash(m_Parent->GetObjectID());
GameMessages::SendHelp(m_Owner, eHelpType::PR_DIG_TUTORIAL_03, owner->GetSystemAddress()); GameMessages::SendHelp(m_Owner, eHelpType::PR_DIG_TUTORIAL_03, owner->GetSystemAddress());
@ -1038,7 +1072,7 @@ void PetComponent::HandleInteractTreasureDig() {
return; return;
} }
if (m_TimerBounce <= 0.0f) { if (m_TimerBounce <= 0.0f) {
Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 1, PetEmote::Bounce, true); // Plays 'bounce' animation Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 1, PetEmote::Bounce, true); // Plays 'bounce' animation
m_TimerBounce = 1.0f; m_TimerBounce = 1.0f;
@ -1048,6 +1082,9 @@ void PetComponent::HandleInteractTreasureDig() {
} }
void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) { // TODO: Offset spawn position so it's not on top of player char void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) { // TODO: Offset spawn position so it's not on top of player char
m_PetInfo = CDClientManager::Instance().GetTable<CDPetComponentTable>()->GetByID(m_ComponentId);
if (!m_PetInfo) LOG("Failed to load PetComponent (id: %d) information from CDClient!", m_ComponentId);
AddDrainImaginationTimer(item, fromTaming); AddDrainImaginationTimer(item, fromTaming);
m_ItemId = item->GetId(); m_ItemId = item->GetId();
@ -1129,22 +1166,22 @@ void PetComponent::AddDrainImaginationTimer(Item* item, bool fromTaming) {
if (!fromTaming) playerDestroyableComponent->Imagine(-1); if (!fromTaming) playerDestroyableComponent->Imagine(-1);
// Set this to a variable so when this is called back from the player the timer doesn't fire off. // Set this to a variable so when this is called back from the player the timer doesn't fire off.
m_Parent->AddCallbackTimer(m_PetInfo.imaginationDrainRate, [playerDestroyableComponent, this, item]() { m_Parent->AddCallbackTimer(m_PetInfo->imaginationDrainRate, [playerDestroyableComponent, this, item]() {
if (!playerDestroyableComponent) { if (!playerDestroyableComponent) {
LOG("No petComponent and/or no playerDestroyableComponent"); LOG("No petComponent and/or no playerDestroyableComponent");
return; return;
} }
// If we are out of imagination despawn the pet. // If we are out of imagination despawn the pet.
if (playerDestroyableComponent->GetImagination() == 0) { if (playerDestroyableComponent->GetImagination() == 0) {
this->Deactivate(); this->Deactivate();
auto playerEntity = playerDestroyableComponent->GetParent(); auto playerEntity = playerDestroyableComponent->GetParent();
if (!playerEntity) return; if (!playerEntity) return;
GameMessages::SendUseItemRequirementsResponse(playerEntity->GetObjectID(), playerEntity->GetSystemAddress(), eUseItemResponse::NoImaginationForPet); GameMessages::SendUseItemRequirementsResponse(playerEntity->GetObjectID(), playerEntity->GetSystemAddress(), eUseItemResponse::NoImaginationForPet);
} }
this->AddDrainImaginationTimer(item); this->AddDrainImaginationTimer(item);
}); });
} }
@ -1303,7 +1340,7 @@ void PetComponent::SetPetNameForModeration(const std::string& petName) {
} }
//Save to db: //Save to db:
Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{petName, approved}); Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{ petName, approved });
} }
void PetComponent::LoadPetNameFromModeration() { void PetComponent::LoadPetNameFromModeration() {

View File

@ -39,9 +39,9 @@ enum PetFlag : uint32_t {
UNKNOWN4 = 1 << 2, //0x04 - FOLLOWING(?) UNKNOWN4 = 1 << 2, //0x04 - FOLLOWING(?)
BEING_TAMED = 1 << 4, //0x10, BEING_TAMED = 1 << 4, //0x10,
NOT_WAITING = 1 << 5, //0x20, NOT_WAITING = 1 << 5, //0x20,
STOP_MOVING = 1 << 6, //0x40 - Seems to be the "stop moving" flag - called when taming begins and stays active until a name is submitted IMMOBILE = 1 << 6, //0x40 - Seems to be the "stop moving" flag - called when taming begins and stays active until a name is submitted
SPAWNING = 1 << 7, //0x80 SPAWNING = 1 << 7, //0x80
UNKNOWN256 = 1 << 8, //0x100 ON_SWITCH = 1 << 8, //0x100
UNKNOWN1024 = 1 << 10, //0x400 UNKNOWN1024 = 1 << 10, //0x400
TAMEABLE = 1 << 26 //0x4000000 TAMEABLE = 1 << 26 //0x4000000
}; };
@ -69,11 +69,6 @@ public:
PetComponent(Entity* parentEntity, uint32_t componentId); PetComponent(Entity* parentEntity, uint32_t componentId);
~PetComponent() override; ~PetComponent() override;
/**
* Loads pet info from CDClient
*/
bool LoadPetInfo(uint32_t petId, CDPetComponent& result);
/** /**
* Serializes the pet * Serializes the pet
@ -346,6 +341,16 @@ public:
*/ */
void SetupInteractBouncer(); void SetupInteractBouncer();
/**
* Starts the pet bouncer interaction
*/
void StartInteractBouncer();
/**
* Handles the pet bouncer interaction
*/
void HandleInteractBouncer();
/** /**
* Set up the treasure dig interaction * Set up the treasure dig interaction
*/ */
@ -437,7 +442,7 @@ private:
/** /**
* Pet information loaded from the CDClientDatabase * Pet information loaded from the CDClientDatabase
*/ */
CDPetComponent m_PetInfo; CDPetComponent* m_PetInfo;
/** /**
* Cache of all the pets that are currently spawned, indexed by tamer * Cache of all the pets that are currently spawned, indexed by tamer

View File

@ -60,8 +60,8 @@ void SwitchComponent::EntityEnter(Entity* entity) {
if (m_PetBouncer != nullptr) { if (m_PetBouncer != nullptr) {
GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 2602, u"pettriggeractive", "BounceEffect", LWOOBJID_EMPTY, 1, 1, true); GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 2602, u"pettriggeractive", "BounceEffect", LWOOBJID_EMPTY, 1, 1, true);
RenderComponent::PlayAnimation(m_Parent, u"engaged"); //RenderComponent::PlayAnimation(m_Parent, u"engaged");
m_PetBouncer->SetPetBouncerEnabled(true); //m_PetBouncer->SetPetBouncerEnabled(true);
} else { } else {
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
} }