diff --git a/extensions/include/extensions/multiplayer/protocol.h b/extensions/include/extensions/multiplayer/protocol.h index a6e8403c..95a0f996 100644 --- a/extensions/include/extensions/multiplayer/protocol.h +++ b/extensions/include/extensions/multiplayer/protocol.h @@ -191,7 +191,7 @@ struct AnimStartMsg { // Per-participant data in AnimCompleteMsg struct AnimCompletionParticipant { uint32_t peerId; - int8_t charIndex; // Participant's character (g_characters index) + int8_t charIndex; // Participant's character (g_actorInfoInit index) char displayName[8]; // 7 chars + null }; diff --git a/extensions/src/multiplayer/animation/catalog.cpp b/extensions/src/multiplayer/animation/catalog.cpp index 20ec04cf..a7fe17fc 100644 --- a/extensions/src/multiplayer/animation/catalog.cpp +++ b/extensions/src/multiplayer/animation/catalog.cpp @@ -1,25 +1,23 @@ #include "extensions/multiplayer/animation/catalog.h" #include "decomp.h" +#include "legoactors.h" #include "legoanimationmanager.h" -#include "legocharactermanager.h" #include "misc.h" #include using namespace Multiplayer::Animation; -// Defined in legoanimationmanager.cpp -extern LegoAnimationManager::Character g_characters[47]; - -// Exact-match a model name against g_characters[].m_name. +// Exact-match a model name against g_actorInfoInit[].m_name. // The engine's LegoAnimationManager::GetCharacterIndex uses 2-char prefix matching, // which causes false positives (e.g. "ladder" matching "laura"). We need exact // matching to correctly identify character performers vs props. +// Capped at 64 because performerMask is uint64_t. static int8_t GetCharacterIndex(const char* p_name) { - for (int8_t i = 0; i < (int8_t) sizeOfArray(g_characters); i++) { - if (!SDL_strcasecmp(p_name, g_characters[i].m_name)) { + for (int8_t i = 0; i < (int8_t) SDL_min(sizeOfArray(g_actorInfoInit), (size_t) 64); i++) { + if (!SDL_strcasecmp(p_name, g_actorInfoInit[i].m_name)) { return i; } } @@ -77,7 +75,7 @@ void Catalog::Refresh(LegoAnimationManager* p_am) entry.category = e_camAnim; } - // Compute performerMask by matching models against g_characters[].m_name + // Compute performerMask by matching models against g_actorInfoInit[].m_name entry.performerMask = 0; for (uint8_t m = 0; m < entry.modelCount; m++) { if (m_animsBase[i].m_models && m_animsBase[i].m_models[m].m_name) { @@ -107,12 +105,10 @@ const AnimInfo* Catalog::GetAnimInfo(uint16_t p_animIndex) const int8_t Catalog::DisplayActorToCharacterIndex(uint8_t p_displayActorIndex) { - const char* actorName = CharacterManager()->GetActorName(p_displayActorIndex); - if (!actorName) { + if (p_displayActorIndex >= SDL_min(sizeOfArray(g_actorInfoInit), (size_t) 64)) { return -1; } - - return GetCharacterIndex(actorName); + return static_cast(p_displayActorIndex); } const CatalogEntry* Catalog::FindEntry(uint16_t p_animIndex) const diff --git a/extensions/src/multiplayer/animation/coordinator.cpp b/extensions/src/multiplayer/animation/coordinator.cpp index 7f501471..d7faafd0 100644 --- a/extensions/src/multiplayer/animation/coordinator.cpp +++ b/extensions/src/multiplayer/animation/coordinator.cpp @@ -1,15 +1,12 @@ #include "extensions/multiplayer/animation/coordinator.h" #include "extensions/multiplayer/animation/catalog.h" -#include "legoanimationmanager.h" +#include "legoactors.h" #include using namespace Multiplayer::Animation; -// Defined in legoanimationmanager.cpp -extern LegoAnimationManager::Character g_characters[47]; - Coordinator::Coordinator() : m_catalog(nullptr), m_state(CoordinationState::e_idle), m_currentAnimIndex(ANIM_INDEX_NONE), m_localPeerId(0), m_cancelPending(false) @@ -59,8 +56,8 @@ static void BuildSlots( // One slot per performer bit in performerMask for (int8_t i : GetPerformerIndices(p_entry->performerMask)) { SlotInfo slot; - if (i < (int8_t) sizeOfArray(g_characters)) { - slot.names.push_back(g_characters[i].m_name); + if (i < (int8_t) sizeOfArray(g_actorInfoInit)) { + slot.names.push_back(g_actorInfoInit[i].m_name); } slot.filled = (p_filledPerformers & (uint64_t(1) << i)) != 0; p_slots.push_back(std::move(slot)); @@ -74,7 +71,7 @@ static void BuildSlots( else { for (int8_t i = 0; i < CORE_CHARACTER_COUNT; i++) { if ((p_entry->spectatorMask >> i) & 1) { - spectatorSlot.names.push_back(g_characters[i].m_name); + spectatorSlot.names.push_back(g_actorInfoInit[i].m_name); } } } diff --git a/extensions/src/multiplayer/animation/sceneplayer.cpp b/extensions/src/multiplayer/animation/sceneplayer.cpp index 66e73087..2a995721 100644 --- a/extensions/src/multiplayer/animation/sceneplayer.cpp +++ b/extensions/src/multiplayer/animation/sceneplayer.cpp @@ -4,6 +4,7 @@ #include "anim/legoanim.h" #include "extensions/common/animutils.h" #include "extensions/common/charactercloner.h" +#include "legoactors.h" #include "legoanimationmanager.h" #include "legocameracontroller.h" #include "legocharactermanager.h" @@ -28,9 +29,6 @@ using namespace Multiplayer::Animation; namespace AnimUtils = Extensions::Common::AnimUtils; using Extensions::Common::CharacterCloner; -// Defined in legoanimationmanager.cpp -extern LegoAnimationManager::Character g_characters[47]; - enum VehicleCategory { e_bike, e_motorcycle, @@ -54,10 +52,10 @@ static VehicleCategory GetVehicleCategory(MxU32 p_vehicleIdx) static bool MatchesCharacter(const std::string& p_actorName, int8_t p_charIndex) { - if (p_charIndex < 0 || p_charIndex >= (int8_t) sizeOfArray(g_characters)) { + if (p_charIndex < 0 || p_charIndex >= (int8_t) sizeOfArray(g_actorInfoInit)) { return false; } - return !SDL_strcasecmp(p_actorName.c_str(), g_characters[p_charIndex].m_name); + return !SDL_strcasecmp(p_actorName.c_str(), g_actorInfoInit[p_charIndex].m_name); } ScenePlayer::ScenePlayer() diff --git a/extensions/src/multiplayer/networkmanager.cpp b/extensions/src/multiplayer/networkmanager.cpp index 1c61f7e4..7d95f197 100644 --- a/extensions/src/multiplayer/networkmanager.cpp +++ b/extensions/src/multiplayer/networkmanager.cpp @@ -33,9 +33,6 @@ using Common::IsMultiPartEmote; using Common::IsRestrictedArea; using Common::WORLD_NOT_VISIBLE; -// Defined in legoanimationmanager.cpp -extern LegoAnimationManager::Character g_characters[47]; - // Slightly larger than NPC_ANIM_PROXIMITY to catch transitions static constexpr float NPC_ANIM_NEARBY_RADIUS_SQ = (Animation::NPC_ANIM_PROXIMITY + 5.0f) * (Animation::NPC_ANIM_PROXIMITY + 5.0f);