mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-24 22:43:34 +00:00
pet bouncer minimum functionality
This commit is contained in:
parent
d7d5202c17
commit
6edd42d37c
@ -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() {
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user