mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-24 22:43:34 +00:00
redone pet update loop
This commit is contained in:
parent
1c01219ae9
commit
200d679dd8
@ -82,32 +82,41 @@ PetComponent::PetComponent(Entity* parent, uint32_t componentId): Component(pare
|
||||
m_DatabaseId = LWOOBJID_EMPTY;
|
||||
m_Status = PetStatus::TAMEABLE; // Tameable
|
||||
m_Ability = PetAbilityType::Invalid;
|
||||
m_StartPosition = NiPoint3::ZERO;
|
||||
m_StartPosition = m_Parent->GetPosition(); //NiPoint3::ZERO;
|
||||
m_MovementAI = nullptr;
|
||||
m_TresureTime = 0;
|
||||
m_Preconditions = nullptr;
|
||||
|
||||
m_ReadyToDig = false;
|
||||
m_InInteract = false;
|
||||
SetPetAiState(PetAiState::spawn);
|
||||
|
||||
std::string checkPreconditions = GeneralUtils::UTF16ToWTF8(parent->GetVar<std::u16string>(u"CheckPrecondition"));
|
||||
|
||||
if (!checkPreconditions.empty()) {
|
||||
SetPreconditions(checkPreconditions);
|
||||
}
|
||||
// Get the imagination drain rate from the CDClient
|
||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT imaginationDrainRate FROM PetComponent WHERE id = ?;");
|
||||
|
||||
// Get pet information from the CDClient
|
||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
||||
"SELECT walkSpeed, runSpeed, sprintSpeed, imaginationDrainRate FROM PetComponent WHERE id = ?;");
|
||||
query.bind(1, static_cast<int>(componentId));
|
||||
|
||||
auto result = query.execQuery();
|
||||
|
||||
// Should a result not exist for this pet default to 60 seconds.
|
||||
if (!result.eof() && !result.fieldIsNull(0)) {
|
||||
imaginationDrainRate = result.getFloatField(0, 60.0f);
|
||||
} else {
|
||||
imaginationDrainRate = 60.0f;
|
||||
if (!result.eof()) {
|
||||
if (!result.fieldIsNull(0))
|
||||
m_walkSpeed = result.getFloatField(0);
|
||||
|
||||
if (!result.fieldIsNull(1))
|
||||
m_RunSpeed = result.getFloatField(1);
|
||||
|
||||
if (!result.fieldIsNull(2))
|
||||
m_SprintSpeed = result.getFloatField(2);
|
||||
|
||||
if (!result.fieldIsNull(3))
|
||||
imaginationDrainRate = result.getFloatField(3);
|
||||
}
|
||||
|
||||
result.finalize();
|
||||
}
|
||||
|
||||
@ -152,19 +161,17 @@ void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpd
|
||||
}
|
||||
}
|
||||
|
||||
void PetComponent::SetPetAiState(PetAiState newState) {
|
||||
if (newState == GetPetAiState()) return;
|
||||
this->m_State = newState;
|
||||
LOG_DEBUG("Set pet AI state!");
|
||||
//Game::entityManager->SerializeEntity(m_Parent); // Do we need to serialize entity?
|
||||
}
|
||||
|
||||
void PetComponent::OnUse(Entity* originator) {
|
||||
LOG("PET USE!");
|
||||
|
||||
/*if(m_ReadyToDig) {
|
||||
LOG("Dig initiated!");
|
||||
m_TresureTime = 2.0f;
|
||||
//m_ReadyToDig = false;
|
||||
SetAbility(PetAbilityType::DigAtPosition);
|
||||
}*/
|
||||
|
||||
if (m_Owner != LWOOBJID_EMPTY) {
|
||||
return;
|
||||
}
|
||||
if (m_Owner != LWOOBJID_EMPTY) return;
|
||||
|
||||
if (m_Tamer != LWOOBJID_EMPTY) {
|
||||
auto* tamer = Game::entityManager->GetEntity(m_Tamer);
|
||||
@ -336,29 +343,159 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
}
|
||||
|
||||
void PetComponent::Update(float deltaTime) {
|
||||
if (m_StartPosition == NiPoint3::ZERO) {
|
||||
m_StartPosition = m_Parent->GetPosition();
|
||||
}
|
||||
|
||||
// If pet does not have an owner, use the UpdateUnowned() loop
|
||||
if (m_Owner == LWOOBJID_EMPTY) {
|
||||
UpdateUnowned(deltaTime);
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine pet owner
|
||||
auto* owner = GetOwner();
|
||||
if (!owner) {
|
||||
m_Parent->Kill();
|
||||
m_Parent->Kill(); // Kill pet if no owner
|
||||
return;
|
||||
}
|
||||
|
||||
m_MovementAI = m_Parent->GetComponent<MovementAIComponent>();
|
||||
if (!m_MovementAI) return;
|
||||
// Update timer
|
||||
if (m_Timer > 0) {
|
||||
m_Timer -= deltaTime;
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle treasure timer
|
||||
if (m_TresureTime > 0.0f) { //TODO: Find better trigger?
|
||||
InteractDig(deltaTime);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle pet AI states
|
||||
switch (m_State) {
|
||||
// Handle idle state
|
||||
case PetAiState::idle: {
|
||||
LOG_DEBUG("Pet in idle state!");
|
||||
m_Timer = 1.0f;
|
||||
break;
|
||||
}
|
||||
// Handle follow state
|
||||
case PetAiState::follow: {
|
||||
// Get movement AI component
|
||||
m_MovementAI = m_Parent->GetComponent<MovementAIComponent>();
|
||||
if (!m_MovementAI) return;
|
||||
|
||||
// Get and set destination
|
||||
//auto position = m_MovementAI->GetParent()->GetPosition();
|
||||
auto ownerPos = owner->GetPosition();
|
||||
NiPoint3 destination = ownerPos;
|
||||
NiPoint3 interactPos = NiPoint3::ZERO;
|
||||
|
||||
// Determine if the "Lost Tags" mission has been completed and digging has been unlocked
|
||||
auto* missionComponent = owner->GetComponent<MissionComponent>();
|
||||
if (!missionComponent) return;
|
||||
const bool digUnlocked = missionComponent->GetMissionState(842) == eMissionState::COMPLETE;
|
||||
|
||||
// Interactions checks
|
||||
SwitchComponent* closestSwitch = SwitchComponent::GetClosestSwitch(ownerPos);
|
||||
Entity* closestTreasure = PetDigServer::GetClosestTresure(ownerPos);
|
||||
if (closestSwitch != nullptr && !closestSwitch->GetActive()) {
|
||||
m_Interaction = closestSwitch->GetParentEntity()->GetObjectID();
|
||||
interactPos = closestSwitch->GetParentEntity()->GetPosition();
|
||||
m_Ability = PetAbilityType::GoToObject;
|
||||
}
|
||||
if (closestTreasure != nullptr && digUnlocked) {
|
||||
m_Interaction = closestTreasure->GetObjectID();
|
||||
interactPos = closestTreasure->GetPosition();
|
||||
m_Ability = PetAbilityType::GoToObject;
|
||||
}
|
||||
|
||||
// Trigger interaction if checks are valid
|
||||
if (m_Ability != PetAbilityType::Invalid) {
|
||||
float distance = Vector3::DistanceSquared(ownerPos, interactPos);
|
||||
if (distance < 20 * 20) {
|
||||
destination = interactPos;
|
||||
m_MovementAI->SetHaltDistance(0.0f);
|
||||
SetPetAiState(PetAiState::interact);
|
||||
}
|
||||
}
|
||||
|
||||
m_MovementAI->SetDestination(destination);
|
||||
//LOG_DEBUG("Pet destination: %f %f %f", destination.x, destination.y, destination.z);
|
||||
m_Timer = 1.0f;
|
||||
|
||||
break;
|
||||
}
|
||||
// Handle interact state
|
||||
case PetAiState::interact: {
|
||||
LOG_DEBUG("Interacting with object!");
|
||||
|
||||
// Get movement AI component
|
||||
m_MovementAI = m_Parent->GetComponent<MovementAIComponent>();
|
||||
if (!m_MovementAI) return;
|
||||
|
||||
// Get distance from owner
|
||||
auto ownerPos = owner->GetPosition();
|
||||
auto position = m_MovementAI->GetParent()->GetPosition();
|
||||
float distanceFromOwner = Vector3::DistanceSquared(position, ownerPos);
|
||||
|
||||
// Switch back to follow AI state if player moves too far away from pet
|
||||
if (distanceFromOwner > 15 * 15) {
|
||||
m_MovementAI->SetHaltDistance(5.0f); // TODO: Remove this magic number
|
||||
m_Interaction = LWOOBJID_EMPTY;
|
||||
m_Ability = PetAbilityType::Invalid;
|
||||
SetIsReadyToDig(false);
|
||||
SetPetAiState(PetAiState::follow);
|
||||
LOG_DEBUG("Pet interaction aborted due to player distance!");
|
||||
break;
|
||||
}
|
||||
|
||||
// Get distance from interactable
|
||||
auto destination = m_MovementAI->GetDestination();
|
||||
float distanceFromInteract = Vector3::DistanceSquared(position, destination);
|
||||
|
||||
// Handle the interaction
|
||||
if (m_MovementAI->AtFinalWaypoint()) {
|
||||
Entity* interactEntity = Game::entityManager->GetEntity(m_Interaction);
|
||||
|
||||
/*auto* switchComponent = interactEntity->GetComponent<SwitchComponent>();
|
||||
if (switchComponent != nullptr) {
|
||||
switchComponent->EntityEnter(m_Parent);
|
||||
}
|
||||
else {*/
|
||||
Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 1, PetEmote::Bounce, true); // Plays 'bounce' animation
|
||||
SetIsReadyToDig(true);
|
||||
//}
|
||||
}
|
||||
|
||||
m_Timer = 1.0f;
|
||||
break;
|
||||
}
|
||||
// Handle spawn state
|
||||
case PetAiState::spawn: {
|
||||
LOG_DEBUG("Pet spawned!");
|
||||
|
||||
// Get movement AI component
|
||||
m_MovementAI = m_Parent->GetComponent<MovementAIComponent>();
|
||||
if (!m_MovementAI) return;
|
||||
|
||||
// Determine the pet start position
|
||||
if (m_StartPosition == NiPoint3::ZERO) m_StartPosition = m_Parent->GetPosition();
|
||||
|
||||
// Determine next state;
|
||||
if (m_Owner == LWOOBJID_EMPTY) {
|
||||
SetPetAiState(PetAiState::idle);
|
||||
}
|
||||
else {
|
||||
SetPetAiState(PetAiState::follow);
|
||||
m_MovementAI->SetMaxSpeed(m_SprintSpeed);
|
||||
m_MovementAI->SetHaltDistance(5.0f); // TODO: Remove magic number
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
/*
|
||||
|
||||
auto destination = owner->GetPosition();
|
||||
NiPoint3 position = m_MovementAI->GetParent()->GetPosition();
|
||||
|
||||
@ -387,18 +524,15 @@ void PetComponent::Update(float deltaTime) {
|
||||
|
||||
float haltDistance = 5;
|
||||
|
||||
if (closestSwitch != nullptr) {
|
||||
if (!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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,13 +568,13 @@ void PetComponent::Update(float deltaTime) {
|
||||
|
||||
skipTresure:
|
||||
|
||||
//m_MovementAI->SetHaltDistance(haltDistance);
|
||||
m_MovementAI->SetHaltDistance(haltDistance);
|
||||
|
||||
//m_MovementAI->SetMaxSpeed(2.5f);
|
||||
|
||||
m_MovementAI->SetDestination(destination);
|
||||
|
||||
m_Timer = 1;
|
||||
m_Timer = 1;*/
|
||||
}
|
||||
|
||||
void PetComponent::UpdateUnowned(float deltaTime) {
|
||||
@ -473,6 +607,7 @@ void PetComponent::SetIsReadyToDig(bool isReady) {
|
||||
//SetAbility(PetAbilityType::JumpOnObject);
|
||||
SetStatus(PetStatus::IS_NOT_WAITING); // Treasure dig status
|
||||
m_ReadyToDig = true;
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}
|
||||
else {
|
||||
LOG("Dig state ended!");
|
||||
@ -480,6 +615,7 @@ void PetComponent::SetIsReadyToDig(bool isReady) {
|
||||
//SetAbility(PetAbilityType::Invalid);
|
||||
SetStatus(0); // TODO: Check status
|
||||
m_ReadyToDig = false;
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1022,7 +1158,7 @@ void PetComponent::Command(NiPoint3 position, LWOOBJID source, int32_t commandTy
|
||||
// Emotes
|
||||
GameMessages::SendPlayEmote(m_Parent->GetObjectID(), typeId, owner->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
} else if (commandType == 3) {
|
||||
// Follow me, ???
|
||||
SetPetAiState(PetAiState::follow);
|
||||
} else if (commandType == 6) {
|
||||
// TODO: Go to player
|
||||
}
|
||||
@ -1034,7 +1170,7 @@ void PetComponent::Command(NiPoint3 position, LWOOBJID source, int32_t commandTy
|
||||
// Add movement functionality
|
||||
if (position != NiPoint3::ZERO) {
|
||||
m_MovementAI->SetDestination(position);
|
||||
m_Timer = 9; //Is this setting how long until the next update tick?
|
||||
//m_Timer = 9; //Is this setting how long until the next update tick?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,21 @@
|
||||
#include "Preconditions.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/*
|
||||
* The current state of the pet AI
|
||||
*/
|
||||
enum class PetAiState : uint {
|
||||
idle = 0, // Doing nothing
|
||||
spawn, // Spawning into the world
|
||||
follow, // Following player
|
||||
interact, // Beginning interaction
|
||||
goToObj, // Go to object
|
||||
despawn // Despawning from world
|
||||
};
|
||||
|
||||
/*
|
||||
* The status of the pet: Governs the icon above their head and the interactions available
|
||||
*/
|
||||
enum PetStatus : uint32_t {
|
||||
NONE,
|
||||
BEING_TAMED = 0x10,
|
||||
@ -41,6 +56,18 @@ public:
|
||||
~PetComponent() override;
|
||||
|
||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
/**
|
||||
* Sets the AI state of the pet
|
||||
* @param newState New pet AI state
|
||||
*/
|
||||
void SetPetAiState(PetAiState newState);
|
||||
|
||||
/**
|
||||
* Gets the AI state of the pet
|
||||
*/
|
||||
PetAiState GetPetAiState() { return m_State; };
|
||||
|
||||
void Update(float deltaTime) override;
|
||||
|
||||
/**
|
||||
@ -373,6 +400,11 @@ private:
|
||||
*/
|
||||
uint32_t m_Status;
|
||||
|
||||
/**
|
||||
* The current state of the pet AI
|
||||
*/
|
||||
PetAiState m_State;
|
||||
|
||||
/**
|
||||
* A currently active ability, mostly unused
|
||||
*/
|
||||
@ -399,11 +431,6 @@ private:
|
||||
*/
|
||||
bool m_ReadyToDig;
|
||||
|
||||
/**
|
||||
* Boolean that sets if a pet is in an interaction
|
||||
*/
|
||||
bool m_InInteract;
|
||||
|
||||
/**
|
||||
* The position that this pet was spawned at
|
||||
*/
|
||||
@ -423,4 +450,19 @@ private:
|
||||
* The rate at which imagination is drained from the user for having the pet out.
|
||||
*/
|
||||
float imaginationDrainRate;
|
||||
|
||||
/**
|
||||
* The walk speed of the pet
|
||||
*/
|
||||
float m_walkSpeed;
|
||||
|
||||
/**
|
||||
* The run speed of the pet
|
||||
*/
|
||||
float m_RunSpeed;
|
||||
|
||||
/**
|
||||
* The sprint speed of the pet
|
||||
*/
|
||||
float m_SprintSpeed;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user