mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-14 07:47:13 +00:00
fix: a worn jetpack works again after a world change
Jetpack mode is not saved, and the equip skill that turns it on was cast only when the item was put on, so a player still wearing a jetpack lost it in the next world. Live sent SetJetPackMode (use, bypass checks, effect 167, the values of the jetpack's equip skill) shortly after the player's own construction in 12 of 28 world loads of a player with a jetpack, and constructed the player in jetpack mode in the other 16. The jetpack behaviors among the equip skills of the equipped items are run again when the player has loaded. Nothing new is saved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include "ZoneMessages.h"
|
||||
#include "MovementMessages.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "Behavior.h"
|
||||
#include "Character.h"
|
||||
#include "EntityManager.h"
|
||||
#include "ItemSet.h"
|
||||
@@ -1694,6 +1695,20 @@ std::vector<uint32_t> InventoryComponent::FindBuffs(Item* item, bool castOnEquip
|
||||
return buffs;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> InventoryComponent::FindEquippedJetPacks() const {
|
||||
std::vector<uint32_t> jetPacks;
|
||||
for (const auto& equipped : m_Equipped | std::views::values) {
|
||||
for (const auto behaviorID : FindBuffs(FindItemById(equipped.id), false)) {
|
||||
if (Behavior::GetBehaviorTemplate(behaviorID) == BehaviorTemplate::JETPACK) jetPacks.push_back(behaviorID);
|
||||
}
|
||||
}
|
||||
return jetPacks;
|
||||
}
|
||||
|
||||
void InventoryComponent::RecastEquippedJetPacks() const {
|
||||
for (const auto behaviorID : FindEquippedJetPacks()) SkillComponent::HandleUnmanaged(behaviorID, m_Parent->GetObjectID());
|
||||
}
|
||||
|
||||
void InventoryComponent::SetNPCItems(const std::vector<LOT>& items) {
|
||||
m_Equipped.clear();
|
||||
|
||||
|
||||
@@ -364,6 +364,17 @@ public:
|
||||
*/
|
||||
std::vector<uint32_t> FindBuffs(Item* item, bool castOnEquip) const;
|
||||
|
||||
/**
|
||||
* The jetpack behaviors among the equip skills of the equipped items
|
||||
*/
|
||||
std::vector<uint32_t> FindEquippedJetPacks() const;
|
||||
|
||||
/**
|
||||
* Puts a player that wears a jetpack back in jetpack mode after a world load: live sent SetJetPackMode again
|
||||
* shortly after the player's own construction in the next world, as the equip skill sends it
|
||||
*/
|
||||
void RecastEquippedJetPacks() const;
|
||||
|
||||
/**
|
||||
* One DeletionRestrictions row (CheckDeletionRestrictionIndex @ 00c94c20). visited stops rows that refer back to
|
||||
* themselves; the client lets such rows through.
|
||||
|
||||
@@ -143,6 +143,9 @@ namespace GameMessages {
|
||||
character->OnZoneLoad();
|
||||
}
|
||||
|
||||
// A jetpack that is worn works again in the new world (jetpack mode is not saved)
|
||||
if (auto* const inventory = entity->GetComponent<InventoryComponent>()) inventory->RecastEquippedJetPacks();
|
||||
|
||||
// Moved here from another instance: put back what their save doesn't keep (the pet that was out)
|
||||
WorldMigration::OnPlayerLoaded(entity);
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
#include "CDClientDatabase.h"
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDItemComponentTable.h"
|
||||
#include "CDBehaviorTemplateTable.h"
|
||||
#include "CDObjectSkillsTable.h"
|
||||
#include "CDSkillBehaviorTable.h"
|
||||
#include "BehaviorTemplate.h"
|
||||
#include "Character.h"
|
||||
#include "CharacterComponent.h"
|
||||
#include "EffectsMessages.h"
|
||||
@@ -210,3 +213,41 @@ TEST_F(EquipMessagesTests, UnequippingAndSlotsWithoutAnEffect) {
|
||||
sent = Messages(Capture([&] { rocket->Equip(true); }));
|
||||
EXPECT_EQ(sent, (std::vector<Sent>{ { CHANGE_OBJECT_WORLD_STATE, rocket->GetId(), true, "ATTACHED" } }));
|
||||
}
|
||||
|
||||
// A worn jetpack is found again after a world load, so jetpack mode can be sent again: live sent SetJetPackMode (use,
|
||||
// bypass checks, effect 167) about 100 packets after the player's own construction in 12 of 28 world loads of a player
|
||||
// with a jetpack, and constructed the player in jetpack mode in the other 16.
|
||||
TEST_F(EquipMessagesTests, AWornJetPackIsFoundAfterAWorldLoad) {
|
||||
constexpr LOT JETPACK = 1727; // skill 306, behavior 3569 on equip
|
||||
RegisterLot(JETPACK, "back");
|
||||
CDClientManager::GetEntriesMutable<CDObjectSkillsTable>().push_back({ JETPACK, 306, 1, 0 });
|
||||
CDClientManager::GetEntriesMutable<CDObjectSkillsTable>().push_back({ SWORD, 400, 0, 0 }); // a use skill, not an equip one
|
||||
auto& skills = CDClientManager::GetEntriesMutable<CDSkillBehaviorTable>();
|
||||
CDSkillBehavior jetPackSkill{};
|
||||
jetPackSkill.skillID = 306;
|
||||
jetPackSkill.behaviorID = 3569;
|
||||
skills.insert_or_assign(306, jetPackSkill);
|
||||
CDSkillBehavior hoodSkill{};
|
||||
hoodSkill.skillID = 362;
|
||||
hoodSkill.behaviorID = 4000;
|
||||
skills.insert_or_assign(362, hoodSkill);
|
||||
auto& templates = CDClientManager::GetEntriesMutable<CDBehaviorTemplateTable>();
|
||||
CDBehaviorTemplate jetPackTemplate{};
|
||||
jetPackTemplate.behaviorID = 3569;
|
||||
jetPackTemplate.templateID = static_cast<uint32_t>(BehaviorTemplate::JETPACK);
|
||||
templates.insert_or_assign(3569, jetPackTemplate);
|
||||
CDBehaviorTemplate buffTemplate{};
|
||||
buffTemplate.behaviorID = 4000;
|
||||
buffTemplate.templateID = static_cast<uint32_t>(BehaviorTemplate::BUFF);
|
||||
templates.insert_or_assign(4000, buffTemplate);
|
||||
|
||||
EXPECT_TRUE(inventory->FindEquippedJetPacks().empty());
|
||||
// What a save puts back: the equipped items, without their equip skills cast
|
||||
auto* const hood = Give(HOOD);
|
||||
auto* const jetPack = Give(JETPACK);
|
||||
Give(SWORD);
|
||||
inventory->UpdateSlot("hair", { hood->GetId(), HOOD, 1, 0 });
|
||||
EXPECT_TRUE(inventory->FindEquippedJetPacks().empty());
|
||||
inventory->UpdateSlot("back", { jetPack->GetId(), JETPACK, 1, 1 });
|
||||
EXPECT_EQ(inventory->FindEquippedJetPacks(), std::vector<uint32_t>{ 3569 });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user