pet following and flag behavior improvements

This commit is contained in:
jadebenn 2023-12-16 20:51:06 -06:00
parent b8449a167d
commit 2d3e03a2a8
2 changed files with 42 additions and 44 deletions

View File

@ -339,7 +339,7 @@ void PetComponent::OnUse(Entity* originator) {
GameMessages::SendNotifyPetTamingPuzzleSelected(originator->GetObjectID(), bricks, originator->GetSystemAddress()); GameMessages::SendNotifyPetTamingPuzzleSelected(originator->GetObjectID(), bricks, originator->GetSystemAddress());
m_Tamer = originator->GetObjectID(); m_Tamer = originator->GetObjectID();
SetFlag(UNKNOWN1, UNKNOWN4); //SetStatus(5); SetFlag(IDLE, UNKNOWN4); //SetStatus(5);
currentActivities.insert_or_assign(m_Tamer, m_Parent->GetObjectID()); currentActivities.insert_or_assign(m_Tamer, m_Parent->GetObjectID());
@ -386,15 +386,15 @@ void PetComponent::Update(float deltaTime) {
LOG_DEBUG("Has NOT_WAITING flag!"); LOG_DEBUG("Has NOT_WAITING flag!");
break; break;
case UNKNOWN1: case IDLE:
LOG_DEBUG("Has UNKNOWN1 flag!"); LOG_DEBUG("Has IDLE flag!");
break; break;
default: default:
LOG_DEBUG("Triggered default case!"); LOG_DEBUG("Triggered default case!");
}*/ }*/
//if (HasFlag(SPAWNING)) OnSpawn(); if (HasFlag(SPAWNING)) OnSpawn();
// Handle pet AI states // Handle pet AI states
switch (m_State) { switch (m_State) {
@ -403,7 +403,7 @@ void PetComponent::Update(float deltaTime) {
break; break;
case PetAiState::follow: case PetAiState::follow:
OnFollow(); OnFollow(deltaTime);
break; break;
case PetAiState::goToObj: case PetAiState::goToObj:
@ -427,30 +427,6 @@ void PetComponent::Update(float deltaTime) {
} }
/* /*
auto destination = owner->GetPosition();
NiPoint3 position = m_MovementAI->GetParent()->GetPosition();
float distanceToOwner = Vector3::DistanceSquared(position, destination);
if (distanceToOwner > 50 * 50 || m_TimerAway > 5) {
m_MovementAI->Warp(destination);
m_Timer = 1;
m_TimerAway = 0;
return;
}
if (distanceToOwner > 15 * 15 || std::abs(destination.y - position.y) >= 3) {
m_TimerAway += deltaTime;
} else {
m_TimerAway = 0;
}
if (m_Timer > 0) {
m_Timer -= deltaTime;
return;
}
SwitchComponent* closestSwitch = SwitchComponent::GetClosestSwitch(position); SwitchComponent* closestSwitch = SwitchComponent::GetClosestSwitch(position);
float haltDistance = 5; float haltDistance = 5;
@ -627,7 +603,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
missionComponent->Progress(eMissionTaskType::PET_TAMING, m_Parent->GetLOT()); missionComponent->Progress(eMissionTaskType::PET_TAMING, m_Parent->GetLOT());
} }
SetOnlyFlag(UNKNOWN1); // SetStatus(1); SetOnlyFlag(IDLE); // SetStatus(1);
auto* characterComponent = tamer->GetComponent<CharacterComponent>(); auto* characterComponent = tamer->GetComponent<CharacterComponent>();
if (characterComponent != nullptr) { if (characterComponent != nullptr) {
@ -856,7 +832,7 @@ void PetComponent::OnSpawn() {
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(UNKNOWN1); //SetStatus(PetFlag::NONE); //SetOnlyFlag(IDLE); //SetStatus(PetFlag::NONE);
SetPetAiState(PetAiState::follow); SetPetAiState(PetAiState::follow);
} }
else { else {
@ -864,14 +840,15 @@ void PetComponent::OnSpawn() {
SetPetAiState(PetAiState::idle); SetPetAiState(PetAiState::idle);
} }
SetFlag(UNKNOWN1); //IDLE? SetFlag(IDLE);
UnsetFlag(SPAWNING); UnsetFlag(SPAWNING);
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
} }
void PetComponent::OnFollow() { void PetComponent::OnFollow(const float& deltaTime) {
Entity* owner = GetOwner(); Entity* owner = GetOwner();
if (!owner) return; if (!owner) return;
const NiPoint3 ownerPos = owner->GetPosition(); const NiPoint3 ownerPos = owner->GetPosition();
// Find interactions // Find interactions
@ -904,14 +881,28 @@ void PetComponent::OnFollow() {
// Handle actual following logic // Handle actual following logic
const NiPoint3 currentPos = m_MovementAI->GetParent()->GetPosition(); const NiPoint3 currentPos = m_MovementAI->GetParent()->GetPosition();
const float distanceToOwner = Vector3::DistanceSquared(currentPos, ownerPos);
// If the player's position is within range, stop moving // If the player's position is within range, stop moving
if (Vector3::DistanceSquared(currentPos, ownerPos) <= 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);
LOG_DEBUG("New pet destination: %f %f %f", ownerPos.x, ownerPos.y, ownerPos.z); //LOG_DEBUG("New pet destination: %f %f %f", ownerPos.x, ownerPos.y, ownerPos.z);
}
// Teleporting logic
if (distanceToOwner > 50 * 50 || m_TimerAway > 5) {
m_MovementAI->Warp(ownerPos);
m_Timer = 1;
m_TimerAway = 0;
return;
}
else if (distanceToOwner > 15 * 15 || std::abs(ownerPos.y - currentPos.y) >= 3) {
m_TimerAway += deltaTime;
} }
m_Timer += 0.5f; m_Timer += 0.5f;
@ -962,7 +953,7 @@ void PetComponent::StartInteract(const NiPoint3 position, const PetInteractType
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
} }
void PetComponent::StopInteract() { void PetComponent::StopInteract(bool bDontSerialize) {
Entity* owner = GetOwner(); Entity* owner = GetOwner();
if (!owner) return; if (!owner) return;
@ -972,14 +963,17 @@ void PetComponent::StopInteract() {
SetInteractType(PetInteractType::none); SetInteractType(PetInteractType::none);
SetAbility(petAbility); SetAbility(petAbility);
SetPetAiState(PetAiState::follow); SetPetAiState(PetAiState::follow);
SetOnlyFlag(UNKNOWN1); //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!");
Game::entityManager->SerializeEntity(m_Parent); if (!bDontSerialize) {
Game::entityManager->SerializeEntity(m_Parent);
}
GameMessages::SendShowPetActionButton(m_Owner, petAbility, false, owner->GetSystemAddress()); // Needed? GameMessages::SendShowPetActionButton(m_Owner, petAbility, false, owner->GetSystemAddress()); // Needed?
} }
@ -1002,7 +996,8 @@ void PetComponent::SetupInteractTreasureDig() {
auto petAbility = ePetAbilityType::DigAtPosition; auto petAbility = ePetAbilityType::DigAtPosition;
SetAbility(petAbility); SetAbility(petAbility);
SetFlag(NOT_WAITING); //SetStatus(PetFlag::NOT_WAITING); // TODO: Double-check this is the right flag being set UnsetFlag(IDLE);
SetFlag(UNKNOWN256, 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
@ -1033,7 +1028,9 @@ void PetComponent::StartInteractTreasureDig() {
Game::entityManager->SerializeEntity(user); Game::entityManager->SerializeEntity(user);
SetIsHandlingInteraction(true); SetIsHandlingInteraction(true);
UnsetFlag(NOT_WAITING); // TODO: FIND THE CORRECT STATUS TO USE HERE UnsetFlag(UNKNOWN256, NOT_WAITING); // TODO: FIND THE CORRECT STATUS TO USE HERE
SetFlag(IDLE);
LOG_DEBUG("StartInteractTreasureDig() m_Flags = %d", m_Flags);
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 1, PetEmote::DigTreasure, true); // Plays 'dig' animation Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 1, PetEmote::DigTreasure, true); // Plays 'dig' animation
@ -1051,7 +1048,7 @@ void PetComponent::HandleInteractTreasureDig() {
GameMessages::SendHelp(m_Owner, eHelpType::PR_DIG_TUTORIAL_03, owner->GetSystemAddress()); GameMessages::SendHelp(m_Owner, eHelpType::PR_DIG_TUTORIAL_03, owner->GetSystemAddress());
LOG_DEBUG("Pet dig completed!"); LOG_DEBUG("Pet dig completed!");
StopInteract(); //TODO: This may not be totally consistent with live behavior, where the pet seems to stay near the dig and not immediately follow StopInteract(true); //TODO: This may not be totally consistent with live behavior, where the pet seems to stay near the dig and not immediately follow
return; return;
} }

View File

@ -35,7 +35,7 @@ enum PetInteractType : uint8_t {
*/ */
enum PetFlag : uint32_t { enum PetFlag : uint32_t {
NONE, NONE,
UNKNOWN1 = 1 << 0, //0x01 - Seems to be "idle," which the game doesn't differentiate from "follow" IDLE = 1 << 0, //0x01 - Seems to be "idle," which the game doesn't differentiate from "follow"
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,
@ -197,7 +197,7 @@ public:
/** /**
* Continues a step in the follow state, making sure that the entity is around its start position * Continues a step in the follow state, making sure that the entity is around its start position
*/ */
void OnFollow(); void OnFollow(const float& deltaTime);
/** /**
* Continues a step in the interact state, handling the pet's interaction with an entity * Continues a step in the interact state, handling the pet's interaction with an entity
@ -211,8 +211,9 @@ public:
/** /**
* Stop a pet interaction with an object * Stop a pet interaction with an object
* @param bDontSerialize optional parameter, set to true to not serialize afterwards
*/ */
void StopInteract(); void StopInteract(bool bDontSerialize = false);
/** /**
* Set the type of interaction the pet is executing * Set the type of interaction the pet is executing