mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-05-02 10:33:57 +00:00
* Add feasibility plan for reusing multiplayer animation system for third-person camera Evaluates reusing the multiplayer extension's RemotePlayer animation system (BuildROIMap, AssignROIIndices, ApplyAnimationTransformation) for the local player to enable a third-person camera mode. Conclusion: feasible with only 3 single-line extension hooks added to core game code. https://claude.ai/code/session_01NC3zdQZ4nqEcYjyvStqcdD * WIP: Third-person camera with animation reuse and movement fix * Fix third-person camera bugs: vehicles, remote facing, emote distortion (#2) - Fix spawn pose and building re-entry by applying idle frame 0 and reinitializing on world enable - Handle vehicle transitions: ride animations for small vehicles, first-person fallback for large vehicles and helicopter - Keep vehicle dashboards visible for exit controls - Disable third-person camera for large vehicles, fix ROI cleanup - Move HandleActorExit hook to end of Exit() for immediate reinit - Fix remote player facing 180 degrees wrong by negating direction in BroadcastLocalState when third-person camera is active - Fix Hat Tip emote distortion from compounding transform scale by saving clean parent transform at emote start and restoring after each frame's animation application * DRY cleanup for third-person camera branch - Extract shared DetectVehicleType() to protocol.h/cpp (was duplicated in ThirdPersonCamera and NetworkManager) - Remove no-op HandlePostApplyTransform hook chain (called every frame for every LegoPathActor but did nothing) - Add ThirdPersonCamera::ClearAnimCaches() helper (pattern repeated 5x) - Add AnimUtils::EnsureROIMapVisibility() inline helper (loop repeated 5x across ThirdPersonCamera and RemotePlayer) - Remove redundant static_cast in multiplayer.cpp (UserActor() already returns LegoPathActor*) - Delete THIRD_PERSON_CAMERA_ANIMATION_REUSE_PLAN.md development artifact
80 lines
2.2 KiB
C++
80 lines
2.2 KiB
C++
#include "extensions/multiplayer/protocol.h"
|
|
|
|
#include "legopathactor.h"
|
|
|
|
#include <cstddef>
|
|
|
|
namespace Multiplayer
|
|
{
|
|
|
|
const char* const g_walkAnimNames[] = {
|
|
"CNs001xx", // 0: Normal (default)
|
|
"CNs002xx", // 1: Joyful
|
|
"CNs003xx", // 2: Gloomy
|
|
"CNs005xx", // 3: Leaning
|
|
"CNs006xx", // 4: Scared
|
|
"CNs007xx", // 5: Hyper
|
|
};
|
|
const int g_walkAnimCount = sizeof(g_walkAnimNames) / sizeof(g_walkAnimNames[0]);
|
|
|
|
const char* const g_idleAnimNames[] = {
|
|
"CNs008xx", // 0: Sway (default)
|
|
"CNs009xx", // 1: Groove
|
|
"CNs010xx", // 2: Excited
|
|
};
|
|
const int g_idleAnimCount = sizeof(g_idleAnimNames) / sizeof(g_idleAnimNames[0]);
|
|
|
|
const char* const g_emoteAnimNames[] = {
|
|
"CNs011xx", // 0: Wave
|
|
"CNs012xx", // 1: Hat Tip
|
|
};
|
|
const int g_emoteAnimCount = sizeof(g_emoteAnimNames) / sizeof(g_emoteAnimNames[0]);
|
|
|
|
// Vehicle model names (LOD names). The helicopter is a compound ROI ("copter")
|
|
// with no standalone LOD; use its body part instead.
|
|
const char* const g_vehicleROINames[VEHICLE_COUNT] =
|
|
{"chtrbody", "jsuser", "dunebugy", "bike", "board", "moto", "towtk", "ambul"};
|
|
|
|
// Ride animation names for small vehicles (NULL = large vehicle, no ride anim)
|
|
const char* const g_rideAnimNames[VEHICLE_COUNT] =
|
|
{NULL, NULL, NULL, "CNs001Bd", "CNs001sk", "CNs011Ni", NULL, NULL};
|
|
|
|
// Vehicle variant ROI names used in ride animations
|
|
const char* const g_rideVehicleROINames[VEHICLE_COUNT] =
|
|
{NULL, NULL, NULL, "bikebd", "board", "motoni", NULL, NULL};
|
|
|
|
bool IsLargeVehicle(int8_t p_vehicleType)
|
|
{
|
|
return p_vehicleType != VEHICLE_NONE && p_vehicleType < VEHICLE_COUNT && g_rideAnimNames[p_vehicleType] == NULL;
|
|
}
|
|
|
|
int8_t DetectVehicleType(LegoPathActor* p_actor)
|
|
{
|
|
static const struct {
|
|
const char* className;
|
|
int8_t vehicleType;
|
|
} vehicleMap[] = {
|
|
{"Helicopter", VEHICLE_HELICOPTER},
|
|
{"Jetski", VEHICLE_JETSKI},
|
|
{"DuneBuggy", VEHICLE_DUNEBUGGY},
|
|
{"Bike", VEHICLE_BIKE},
|
|
{"SkateBoard", VEHICLE_SKATEBOARD},
|
|
{"Motorcycle", VEHICLE_MOTOCYCLE},
|
|
{"TowTrack", VEHICLE_TOWTRACK},
|
|
{"Ambulance", VEHICLE_AMBULANCE},
|
|
};
|
|
|
|
if (!p_actor) {
|
|
return VEHICLE_NONE;
|
|
}
|
|
|
|
for (const auto& entry : vehicleMap) {
|
|
if (p_actor->IsA(entry.className)) {
|
|
return entry.vehicleType;
|
|
}
|
|
}
|
|
return VEHICLE_NONE;
|
|
}
|
|
|
|
} // namespace Multiplayer
|