diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 48551c47d..63a045b1f 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -367,18 +367,21 @@ 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->OnUse(m_Parent); - } else if (distance < 20 * 20) { - haltDistance = 1; + Entity* abilityObject = nullptr; + auto objectAbility = ePetAbilityType::Invalid; + bool atAbilityObject = false; - destination = switchPosition; - } + if (closestSwitch != nullptr && !closestSwitch->GetActive()) { + NiPoint3 switchPosition = closestSwitch->GetParentEntity()->GetPosition(); + float distance = Vector3::DistanceSquared(position, switchPosition); + if (distance < 20 * 20) { + abilityObject = closestSwitch->GetParentEntity(); + objectAbility = ePetAbilityType::JumpOnObject; + atAbilityObject = distance < 3 * 3; + + haltDistance = 1; + + destination = switchPosition; } } @@ -390,10 +393,6 @@ void PetComponent::Update(float deltaTime) { Entity* closestTreasure = PetDigServer::GetClosestTreasure(position); - Entity* abilityObject = nullptr; - auto objectAbility = ePetAbilityType::Invalid; - bool atAbilityObject = false; - // Skeleton Dragon Pat special case for bone digging if (closestTreasure != nullptr && digUnlocked && (closestTreasure->GetLOT() != 12192 || m_Parent->GetLOT() == 13067)) { NiPoint3 treasurePosition = closestTreasure->GetPosition(); @@ -1190,6 +1189,7 @@ void PetComponent::SetAbilityObject(Entity* object, const ePetAbilityType abilit Game::entityManager->SerializeEntity(m_Parent); if (ability == ePetAbilityType::DigAtPosition) SendHelp(eHelpType::PR_DIG_TUTORIAL_01); + else if (ability == ePetAbilityType::JumpOnObject) SendHelp(eHelpType::PR_BOUNCER_TUTORIAL_01); } if (!atObject || m_AbilityButtonShown) return; @@ -1198,6 +1198,13 @@ void PetComponent::SetAbilityObject(Entity* object, const ePetAbilityType abilit SetStatus(status | PET_STATE_USING_ABILITY | PET_STATE_AT_ABILITY_OBJECT); Game::entityManager->SerializeEntity(m_Parent); + if (ability == ePetAbilityType::JumpOnObject) { + // On the pet switch, as live did: the pet gets excited and the switch engages + RenderComponent::PlayAnimation(m_Parent, u"excited"); + RenderComponent::PlayAnimation(object, u"engaged"); + SendHelp(eHelpType::PR_BOUNCER_TUTORIAL_03); + } + auto* const owner = GetOwner(); if (!owner) return; @@ -1238,6 +1245,18 @@ void PetComponent::UseAbility() { Command(NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 1, 202, true); m_TreasureTime = 2; + } else if (ability == ePetAbilityType::JumpOnObject) { + // The pet jumps on the switch, which turns its bouncer on; the pet is done with the switch then + m_Ability = ePetAbilityType::Invalid; + m_AbilityObject = LWOOBJID_EMPTY; + SetStatus(m_Status & ~(PET_STATE_AT_ABILITY_OBJECT | PET_STATE_USING_ABILITY | PET_STATE_GOING_TO_ABILITY_OBJECT)); + Game::entityManager->SerializeEntity(m_Parent); + + RenderComponent::PlayAnimation(m_Parent, u"jump"); + SendHelp(eHelpType::PR_TOOLTIP_1ST_PET_JUMPED_ON_SWITCH); + + auto* const switchComponent = object->GetComponent(); + if (switchComponent) switchComponent->OnUse(m_Parent); } } diff --git a/dGame/dComponents/PetComponent.h b/dGame/dComponents/PetComponent.h index d9a40dd22..d18e3a9f0 100644 --- a/dGame/dComponents/PetComponent.h +++ b/dGame/dComponents/PetComponent.h @@ -232,7 +232,7 @@ public: private: /** - * Sets the object the pet goes to use its ability on (a dig), or none. The pet first goes to it; once it is there + * Sets the object the pet goes to use its ability on (a pet switch or a dig), or none. The pet first goes to it; once it is there * its owner gets the pet's action button, which uses the ability. * @param object the object, nullptr for none * @param ability the ability the object is for @@ -399,7 +399,7 @@ private: bool m_Despawning{ false }; /** - * The object the pet goes to use its ability on (a dig), if any. Live did not serialize it as the interaction. + * The object the pet goes to use its ability on (a pet switch or a dig), if any. Live did not serialize it as the interaction. */ LWOOBJID m_AbilityObject{ LWOOBJID_EMPTY }; diff --git a/dGame/dComponents/SwitchComponent.cpp b/dGame/dComponents/SwitchComponent.cpp index 07f989877..0d7f6755b 100644 --- a/dGame/dComponents/SwitchComponent.cpp +++ b/dGame/dComponents/SwitchComponent.cpp @@ -80,7 +80,8 @@ void SwitchComponent::EntityEnter(Entity* entity) { if (m_PetBouncer != nullptr) { GameMessages::PlayFXEffect(m_Parent->GetObjectID(), 2602, u"pettriggeractive", "BounceEffect").Send(UNASSIGNED_SYSTEM_ADDRESS); - RenderComponent::PlayAnimation(m_Parent, u"engaged"); + // Live played "launch" here; "engaged" is played when a pet arrives on the switch + RenderComponent::PlayAnimation(m_Parent, u"launch"); m_PetBouncer->SetPetBouncerEnabled(true); } else { Game::entityManager->SerializeEntity(m_Parent);