diff --git a/Source/Client/Replay.h b/Source/Client/Replay.h index eaa767c..608ef60 100644 --- a/Source/Client/Replay.h +++ b/Source/Client/Replay.h @@ -99,6 +99,8 @@ public: bool WriteSection(int id, std::vector& bytes, int event); int WriteHeader(int event); std::vector BuildMetadata(); + float AnimationScale() const; + bool SetState(int state); }; extern int g_replayAnimationScaling; diff --git a/Source/Client/ReplayControl.cpp b/Source/Client/ReplayControl.cpp new file mode 100644 index 0000000..aaf3272 --- /dev/null +++ b/Source/Client/ReplayControl.cpp @@ -0,0 +1,53 @@ +#include "Client/Replay.h" + +// OFFSET: 0x00B844C0 +// FUNCTION: fn_19316 +float Replay::AnimationScale() const { + if (this->speed == 0.25f) { + return 1.4f; + } + if (this->speed == 0.5f) { + return 1.2f; + } + if (this->speed == 1.0f) { + return 1.0f; + } + if (this->speed == 2.0f) { + return 0.8f; + } + if (this->speed == 4.0f) { + return 0.6f; + } + if (this->speed == 8.0f) { + return 0.4f; + } + if (this->speed == 16.0f) { + return 0.2f; + } + return 1.0f; +} + +// OFFSET: 0x00B872F0 +// FUNCTION: fn_19343 +bool Replay::SetState(int state) { + if (state == 4) { + this->state = 1; + return true; + } + if (state == 5) { + this->state = 6; + return true; + } + if (state >= 1 && state <= 8) { + this->state = state; + if (state <= 3) { + g_replayAnimationScaling = 0; + } + } else { + this->state = 1; + } + if (state >= 6 && state <= 8) { + g_replayAnimationScaling = 1; + } + return true; +} diff --git a/Source/Contents/Actors/RenderObject.cpp b/Source/Contents/Actors/RenderObject.cpp index 428efc1..94ed981 100644 --- a/Source/Contents/Actors/RenderObject.cpp +++ b/Source/Contents/Actors/RenderObject.cpp @@ -1,7 +1,12 @@ #include "Contents/Actors/RenderObject.h" +#include "Client/Replay.h" +#include "Resource/Sprites/ActionResource.h" #include "Utility/Math/ScalarConversion.h" +#include +#include + // OFFSET: 0x00CA8730 // FUNCTION: fn_20991 CRenderObject::CRenderObject(ResourceMgr& resources, JobNames& names) : render(resources, names) { @@ -33,3 +38,136 @@ void CRenderObject::SetScreenPosition(float x, float y) { this->render.screenX = TruncateToInt(x); this->render.screenY = TruncateToInt(y); } + +// OFFSET: 0x00CBFAE0 +// FUNCTION: fn_21118 +void CRenderObject::SetAnimation(unsigned animation, int, int repeat) { + float speed = this->render.action->Speed(animation); + if (g_replayAnimationScaling != 0) { + speed *= Replay::Instance().AnimationScale(); + } + if (speed > 0.0f) { + this->render.speed = speed; + } + if (this->render.speed < 1.0f) { + if (g_replayAnimationScaling != 0) { + speed = Replay::Instance().AnimationScale(); + if (speed > 0.0f) { + this->render.speed = speed; + } + } else { + this->render.speed = 1.0f; + } + } + speed = this->render.speed * this->render.unknown_0064; + if (g_replayAnimationScaling != 0) { + speed *= Replay::Instance().AnimationScale(); + } + if (speed > 0.0f) { + this->render.speed = speed; + } + + this->render.animation = animation; + this->render.previousAnimation = animation; + this->render.unknown_003C = 0; + this->render.unknown_006C = repeat; + this->render.unknown_009C[1] = 0; + this->render.unknown_0060 = 1.0f; + this->render.unknown_0064 = 1.0f; + this->render.unknown_00C8 = 0; + this->render.unknown_00D8 = 0; + this->render.unknown_00DC = 0; +} + +// OFFSET: 0x00CBFC00 +// FUNCTION: fn_21119 +void CRenderObject::SetColor(int alpha, int red, int green, int blue) { + if (alpha != -1) { + this->render.color = (this->render.color & 0x00FFFFFFu) | (static_cast(alpha) << 24); + } + if (red != -1) { + this->render.color = (this->render.color & 0xFF00FFFFu) | ((static_cast(red) & 0xFFu) << 16); + } + if (green != -1) { + this->render.color = (this->render.color & 0xFFFF00FFu) | ((static_cast(green) & 0xFFu) << 8); + } + if (blue != -1) { + this->render.color = (this->render.color & 0xFFFFFF00u) | static_cast(blue); + } +} + +// OFFSET: 0x00CC1E70 +// FUNCTION: fn_21130 +void CRenderObject::SetSequenceDeadline(std::uint32_t duration) { + this->render.sequenceDeadline = timeGetTime() + duration; +} + +// OFFSET: 0x00CC1E90 +// FUNCTION: fn_21131 +void CRenderObject::SetSequenceInterval(unsigned char interval) { + this->render.unknown_00C2 = interval; +} + +// OFFSET: 0x00CC1EA0 +// FUNCTION: fn_21132 +void CRenderObject::SetAnimationSequence( + unsigned char animation0, unsigned char frame0, unsigned char animation1, unsigned char frame1, + unsigned char animation2, unsigned char frame2, unsigned char animation3, unsigned char frame3, + unsigned char animation4, unsigned char frame4, int timed, std::uint32_t duration, int loop +) { + this->render.sequenceAnimations[0] = animation0; + this->render.sequenceFrames[0] = frame0; + this->render.sequenceAnimations[1] = animation1; + this->render.sequenceFrames[1] = frame1; + this->render.sequenceAnimations[2] = animation2; + this->render.sequenceFrames[2] = frame2; + this->render.sequenceAnimations[3] = animation3; + this->render.sequenceFrames[3] = frame3; + this->render.sequenceAnimations[4] = animation4; + this->render.sequenceFrames[4] = frame4; + this->render.sequenceAnimation = animation0; + this->render.sequenceFrame = frame0; + this->render.sequenceIndex = 0; + this->render.sequenceLast = 4; + this->render.sequenceLoop = loop; + this->render.sequenceTimed = timed; + this->render.sequenceFinished = 0; + this->render.unknown_00D8 = 1; + this->render.unknown_00C8 = 0; + this->render.unknown_00DC = 0; + this->render.sequenceDeadline = timed != 0 ? timeGetTime() + duration : 0; + this->render.sequenceTick = 1; +} + +// OFFSET: 0x00CC1FA0 +// FUNCTION: fn_21133 +void CRenderObject::SetFrameSequence( + unsigned char animation, unsigned char firstFrame, unsigned char lastFrame, unsigned char finishAnimation, + unsigned char finishFrame, int timed, std::uint32_t duration, int loop +) { + this->render.sequenceAnimation = animation; + this->render.sequenceFrame = firstFrame; + this->render.sequenceIndex = firstFrame; + this->render.sequenceLast = lastFrame; + this->render.sequenceFinishAnimation = finishAnimation; + this->render.sequenceFinishFrame = finishFrame; + this->render.sequenceLoop = loop; + this->render.sequenceTimed = timed; + this->render.sequenceFinished = 0; + this->render.unknown_00C8 = 1; + this->render.unknown_00DC = 0; + this->render.unknown_00D8 = 0; + this->render.sequenceDeadline = timed != 0 ? timeGetTime() + duration : 0; + this->render.sequenceTick = 1; +} + +// OFFSET: 0x00CC2780 +// FUNCTION: fn_21140 +void CRenderObject::SetAnimationSpeed(float speed) { + if (g_replayAnimationScaling != 0) { + speed *= Replay::Instance().AnimationScale(); + } + if (speed > 0.0f) { + this->render.speed = speed; + } +} diff --git a/Source/Contents/Actors/RenderObject.h b/Source/Contents/Actors/RenderObject.h index 604a97a..1836bd6 100644 --- a/Source/Contents/Actors/RenderObject.h +++ b/Source/Contents/Actors/RenderObject.h @@ -14,10 +14,24 @@ public: virtual void SetScreenBounds(const float* bounds, float x, float y); virtual void SetScreenPosition(float x, float y); + virtual void SetAnimation(unsigned animation, int motion, int repeat); static float __stdcall Heading(float x, float z, float targetX, float targetZ); void Face(float x, float z); float HorizontalDistance(float x, float z) const; float Distance(float x, float y, float z) const; + void SetAnimationSpeed(float speed); + void SetColor(int alpha, int red, int green, int blue); + void SetSequenceDeadline(std::uint32_t duration); + void SetSequenceInterval(unsigned char interval); + void SetAnimationSequence( + unsigned char animation0, unsigned char frame0, unsigned char animation1, unsigned char frame1, + unsigned char animation2, unsigned char frame2, unsigned char animation3, unsigned char frame3, + unsigned char animation4, unsigned char frame4, int timed, std::uint32_t duration, int loop + ); + void SetFrameSequence( + unsigned char animation, unsigned char firstFrame, unsigned char lastFrame, unsigned char finishAnimation, + unsigned char finishFrame, int timed, std::uint32_t duration, int loop + ); RenderObjectState render; }; diff --git a/Source/Contents/Actors/RenderObjectState.h b/Source/Contents/Actors/RenderObjectState.h index 9d5096d..5a15614 100644 --- a/Source/Contents/Actors/RenderObjectState.h +++ b/Source/Contents/Actors/RenderObjectState.h @@ -3,6 +3,7 @@ #include "Contents/InstantVar.h" +#include #include #include @@ -57,14 +58,24 @@ struct RenderObjectState { /* 00AC */ int screenX; /* 00B0 */ int screenY; /* 00B4 */ unsigned char unknown_00B4; - /* 00B5 */ unsigned char unknown_00B5[13]; + /* 00B5 */ unsigned char sequenceAnimation; + /* 00B6 */ unsigned char sequenceFrame; + /* 00B7 */ unsigned char sequenceAnimations[5]; + /* 00BC */ unsigned char sequenceFrames[5]; + /* 00C1 */ unsigned char sequenceLast; /* 00C2 */ unsigned char unknown_00C2; - /* 00C3 */ unsigned char unknown_00C3[5]; + /* 00C3 */ unsigned char sequenceFinishAnimation; + /* 00C4 */ unsigned char sequenceFinishFrame; + /* 00C5 */ unsigned char sequenceIndex; + /* 00C6 */ unsigned char unknown_00C6[2]; /* 00C8 */ std::uint32_t unknown_00C8; - /* 00CC */ unsigned char unknown_00CC[12]; + /* 00CC */ int sequenceLoop; + /* 00D0 */ int sequenceTimed; + /* 00D4 */ int sequenceFinished; /* 00D8 */ std::uint32_t unknown_00D8; /* 00DC */ std::uint32_t unknown_00DC; - /* 00E0 */ unsigned char unknown_00E0[8]; + /* 00E0 */ std::uint32_t sequenceTick; + /* 00E4 */ std::uint32_t sequenceDeadline; /* 00E8 */ std::uint32_t flags; /* 00EC */ std::uint32_t unknown_00EC; /* 00F0 */ std::uint16_t unknown_00F0; @@ -94,6 +105,12 @@ struct RenderObjectState { #if defined(_WIN32) && !defined(_WIN64) static_assert(sizeof(RenderObjectState) == 296); +static_assert(offsetof(RenderObjectState, sequenceAnimation) == 0xA5); +static_assert(offsetof(RenderObjectState, sequenceAnimations) == 0xA7); +static_assert(offsetof(RenderObjectState, sequenceFrames) == 0xAC); +static_assert(offsetof(RenderObjectState, sequenceFinishAnimation) == 0xB3); +static_assert(offsetof(RenderObjectState, sequenceLoop) == 0xBC); +static_assert(offsetof(RenderObjectState, sequenceDeadline) == 0xD4); #endif #endif diff --git a/compile.json b/compile.json index 92a6999..899d014 100644 --- a/compile.json +++ b/compile.json @@ -262,6 +262,7 @@ "Source/Client/ModeFadeOut.cpp": 0, "Source/Client/Registry.cpp": 0, "Source/Client/Replay.cpp": 0, + "Source/Client/ReplayControl.cpp": 0, "Source/Client/ReplayPacketRecorder.cpp": 2, "Source/Client/Session.cpp": 0, "Source/Contents/ActorGeometry.cpp": 4,