feat(loot): smashables use the level's smashable_loot_matrix

A level object's smashable_loot_matrix replaces the DestructibleComponent
LootMatrixIndex when smashable_loot_matrix_set is true or absent and the
matrix is not -1, as the client resolves it
(LWODestroyableComponent::LoadConfigData 0x00c44cb0). DLU only read the
key in BaseInteractDropLootServer, so tagged smashables dropped their
template's loot. Resolution in DestroyableComponent::GetLevelLootMatrix,
with tests. No wire change.

In game: smash level smashables that carry smashable_loot_matrix_set=1
(11 level objects in the 1.10.64 levels) and ones with a matrix but no _set key; they drop the
level's loot instead of the template's. Ordinary smashables
(smashable_loot_matrix_set=0) drop what they did before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-28 23:34:30 -05:00
parent 721925add0
commit 54cd9abd7a
4 changed files with 54 additions and 0 deletions

View File

@@ -806,6 +806,15 @@ std::optional<std::vector<int32_t>> DestroyableComponent::GetLevelFactions(const
return factions;
}
std::optional<int32_t> DestroyableComponent::GetLevelLootMatrix(const Entity& entity) {
if (entity.HasVar(u"smashable_loot_matrix_set") && !entity.GetVar<bool>(u"smashable_loot_matrix_set")) return std::nullopt;
if (!entity.HasVar(u"smashable_loot_matrix")) return std::nullopt;
const auto lootMatrix = entity.GetVar<int32_t>(u"smashable_loot_matrix");
if (lootMatrix == -1) return std::nullopt;
return lootMatrix;
}
void DestroyableComponent::SetFaction(int32_t factionID, bool ignoreChecks) {
m_FactionIDs.clear();
m_EnemyFactionIDs.clear();