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
|
||||
};
|
||||
|
||||
PetComponent::PetComponent(Entity* parent, uint32_t componentId): Component(parent) {
|
||||
PetComponent::PetComponent(Entity* parent, uint32_t componentId) : Component(parent) {
|
||||
m_ComponentId = componentId;
|
||||
|
||||
m_Interaction = LWOOBJID_EMPTY;
|
||||
@ -109,25 +109,13 @@ PetComponent::PetComponent(Entity* parent, uint32_t componentId): Component(pare
|
||||
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) {
|
||||
const bool tamed = m_Owner != LWOOBJID_EMPTY;
|
||||
|
||||
outBitStream->Write1(); // Always serialize as dirty for now
|
||||
|
||||
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;
|
||||
|
||||
@ -177,7 +165,7 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
break;
|
||||
|
||||
case ePetAbilityType::JumpOnObject: // Bouncer
|
||||
//StartInteractBouncer();
|
||||
StartInteractBouncer();
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -350,12 +338,6 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
}
|
||||
|
||||
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
|
||||
m_TimerBounce -= deltaTime;
|
||||
|
||||
@ -398,8 +380,7 @@ void PetComponent::Update(float deltaTime) {
|
||||
LOG_DEBUG("Reached object!");
|
||||
m_MovementAI->Stop();
|
||||
SetPetAiState(PetAiState::interact);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_Timer += 0.5f;
|
||||
}
|
||||
break;
|
||||
@ -412,24 +393,6 @@ void PetComponent::Update(float deltaTime) {
|
||||
LOG_DEBUG("Unknown state: %d!", m_Flags);
|
||||
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
|
||||
@ -443,8 +406,7 @@ void PetComponent::UpdateUnowned(float deltaTime) { //TODO: CURRENTLY UNUSED
|
||||
ClientFailTamingMinigame();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (m_Timer > 0) {
|
||||
m_Timer -= deltaTime;
|
||||
|
||||
@ -798,17 +760,17 @@ void PetComponent::Wander() {
|
||||
return;
|
||||
}
|
||||
|
||||
m_MovementAI->SetMaxSpeed(m_PetInfo.sprintSpeed); //info.wanderSpeed);
|
||||
m_MovementAI->SetMaxSpeed(m_PetInfo->sprintSpeed); //info.wanderSpeed);
|
||||
|
||||
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() {
|
||||
if (!LoadPetInfo(m_ComponentId, m_PetInfo)) {
|
||||
LOG("Failed to load PetComponent (id: %d) information from CDClient!", m_ComponentId);
|
||||
}
|
||||
m_PetInfo = CDClientManager::Instance().GetTable<CDPetComponentTable>()->GetByID(m_ComponentId);
|
||||
if (!m_PetInfo) LOG("Failed to load PetComponent (id: %d) information from CDClient!", m_ComponentId);
|
||||
|
||||
m_MovementAI = m_Parent->GetComponent<MovementAIComponent>();
|
||||
|
||||
if (m_StartPosition == NiPoint3::ZERO) {
|
||||
@ -817,12 +779,11 @@ void PetComponent::OnSpawn() {
|
||||
|
||||
if (m_Owner != LWOOBJID_EMPTY) {
|
||||
m_Parent->SetOwnerOverride(m_Owner);
|
||||
m_MovementAI->SetMaxSpeed(m_PetInfo.sprintSpeed);
|
||||
m_MovementAI->SetMaxSpeed(m_PetInfo->sprintSpeed);
|
||||
m_MovementAI->SetHaltDistance(m_FollowRadius);
|
||||
//SetOnlyFlag(IDLE); //SetStatus(PetFlag::NONE);
|
||||
SetPetAiState(PetAiState::follow);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
SetFlag(TAMEABLE);
|
||||
SetPetAiState(PetAiState::idle);
|
||||
}
|
||||
@ -873,8 +834,7 @@ void PetComponent::OnFollow(const float& deltaTime) {
|
||||
// If the player's position is within range, stop moving
|
||||
if (distanceToOwner <= m_FollowRadius * m_FollowRadius) {
|
||||
m_MovementAI->Stop();
|
||||
}
|
||||
else { // Chase the player's new position
|
||||
} else { // Chase the player's new position
|
||||
m_MovementAI->SetDestination(ownerPos);
|
||||
}
|
||||
|
||||
@ -886,8 +846,7 @@ void PetComponent::OnFollow(const float& deltaTime) {
|
||||
m_TimerAway = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -910,7 +869,7 @@ void PetComponent::OnInteract() {
|
||||
|
||||
switch (GetInteractType()) {
|
||||
case PetInteractType::bouncer:
|
||||
if (IsReadyToInteract()) LOG_DEBUG("Add the HandleInteractBouncer()!");
|
||||
if (IsReadyToInteract()) HandleInteractBouncer();
|
||||
else SetupInteractBouncer();
|
||||
break;
|
||||
|
||||
@ -932,7 +891,7 @@ void PetComponent::StartInteract(const NiPoint3 position, const PetInteractType
|
||||
SetInteractType(interactType);
|
||||
SetAbility(ePetAbilityType::GoToObject);
|
||||
SetPetAiState(PetAiState::goToObj);
|
||||
m_MovementAI->SetMaxSpeed(m_PetInfo.runSpeed);
|
||||
m_MovementAI->SetMaxSpeed(m_PetInfo->runSpeed);
|
||||
m_MovementAI->SetHaltDistance(0.0f);
|
||||
m_MovementAI->SetDestination(position);
|
||||
LOG_DEBUG("Starting interaction!");
|
||||
@ -952,7 +911,7 @@ void PetComponent::StopInteract(bool bDontSerialize) {
|
||||
SetOnlyFlag(IDLE); //SetStatus(PetFlag::NONE);
|
||||
SetIsReadyToInteract(false);
|
||||
SetIsHandlingInteraction(false); // Needed?
|
||||
m_MovementAI->SetMaxSpeed(m_PetInfo.sprintSpeed);
|
||||
m_MovementAI->SetMaxSpeed(m_PetInfo->sprintSpeed);
|
||||
m_MovementAI->SetHaltDistance(m_FollowRadius);
|
||||
LOG_DEBUG("Stopping interaction!");
|
||||
|
||||
@ -964,32 +923,107 @@ void PetComponent::StopInteract(bool bDontSerialize) {
|
||||
}
|
||||
|
||||
void PetComponent::SetupInteractBouncer() {
|
||||
const auto* owner = GetOwner();
|
||||
if (!owner) return;
|
||||
|
||||
LOG_DEBUG("Setting up bouncer interaction!");
|
||||
SetIsReadyToInteract(true);
|
||||
const auto petAbility = ePetAbilityType::JumpOnObject;
|
||||
|
||||
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_BOUNCER_TUTORIAL_03, 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;
|
||||
}
|
||||
|
||||
void PetComponent::StartInteractBouncer() {
|
||||
Entity* user = GetOwner();
|
||||
if (IsHandlingInteraction() || !user) return;
|
||||
|
||||
auto* destroyableComponent = user->GetComponent<DestroyableComponent>();
|
||||
if (!destroyableComponent) return;
|
||||
|
||||
auto imagination = destroyableComponent->GetImagination();
|
||||
const int32_t imaginationCost = 2; // 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);
|
||||
Game::entityManager->SerializeEntity(user);
|
||||
|
||||
// THIS IS ALL BAD, BAD, BAD! FIX IT, ME! >:(
|
||||
/*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);*/
|
||||
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() {
|
||||
auto* owner = GetOwner();
|
||||
const auto* owner = GetOwner();
|
||||
if (!owner) return;
|
||||
|
||||
LOG_DEBUG("Setting up dig interaction!");
|
||||
SetIsReadyToInteract(true);
|
||||
auto petAbility = ePetAbilityType::DigAtPosition;
|
||||
const auto petAbility = ePetAbilityType::DigAtPosition;
|
||||
|
||||
SetAbility(petAbility);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1001,7 +1035,7 @@ void PetComponent::StartInteractTreasureDig() {
|
||||
if (!destroyableComponent) return;
|
||||
|
||||
auto imagination = destroyableComponent->GetImagination();
|
||||
int32_t imaginationCost = 1; // TODO: Get rid of this magic number - make static variable from lookup
|
||||
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;
|
||||
@ -1014,7 +1048,7 @@ void PetComponent::StartInteractTreasureDig() {
|
||||
Game::entityManager->SerializeEntity(user);
|
||||
|
||||
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);
|
||||
LOG_DEBUG("StartInteractTreasureDig() m_Flags = %d", m_Flags);
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
@ -1025,10 +1059,10 @@ void PetComponent::StartInteractTreasureDig() {
|
||||
|
||||
void PetComponent::HandleInteractTreasureDig() {
|
||||
if (IsHandlingInteraction()) {
|
||||
auto* owner = GetOwner();
|
||||
auto* const owner = GetOwner();
|
||||
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());
|
||||
|
||||
GameMessages::SendHelp(m_Owner, eHelpType::PR_DIG_TUTORIAL_03, owner->GetSystemAddress());
|
||||
@ -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
|
||||
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);
|
||||
|
||||
m_ItemId = item->GetId();
|
||||
@ -1129,7 +1166,7 @@ void PetComponent::AddDrainImaginationTimer(Item* item, bool fromTaming) {
|
||||
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.
|
||||
m_Parent->AddCallbackTimer(m_PetInfo.imaginationDrainRate, [playerDestroyableComponent, this, item]() {
|
||||
m_Parent->AddCallbackTimer(m_PetInfo->imaginationDrainRate, [playerDestroyableComponent, this, item]() {
|
||||
if (!playerDestroyableComponent) {
|
||||
LOG("No petComponent and/or no playerDestroyableComponent");
|
||||
return;
|
||||
@ -1303,7 +1340,7 @@ void PetComponent::SetPetNameForModeration(const std::string& petName) {
|
||||
}
|
||||
|
||||
//Save to db:
|
||||
Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{petName, approved});
|
||||
Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{ petName, approved });
|
||||
}
|
||||
|
||||
void PetComponent::LoadPetNameFromModeration() {
|
||||
|
@ -39,9 +39,9 @@ enum PetFlag : uint32_t {
|
||||
UNKNOWN4 = 1 << 2, //0x04 - FOLLOWING(?)
|
||||
BEING_TAMED = 1 << 4, //0x10,
|
||||
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
|
||||
UNKNOWN256 = 1 << 8, //0x100
|
||||
ON_SWITCH = 1 << 8, //0x100
|
||||
UNKNOWN1024 = 1 << 10, //0x400
|
||||
TAMEABLE = 1 << 26 //0x4000000
|
||||
};
|
||||
@ -70,11 +70,6 @@ public:
|
||||
PetComponent(Entity* parentEntity, uint32_t componentId);
|
||||
~PetComponent() override;
|
||||
|
||||
/**
|
||||
* Loads pet info from CDClient
|
||||
*/
|
||||
bool LoadPetInfo(uint32_t petId, CDPetComponent& result);
|
||||
|
||||
/**
|
||||
* Serializes the pet
|
||||
* @param outBitStream The output bitstream
|
||||
@ -346,6 +341,16 @@ public:
|
||||
*/
|
||||
void SetupInteractBouncer();
|
||||
|
||||
/**
|
||||
* Starts the pet bouncer interaction
|
||||
*/
|
||||
void StartInteractBouncer();
|
||||
|
||||
/**
|
||||
* Handles the pet bouncer interaction
|
||||
*/
|
||||
void HandleInteractBouncer();
|
||||
|
||||
/**
|
||||
* Set up the treasure dig interaction
|
||||
*/
|
||||
@ -437,7 +442,7 @@ private:
|
||||
/**
|
||||
* Pet information loaded from the CDClientDatabase
|
||||
*/
|
||||
CDPetComponent m_PetInfo;
|
||||
CDPetComponent* m_PetInfo;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 2602, u"pettriggeractive", "BounceEffect", LWOOBJID_EMPTY, 1, 1, true);
|
||||
RenderComponent::PlayAnimation(m_Parent, u"engaged");
|
||||
m_PetBouncer->SetPetBouncerEnabled(true);
|
||||
//RenderComponent::PlayAnimation(m_Parent, u"engaged");
|
||||
//m_PetBouncer->SetPetBouncerEnabled(true);
|
||||
} else {
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user