mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-05-01 18:13:57 +00:00
* WIP: Add animation completion protocol message for Nick Brick's Memories Add MSG_ANIM_COMPLETE (15) protocol message broadcast by the host on natural animation completion. Contains a 64-bit random event ID, the SI object ID, and per-participant data (charIndex, displayName). - BroadcastAnimComplete: gathers participants from session slots, resolves spectator characters from display actors, generates event ID - HandleAnimComplete: filters observers (only participants get callback), builds JSON with eventId/objectId/participants for frontend - OnAnimationCompleted callback in PlatformCallbacks, implemented for Emscripten (CustomEvent dispatch) and Native (SDL_Log) - GetDisplayName() getter on RemotePlayer Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix participant ordering in animation completion message Emit the local player first in the JSON participants array so the frontend can rely on participants[0] being self when reporting to the server. Extract participant JSON-building into a lambda to avoid duplication. Retain null-termination safety for displayName. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Disable workers.dev and preview URLs for relay server Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix path actor assertion failure / freeze on repeated vehicle enter/exit When the third-person camera is active, LMB triggers both forward movement and vehicle interaction. This leaves the previous actor with m_worldSpeed > 0 when entering a vehicle, causing it to wander on the path system in non-user-nav mode. On exit, SetBoundary() overwrites m_boundary without updating m_destEdge, creating a boundary/edge mismatch. On the next vehicle enter, the stale spline finishes and SwitchBoundary asserts (debug) or loops infinitely (release). Stop the previous actor from wandering by zeroing its world speed on enter. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add hold threshold to disambiguate LMB click from hold-to-walk A 300ms time threshold prevents brief clicks (for interacting with world objects) from also triggering forward movement in third-person camera mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add missing SDL_timer.h include for SDL_GetTicks Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Remove maxActors setting from multiplayer — NPCs are always disabled The maxActors room setting added unnecessary complexity for a feature that should always be off in multiplayer. Remove it from the relay server protocol, room configuration API, C++ client, and simplify NPC enforcement to be unconditional. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
151 lines
4.1 KiB
C++
151 lines
4.1 KiB
C++
#ifndef ISLEPATHACTOR_H
|
|
#define ISLEPATHACTOR_H
|
|
|
|
#include "extensions/fwd.h"
|
|
#include "legogamestate.h"
|
|
#include "legopathactor.h"
|
|
#include "mxtypes.h"
|
|
#include "roi/legoroi.h"
|
|
|
|
class LegoControlManagerNotificationParam;
|
|
class LegoEndAnimNotificationParam;
|
|
class LegoWorld;
|
|
class LegoPathStructNotificationParam;
|
|
|
|
// VTABLE: LEGO1 0x100d4398
|
|
// VTABLE: BETA10 0x101b9090
|
|
// SIZE 0x160
|
|
class IslePathActor : public LegoPathActor {
|
|
public:
|
|
enum {
|
|
c_LOCATIONS_NUM = 29
|
|
};
|
|
|
|
enum {
|
|
c_spawnBit1 = 0x01,
|
|
c_playMusic = 0x02,
|
|
c_spawnBit3 = 0x04
|
|
};
|
|
|
|
// SIZE 0x38
|
|
struct SpawnLocation {
|
|
// FUNCTION: LEGO1 0x1001a6f0
|
|
SpawnLocation() {}
|
|
|
|
// FUNCTION: LEGO1 0x1001b1b0
|
|
SpawnLocation(
|
|
LegoGameState::Area p_area,
|
|
MxAtomId* p_script,
|
|
MxS32 p_entityId,
|
|
const char* p_name,
|
|
MxS16 p_src,
|
|
float p_srcScale,
|
|
MxS16 p_dest,
|
|
float p_destScale,
|
|
MxU32 p_location,
|
|
JukeboxScript::Script p_music
|
|
)
|
|
{
|
|
m_area = p_area;
|
|
m_script = p_script;
|
|
m_entityId = p_entityId;
|
|
strcpy(m_name, p_name);
|
|
m_src = p_src;
|
|
m_srcScale = p_srcScale;
|
|
m_dest = p_dest;
|
|
m_destScale = p_destScale;
|
|
m_location = p_location;
|
|
m_music = p_music;
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x1001b230
|
|
SpawnLocation& operator=(const SpawnLocation& p_location)
|
|
{
|
|
m_area = p_location.m_area;
|
|
m_script = p_location.m_script;
|
|
m_entityId = p_location.m_entityId;
|
|
strcpy(m_name, p_location.m_name);
|
|
m_src = p_location.m_src;
|
|
m_srcScale = p_location.m_srcScale;
|
|
m_dest = p_location.m_dest;
|
|
m_destScale = p_location.m_destScale;
|
|
m_location = p_location.m_location;
|
|
m_music = p_location.m_music;
|
|
return *this;
|
|
}
|
|
|
|
LegoGameState::Area m_area; // 0x00
|
|
MxAtomId* m_script; // 0x04
|
|
MxS32 m_entityId; // 0x08
|
|
char m_name[20]; // 0x0c
|
|
MxS16 m_src; // 0x20
|
|
float m_srcScale; // 0x24
|
|
MxS16 m_dest; // 0x28
|
|
float m_destScale; // 0x2c
|
|
MxU32 m_location; // 0x30
|
|
JukeboxScript::Script m_music; // 0x34
|
|
};
|
|
|
|
IslePathActor();
|
|
|
|
// FUNCTION: LEGO1 0x10002e70
|
|
virtual MxLong HandleClick() { return 0; } // vtable+0xcc
|
|
|
|
// FUNCTION: LEGO1 0x10002df0
|
|
virtual MxLong HandleNotification0() { return 0; } // vtable+0xd0
|
|
|
|
// FUNCTION: LEGO1 0x10002e80
|
|
virtual MxLong HandleControl(LegoControlManagerNotificationParam&) { return 0; } // vtable+0xd4
|
|
|
|
// FUNCTION: LEGO1 0x10002e90
|
|
virtual MxLong HandleEndAnim(LegoEndAnimNotificationParam&) { return 0; } // vtable+0xd8
|
|
|
|
// FUNCTION: LEGO1 0x10002e00
|
|
virtual MxLong HandlePathStruct(LegoPathStructNotificationParam&) { return 0; } // vtable+0xdc
|
|
|
|
virtual void Enter(); // vtable+0xe0
|
|
virtual void Exit(); // vtable+0xe4
|
|
virtual void SpawnPlayer(LegoGameState::Area p_area, MxBool p_enter, MxU8 p_flags); // vtable+0xe8
|
|
virtual void UpdateWorld(MxMatrix p_transform, LegoPathBoundary* p_boundary, MxBool p_reset); // vtable+0xec
|
|
|
|
// FUNCTION: LEGO1 0x10002e10
|
|
~IslePathActor() override { IslePathActor::Destroy(TRUE); }
|
|
|
|
MxLong Notify(MxParam& p_param) override; // vtable+0x04
|
|
|
|
// FUNCTION: LEGO1 0x10002ea0
|
|
// FUNCTION: BETA10 0x10023fa0
|
|
const char* ClassName() const override // vtable+0x0c
|
|
{
|
|
// STRING: LEGO1 0x100f0104
|
|
return "IslePathActor";
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10002eb0
|
|
MxBool IsA(const char* p_name) const override // vtable+0x10
|
|
{
|
|
return !strcmp(p_name, IslePathActor::ClassName()) || LegoPathActor::IsA(p_name);
|
|
}
|
|
|
|
MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18
|
|
void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c
|
|
|
|
void TurnAround();
|
|
|
|
void SetWorld(LegoWorld* p_world) { m_world = p_world; }
|
|
|
|
static void RegisterSpawnLocations();
|
|
|
|
// SYNTHETIC: LEGO1 0x10002ff0
|
|
// IslePathActor::`scalar deleting destructor'
|
|
|
|
protected:
|
|
friend class Extensions::ThirdPersonCamera::Controller;
|
|
|
|
LegoWorld* m_world; // 0x154
|
|
LegoPathActor* m_previousActor; // 0x158
|
|
MxFloat m_previousVel; // 0x15c
|
|
};
|
|
|
|
#endif // ISLEPATHACTOR_H
|