Switched to CFreeCamera instead of CReplayFreeCamera

This commit is contained in:
Hyper 2025-02-18 01:59:26 +00:00
parent 0aa1a256dd
commit 5f32e2495f
29 changed files with 484 additions and 195 deletions

View file

@ -21,3 +21,5 @@ namespace Hedgehog::Base
void operator delete(void* in_pMem, void* in_pObj);
};
}
#include "hhObject.inl"

View file

@ -0,0 +1,39 @@
namespace Hedgehog::Base
{
inline CObject::CObject()
{
}
inline CObject::CObject(const swa_null_ctor&)
{
}
inline void* CObject::operator new(const size_t in_Size)
{
return __HH_ALLOC(in_Size);
}
// inline void* CObject::operator new(const size_t in_Size, const size_t in_Align)
// {
// return __HH_ALLOCALIGN(in_Size, in_Align);
// }
inline void CObject::operator delete(void* in_pMem)
{
return __HH_FREE(in_pMem);
}
inline void* CObject::operator new(const size_t in_Size, void* in_pObj)
{
return in_pObj;
}
inline void* CObject::operator new(const size_t in_Size, const size_t in_Align, void* in_pObj)
{
return in_pObj;
}
inline void CObject::operator delete(void* in_pMem, void* in_pObj)
{
}
}

View file

@ -18,6 +18,16 @@ namespace Hedgehog::Math
be<float> Y;
be<float> Z;
be<float> W;
CVector operator*(const float& scalar) const
{
return { X * scalar, Y * scalar, Z * scalar };
}
CVector operator+(const CVector& v) const
{
return { X + v.X, Y + v.Y, Z + v.Z };
}
};
class CVector4

View file

@ -0,0 +1,19 @@
#pragma once
#include <SWA.inl>
#include <Hedgehog/Base/hhObject.h>
#include <boost/smart_ptr/shared_ptr.h>
namespace Hedgehog::Universe
{
class Message : public Base::CObject
{
public:
be<uint32_t> m_pVftable;
be<uint32_t> m_SenderActorID;
boost::shared_ptr<Message> m_spSelf;
};
class MessageTypeGet : public Message {};
class MessageTypeSet : public Message {};
}

View file

@ -49,6 +49,7 @@
#include "Hedgehog/MirageCore/RenderData/hhVertexShaderData.h"
#include "Hedgehog/MirageCore/Renderable/hhRenderable.h"
#include "Hedgehog/Sparkle/hhParticleMaterial.h"
#include "Hedgehog/Universe/Engine/hhMessage.h"
#include "Hedgehog/Universe/Engine/hhMessageActor.h"
#include "Hedgehog/Universe/Engine/hhMessageProcess.h"
#include "Hedgehog/Universe/Engine/hhStateMachineBase.h"
@ -65,7 +66,8 @@
#include "SWA/CSD/CsdTexListMirage.h"
#include "SWA/CSD/GameObjectCSD.h"
#include "SWA/Camera/Camera.h"
#include "SWA/Camera/CameraController.h"
#include "SWA/Camera/Controller/CameraController.h"
#include "SWA/Camera/Controller/FreeCamera.h"
#include "SWA/CharacterUtility/CharacterProxy.h"
#include "SWA/ExtraStage/Tails/Enemy/Boss/ExStageBoss.h"
#include "SWA/ExtraStage/Tails/Enemy/Boss/State/StateBase.h"
@ -87,13 +89,19 @@
#include "SWA/Inspire/InspireTextureOverlay.h"
#include "SWA/Inspire/InspireTextureOverlayInfo.h"
#include "SWA/Menu/MenuWindowBase.h"
#include "SWA/Message/MsgCameraPauseMove.h"
#include "SWA/Message/MsgPopCameraController.h"
#include "SWA/Message/MsgSetPosition.h"
#include "SWA/Message/MsgSetVelocity.h"
#include "SWA/Movie/MovieDisplayer.h"
#include "SWA/Movie/MovieManager.h"
#include "SWA/Object/Common/DashPanel/ObjDashPanel.h"
#include "SWA/Object/SonicStage/EU/RollingBarrel/ObjRollingBarrel.h"
#include "SWA/Player/Character/Base/PlayerContext.h"
#include "SWA/Player/Character/EvilSonic/EvilSonic.h"
#include "SWA/Player/Character/EvilSonic/EvilSonicContext.h"
#include "SWA/Player/Character/EvilSonic/Hud/EvilHudGuide.h"
#include "SWA/Player/Character/Speed/PlayerSpeedContext.h"
#include "SWA/Replay/Camera/ReplayFreeCamera.h"
#include "SWA/Sequence/Unit/SequenceUnitBase.h"
#include "SWA/Sequence/Unit/SequenceUnitPlayMovie.h"
@ -125,5 +133,6 @@
#include "SWA/System/MatrixNodeTransform.h"
#include "SWA/System/PadState.h"
#include "SWA/System/World.h"
#include "SWA/Tool/FreeCameraTool/FreeCameraTool.h"
#include "boost/smart_ptr/make_shared_object.h"
#include "boost/smart_ptr/shared_ptr.h"

View file

@ -1,17 +0,0 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CCameraController
{
public:
SWA_INSERT_PADDING(0x64);
be<float> m_FieldOfView;
SWA_INSERT_PADDING(0x68);
};
SWA_ASSERT_OFFSETOF(CCameraController, m_FieldOfView, 0x64);
SWA_ASSERT_SIZEOF(CCameraController, 0xD0);
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CCameraController
{
public:
SWA_INSERT_PADDING(0x08);
xpointer<CCamera> m_pCamera;
SWA_INSERT_PADDING(0x58);
be<float> m_FieldOfView;
SWA_INSERT_PADDING(0x08);
Hedgehog::Math::CVector m_Position;
Hedgehog::Math::CVector m_UpVector;
Hedgehog::Math::CQuaternion m_Rotation;
SWA_INSERT_PADDING(0x30);
};
SWA_ASSERT_OFFSETOF(CCameraController, m_pCamera, 0x08);
SWA_ASSERT_OFFSETOF(CCameraController, m_FieldOfView, 0x64);
SWA_ASSERT_SIZEOF(CCameraController, 0xD0);
}

View file

@ -0,0 +1,16 @@
#pragma once
#include <SWA.inl>
#include "SWA/Camera/Controller/CameraController.h"
namespace SWA
{
class CFreeCamera : public CCameraController
{
public:
SWA_INSERT_PADDING(0x10);
be<float> m_Speed;
};
SWA_ASSERT_OFFSETOF(CFreeCamera, m_Speed, 0xE0);
}

View file

@ -9,6 +9,9 @@ namespace SWA
// ms_DrawLightFieldSamplingPoint: サンプリング点をデバッグ表示
static inline bool* ms_DrawLightFieldSamplingPoint;
// N/A
static inline be<float>* ms_FreeCameraSpeed;
// N/A
static inline bool* ms_IsAutoSaveWarningShown;
@ -60,6 +63,7 @@ namespace SWA
static void Init()
{
ms_DrawLightFieldSamplingPoint = (bool*)MmGetHostAddress(0x83367BCE);
ms_FreeCameraSpeed = (be<float>*)MmGetHostAddress(0x83366DF8);
ms_IgnoreLightFieldData = (bool*)MmGetHostAddress(0x83367BCF);
ms_IsAutoSaveWarningShown = (bool*)MmGetHostAddress(0x83367BC1);
ms_IsCollisionRender = (bool*)MmGetHostAddress(0x833678A6);

View file

@ -0,0 +1,17 @@
#pragma once
#include <SWA.inl>
namespace SWA::Message
{
class MsgCameraPauseMove : public Hedgehog::Universe::MessageTypeSet
{
public:
SWA_INSERT_PADDING(0x08);
bool m_isPaused;
MsgCameraPauseMove(bool in_isPaused) : m_isPaused(in_isPaused) {}
};
SWA_ASSERT_OFFSETOF(MsgCameraPauseMove, m_isPaused, 0x18);
}

View file

@ -0,0 +1,32 @@
#pragma once
#include <SWA.inl>
namespace SWA::Message
{
class MsgPopCameraController : public Hedgehog::Universe::MessageTypeSet
{
public:
SWA_INSERT_PADDING(0x08);
xpointer<CCameraController> m_pCameraController;
SWA_INSERT_PADDING(0x08);
xpointer<Hedgehog::Base::CSharedString> m_pCameraName;
be<float> m_InterpolateTime;
bool m_Field2C;
bool m_Field2D;
bool m_Field2E;
MsgPopCameraController(CCameraController* in_pCameraController, float in_interpolateTime)
: m_pCameraController(in_pCameraController), m_InterpolateTime(in_interpolateTime) {}
MsgPopCameraController(Hedgehog::Base::CSharedString* in_pCameraName, float in_interpolateTime)
: m_pCameraName(in_pCameraName), m_InterpolateTime(in_interpolateTime) {}
};
SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_pCameraController, 0x18);
SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_pCameraName, 0x24);
SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_InterpolateTime, 0x28);
SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_Field2C, 0x2C);
SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_Field2D, 0x2D);
SWA_ASSERT_OFFSETOF(MsgPopCameraController, m_Field2E, 0x2E);
}

View file

@ -0,0 +1,18 @@
#pragma once
#include <SWA.inl>
namespace SWA::Message
{
class MsgSetPosition : public Hedgehog::Universe::MessageTypeSet
{
public:
SWA_INSERT_PADDING(0x10);
Hedgehog::Math::CVector m_Position;
MsgSetPosition(const Hedgehog::Math::CVector& in_rPosition) : m_Position(in_rPosition) {}
};
SWA_ASSERT_OFFSETOF(MsgSetPosition, m_Position, 0x20);
SWA_ASSERT_SIZEOF(MsgSetPosition, 0x30);
}

View file

@ -0,0 +1,18 @@
#pragma once
#include <SWA.inl>
namespace SWA::Message
{
class MsgSetVelocity : public Hedgehog::Universe::MessageTypeSet
{
public:
SWA_INSERT_PADDING(0x10);
Hedgehog::Math::CVector m_Velocity;
MsgSetVelocity(const Hedgehog::Math::CVector& in_rVelocity) : m_Velocity(in_rVelocity) {}
};
SWA_ASSERT_OFFSETOF(MsgSetVelocity, m_Velocity, 0x20);
SWA_ASSERT_SIZEOF(MsgSetVelocity, 0x30);
}

View file

@ -0,0 +1,29 @@
#pragma once
#include <SWA.inl>
#include "boost/smart_ptr/shared_ptr.h"
namespace SWA::Player
{
class CPlayer;
class CPlayerContext
{
public:
SWA_INSERT_PADDING(0x10);
boost::shared_ptr<CMatrixNodeTransform> m_spMatrixNode;
SWA_INSERT_PADDING(0x18);
boost::anonymous_shared_ptr m_spRayCastCollision;
SWA_INSERT_PADDING(0xC8);
xpointer<CPlayer> m_pPlayer;
SWA_INSERT_PADDING(0xF8);
boost::shared_ptr<void> m_spParameter;
SWA_INSERT_PADDING(0x0C);
};
SWA_ASSERT_OFFSETOF(CPlayerContext, m_spMatrixNode, 0x10);
SWA_ASSERT_OFFSETOF(CPlayerContext, m_spRayCastCollision, 0x30);
SWA_ASSERT_OFFSETOF(CPlayerContext, m_pPlayer, 0x100);
SWA_ASSERT_OFFSETOF(CPlayerContext, m_spParameter, 0x1FC);
SWA_ASSERT_SIZEOF(CPlayerContext, 0x210);
}

View file

@ -5,19 +5,26 @@
namespace SWA::Player
{
class CEvilSonicContext // : public CPlayerContext
class CEvilSonicContext : public CPlayerContext
{
public:
SWA_INSERT_PADDING(0x688);
SWA_INSERT_PADDING(0x478);
be<float> m_DarkGaiaEnergy;
SWA_INSERT_PADDING(0x138);
be<uint32_t> m_AnimationID;
SWA_INSERT_PADDING(0x38);
be<float> m_UnkHudGuideF32;
be<uint32_t> m_UnkHudGuideU32;
be<float> m_Field800; // Related to EvilHudGuide
be<uint32_t> m_Field804; // Related to EvilHudGuide
SWA_INSERT_PADDING(0x18);
be<EGuideType> m_GuideType;
SWA_INSERT_PADDING(0xA8);
be<uint32_t> m_OutOfControlCount;
};
SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_DarkGaiaEnergy, 0x688);
SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_AnimationID, 0x7C4);
SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_Field800, 0x800);
SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_Field804, 0x804);
SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_GuideType, 0x820);
SWA_ASSERT_OFFSETOF(CEvilSonicContext, m_OutOfControlCount, 0x8CC);
}

View file

@ -0,0 +1,15 @@
#pragma once
#include <SWA.inl>
namespace SWA::Player
{
class CPlayerSpeedContext : public CPlayerContext
{
public:
// TODO: Hedgehog::Base::TSynchronizedPtr<CGameDocument>
static CPlayerSpeedContext* GetInstance();
};
}
#include "PlayerSpeedContext.inl"

View file

@ -0,0 +1,7 @@
namespace SWA::Player
{
inline CPlayerSpeedContext* CPlayerSpeedContext::GetInstance()
{
return *(xpointer<CPlayerSpeedContext>*)MmGetHostAddress(0x83362F98);
}
}

View file

@ -1,7 +1,7 @@
#pragma once
#include <SWA.inl>
#include "SWA/Camera/CameraController.h"
#include "SWA/Camera/Controller/CameraController.h"
namespace SWA
{

View file

@ -36,7 +36,9 @@ namespace SWA
xpointer<CSoundAdministrator> m_pSoundAdministrator;
SWA_INSERT_PADDING(0x48);
xpointer<CGeneralWindow> m_pGeneralWindow;
SWA_INSERT_PADDING(0xD8);
SWA_INSERT_PADDING(0xC0);
boost::anonymous_shared_ptr m_spPlayerSwitchManager;
SWA_INSERT_PADDING(0x10);
SScoreInfo m_ScoreInfo;
SWA_INSERT_PADDING(0x0C);
};
@ -63,6 +65,7 @@ namespace SWA
SWA_ASSERT_OFFSETOF(CGameDocument::CMember, m_StageName, 0xAC);
SWA_ASSERT_OFFSETOF(CGameDocument::CMember, m_pSoundAdministrator, 0xB0);
SWA_ASSERT_OFFSETOF(CGameDocument::CMember, m_pGeneralWindow, 0xFC);
SWA_ASSERT_OFFSETOF(CGameDocument::CMember, m_spPlayerSwitchManager, 0x1C0);
SWA_ASSERT_OFFSETOF(CGameDocument::CMember, m_ScoreInfo, 0x1D8);
SWA_ASSERT_SIZEOF(CGameDocument::CMember, 0x230);

View file

@ -0,0 +1,15 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CFreeCameraTool : public CGameObject
{
public:
SWA_INSERT_PADDING(0x04);
xpointer<CFreeCamera> m_pFreeCamera;
};
SWA_ASSERT_OFFSETOF(CFreeCameraTool, m_pFreeCamera, 0xC0);
}

View file

@ -5,6 +5,7 @@
#include <kernel/function.h>
#include <os/process.h>
#include <patches/audio_patches.h>
#include <patches/free_camera_patches.h>
#include <patches/inspire_patches.h>
#include <ui/game_window.h>
#include <user/config.h>
@ -73,6 +74,7 @@ PPC_FUNC(sub_822C1130)
}
AudioPatches::Update(App::s_deltaTime);
FreeCameraPatches::Update();
InspirePatches::Update();
// Apply subtitles option.
@ -94,3 +96,11 @@ PPC_FUNC(sub_822C1130)
__imp__sub_822C1130(ctx, base);
}
// SWA::CGameModeStage::CGameModeStage
PPC_FUNC_IMPL(__imp__sub_82541138);
PPC_FUNC(sub_82541138)
{
App::s_pGameModeStage = (SWA::CGameModeStage*)g_memory.Translate(ctx.r3.u32);
__imp__sub_82541138(ctx, base);
}

View file

@ -1,5 +1,6 @@
#pragma once
#include <api/SWA.h>
#include <user/config.h>
class App
@ -8,9 +9,11 @@ public:
static inline bool s_isInit;
static inline bool s_isMissingDLC;
static inline bool s_isLoading;
static inline bool s_isWerehog;
static inline bool s_isSaveDataCorrupt;
static inline SWA::CGameModeStage* s_pGameModeStage;
static inline SWA::Player::CEvilSonicContext* s_pEvilSonicContext;
static inline ELanguage s_language;
static inline double s_deltaTime;

View file

@ -210,7 +210,7 @@ int HID_OnSDLEvent(void*, SDL_Event* event)
g_controllers[freeIndex] = controller;
SetControllerTimeOfDayLED(controller, App::s_isWerehog);
SetControllerTimeOfDayLED(controller, App::s_pEvilSonicContext);
}
break;

View file

@ -8,19 +8,20 @@
#define DEGREES_TO_RADIANS(x) (float)(x / 180.0f * M_PI)
#define RADIANS_TO_DEGREES(x) (float)(x / M_PI * 180.0f)
constexpr float DEFAULT_SPEED = 0.5f;
constexpr float DEFAULT_FOV = 45.0f;
constexpr float DEFAULT_SPEED = 1.0f;
constexpr float DEFAULT_FIELD_OF_VIEW = 45.0f;
constexpr float MOVE_SPEED_SLOW = 0.075f;
constexpr float MOVE_SPEED_FAST = 8.0f;
constexpr float MOVE_SPEED_MODIFIER_RATIO = 0.02f;
constexpr float FOV_MODIFIER_RATIO = 1.0f;
static float g_baseSpeed = DEFAULT_SPEED;
static float g_baseFOV = DEFAULT_FOV;
static float g_baseFieldOfView = DEFAULT_FIELD_OF_VIEW;
static bool g_isDisablingFreeCamera;
static bool g_isCameraLocked;
static float g_speed;
static float g_fov;
static float g_fieldOfView;
static void ResetParameters()
{
@ -28,90 +29,22 @@ static void ResetParameters()
g_speed = g_baseSpeed = DEFAULT_SPEED;
*SWA::SGlobals::ms_IsRenderDepthOfField = true;
FreeCameraPatches::s_fieldOfView = g_fov = g_baseFOV = DEFAULT_FOV;
FreeCameraPatches::s_fieldOfView = g_fieldOfView = g_baseFieldOfView = DEFAULT_FIELD_OF_VIEW;
}
bool EnableFreeCameraMidAsmHook()
bool FreeCameraActiveMidAsmHook()
{
return Config::EnableFreeCamera;
return Config::EnableFreeCamera && FreeCameraPatches::s_isActive;
}
bool FreeCameraNullInputMidAsmHook()
{
return Config::EnableFreeCamera;
}
// Original input: D-Pad Up
bool FreeCameraActivationInputMidAsmHook(PPCRegister& r11, PPCRegister& r27, PPCRegister& r28)
bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31, PPCRegister& r29, PPCRegister& f0)
{
if (!Config::EnableFreeCamera)
return false;
static auto isChangedCameraMode = false;
if ((r11.u32 & SWA::eKeyState_Select) != 0)
{
if (++r28.u32 >= 2)
r28.u32 = 0;
isChangedCameraMode = true;
}
FreeCameraPatches::s_isActive = r28.u32 > 0;
if (isChangedCameraMode)
{
ResetParameters();
switch (r28.u32)
{
case 0:
LOGN("[Free Camera] Disabled");
break;
case 1:
LOGN("[Free Camera] Enabled");
break;
}
isChangedCameraMode = false;
if (FreeCameraPatches::s_isActive && *SWA::SGlobals::ms_IsRenderHud)
{
*SWA::SGlobals::ms_IsRenderHud = false;
}
else
{
*SWA::SGlobals::ms_IsRenderHud = true;
}
}
return true;
}
// Original input: D-Pad Left
void FreeCameraTeleportToPlayerInputMidAsmHook(PPCRegister& r4)
{
if (Config::EnableFreeCamera)
r4.u32 = SWA::eKeyState_RightStick;
}
// Original inputs: X (Square) / Y (Triangle)
bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31)
{
if (!Config::EnableFreeCamera)
return false;
auto pCamera = (SWA::CReplayFreeCamera*)g_memory.Translate(r31.u32);
auto pInputState = SWA::CInputState::GetInstance();
if (!pInputState)
return false;
auto& rPadState = pInputState->GetPadState();
auto pCamera = (SWA::CFreeCamera*)g_memory.Translate(r31.u32);
auto pPadState = (SWA::SPadState*)g_memory.Translate(r29.u32);
auto factor = App::s_deltaTime / (1.0f / 60.0f);
auto aspectRatio = (float)GameWindow::s_width / (float)GameWindow::s_height;
if (g_isCameraLocked)
{
@ -122,7 +55,7 @@ bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31)
static auto isLeftTriggerSpeedModifier = false;
static auto isRightTriggerSpeedModifier = false;
if (rPadState.IsDown(SWA::eKeyState_LeftTrigger))
if (pPadState->IsDown(SWA::eKeyState_LeftTrigger))
{
g_speed = MOVE_SPEED_SLOW;
isLeftTriggerSpeedModifier = true;
@ -133,7 +66,7 @@ bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31)
isLeftTriggerSpeedModifier = false;
}
if (rPadState.IsDown(SWA::eKeyState_RightTrigger))
if (pPadState->IsDown(SWA::eKeyState_RightTrigger))
{
g_speed = MOVE_SPEED_FAST;
isRightTriggerSpeedModifier = true;
@ -147,10 +80,10 @@ bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31)
if (isLeftTriggerSpeedModifier && isRightTriggerSpeedModifier)
g_speed = MOVE_SPEED_FAST / 3;
if (rPadState.IsDown(SWA::eKeyState_A))
if (pPadState->IsDown(SWA::eKeyState_A))
g_speed = g_baseSpeed = DEFAULT_SPEED;
if (rPadState.IsDown(SWA::eKeyState_B))
if (pPadState->IsDown(SWA::eKeyState_B))
{
g_baseSpeed -= MOVE_SPEED_MODIFIER_RATIO * factor;
g_speed = g_baseSpeed;
@ -158,7 +91,7 @@ bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31)
LOGFN("[Free Camera] Speed: {}", g_speed);
}
if (rPadState.IsDown(SWA::eKeyState_X))
if (pPadState->IsDown(SWA::eKeyState_X))
{
g_baseSpeed += MOVE_SPEED_MODIFIER_RATIO * factor;
g_speed = g_baseSpeed;
@ -166,57 +99,152 @@ bool FreeCameraSpeedInputMidAsmHook(PPCRegister& r31)
LOGFN("[Free Camera] Speed: {}", g_speed);
}
auto isResetFOV = rPadState.IsDown(SWA::eKeyState_Y);
auto isIncreaseFOV = rPadState.IsDown(SWA::eKeyState_DpadUp);
auto isDecreaseFOV = rPadState.IsDown(SWA::eKeyState_DpadDown);
auto fovScaleFactor = 0.0f;
if (isIncreaseFOV)
{
fovScaleFactor = FOV_MODIFIER_RATIO;
}
else if (isDecreaseFOV)
{
fovScaleFactor = -FOV_MODIFIER_RATIO;
}
g_speed = std::clamp(g_speed, 0.01f, 20.0f);
g_fov = fmodf(isResetFOV ? DEFAULT_FOV : g_fov + fovScaleFactor * App::s_deltaTime * 60.0f, 180.0f);
}
if (rPadState.IsTapped(SWA::eKeyState_DpadLeft))
{
g_isCameraLocked = !g_isCameraLocked;
g_speed = g_baseSpeed;
if (g_isCameraLocked)
{
LOGN("[Free Camera] Locked");
}
else
{
LOGN("[Free Camera] Unlocked");
}
}
if (rPadState.IsTapped(SWA::eKeyState_DpadRight))
{
*SWA::SGlobals::ms_IsRenderDepthOfField = !*SWA::SGlobals::ms_IsRenderDepthOfField;
if (*SWA::SGlobals::ms_IsRenderDepthOfField)
{
LOGN("[Free Camera] Depth of Field ON");
}
else
{
LOGN("[Free Camera] Depth of Field OFF");
}
}
pCamera->m_Speed = g_speed;
FreeCameraPatches::s_fieldOfView = 2.0f * atan(tan(DEGREES_TO_RADIANS(g_fov / 2.0f) * (16.0f / 9.0f / std::min(aspectRatio, 16.0f / 9.0f))));
f0.f64 = g_speed;
return true;
}
// SWA::CFreeCamera::Update
PPC_FUNC_IMPL(__imp__sub_82472A18);
PPC_FUNC(sub_82472A18)
{
if (Config::EnableFreeCamera)
{
auto pCamera = (SWA::CFreeCamera*)g_memory.Translate(ctx.r3.u32);
auto aspectRatio = (float)GameWindow::s_width / (float)GameWindow::s_height;
if (auto pInputState = SWA::CInputState::GetInstance())
{
auto& rPadState = pInputState->GetPadState();
// Deactivate.
if (rPadState.IsTapped(SWA::eKeyState_Select))
{
guest_stack_var<SWA::Message::MsgPopCameraController> msgPopCameraController(pCamera, 0.0f);
guest_stack_var<SWA::Message::MsgCameraPauseMove> msgCameraPauseMove(false);
// Process SWA::Message::MsgPopCameraController.
GuestToHostFunction<int>(sub_8246A840, pCamera->m_pCamera.get(), msgPopCameraController.get());
// Process SWA::Message::MsgFinishFreeCamera.
GuestToHostFunction<int>(sub_8253ADB8, App::s_pGameModeStage);
// Process SWA::Message::MsgCameraPauseMove.
GuestToHostFunction<int>(sub_824679C0, pCamera->m_pCamera.get(), msgCameraPauseMove.get());
FreeCameraPatches::s_isActive = false;
*SWA::SGlobals::ms_IsRenderHud = true;
LOGN("[Free Camera] Disabled");
g_isDisablingFreeCamera = true;
return;
}
// Teleport player to camera.
if (rPadState.IsTapped(SWA::eKeyState_LeftStick))
{
guest_stack_var<SWA::Message::MsgSetPosition> msgSetPosition(pCamera->m_Position);
guest_stack_var<SWA::Message::MsgSetVelocity> msgSetVelocity(Hedgehog::Math::CVector(0.0f, 0.0f, 0.0f));
if (auto pPlayerSpeedContext = SWA::Player::CPlayerSpeedContext::GetInstance())
{
// Process SWA::Message::MsgSetPosition.
GuestToHostFunction<int>(sub_82303100, pPlayerSpeedContext->m_pPlayer.get(), msgSetPosition.get());
// Process SWA::Message::MsgSetVelocity.
GuestToHostFunction<int>(sub_82311820, pPlayerSpeedContext->m_pPlayer.get(), msgSetVelocity.get());
}
else if (App::s_pEvilSonicContext)
{
// Process SWA::Message::MsgSetPosition.
GuestToHostFunction<int>(sub_82303100, App::s_pEvilSonicContext->m_pPlayer.get(), msgSetPosition.get());
}
}
// Lock camera.
if (rPadState.IsTapped(SWA::eKeyState_DpadLeft))
{
g_isCameraLocked = !g_isCameraLocked;
if (g_isCameraLocked)
{
LOGN("[Free Camera] Locked");
}
else
{
g_speed = g_baseSpeed;
LOGN("[Free Camera] Unlocked");
}
}
// Toggle depth of field.
if (rPadState.IsTapped(SWA::eKeyState_DpadRight))
{
*SWA::SGlobals::ms_IsRenderDepthOfField = !*SWA::SGlobals::ms_IsRenderDepthOfField;
if (*SWA::SGlobals::ms_IsRenderDepthOfField)
{
LOGN("[Free Camera] Depth of Field ON");
}
else
{
LOGN("[Free Camera] Depth of Field OFF");
}
}
auto isResetFOV = rPadState.IsDown(SWA::eKeyState_Y);
auto isIncreaseFOV = rPadState.IsDown(SWA::eKeyState_DpadUp);
auto isDecreaseFOV = rPadState.IsDown(SWA::eKeyState_DpadDown);
auto fovScaleFactor = 0.0f;
if (isIncreaseFOV)
{
fovScaleFactor = FOV_MODIFIER_RATIO;
}
else if (isDecreaseFOV)
{
fovScaleFactor = -FOV_MODIFIER_RATIO;
}
g_fieldOfView = fmodf(isResetFOV ? DEFAULT_FIELD_OF_VIEW : g_fieldOfView + fovScaleFactor * App::s_deltaTime * 60.0f, 180.0f);
FreeCameraPatches::s_fieldOfView = 2.0f * atan(tan(DEGREES_TO_RADIANS(g_fieldOfView / 2.0f) * (16.0f / 9.0f / std::min(aspectRatio, 16.0f / 9.0f))));
}
}
__imp__sub_82472A18(ctx, base);
}
void FreeCameraPatches::Update()
{
if (!Config::EnableFreeCamera || !App::s_pGameModeStage)
return;
if (auto pInputState = SWA::CInputState::GetInstance())
{
auto& rPadState = pInputState->GetPadState();
if (rPadState.IsTapped(SWA::eKeyState_Select) && !FreeCameraPatches::s_isActive && !g_isDisablingFreeCamera)
{
ResetParameters();
// Process SWA::Message::MsgStartFreeCamera.
GuestToHostFunction<int>(sub_8253ACB8, App::s_pGameModeStage);
FreeCameraPatches::s_isActive = true;
*SWA::SGlobals::ms_IsRenderHud = false;
LOGN("[Free Camera] Enabled");
}
if (rPadState.IsReleased(SWA::eKeyState_Select) && !FreeCameraPatches::s_isActive)
g_isDisablingFreeCamera = false;
}
}

View file

@ -6,4 +6,6 @@ public:
static inline bool s_isActive;
static inline float s_fieldOfView;
static void Update();
};

View file

@ -57,7 +57,7 @@ PPC_FUNC(sub_82B98D30)
g_pScene = nullptr;
InspirePatches::s_sceneName.clear();
SDL_User_EvilSonic(App::s_isWerehog);
SDL_User_EvilSonic(App::s_pEvilSonicContext);
g_loadedMouthExplosionAnimation = false;
g_hideMorphModels = false;

View file

@ -104,9 +104,9 @@ void SetXButtonHomingMidAsmHook(PPCRegister& r30)
PPC_FUNC_IMPL(__imp__sub_823B49D8);
PPC_FUNC(sub_823B49D8)
{
__imp__sub_823B49D8(ctx, base);
App::s_pEvilSonicContext = (SWA::Player::CEvilSonicContext*)g_memory.Translate(ctx.r3.u32);
App::s_isWerehog = true;
__imp__sub_823B49D8(ctx, base);
SDL_User_EvilSonic(true);
}
@ -115,9 +115,9 @@ PPC_FUNC(sub_823B49D8)
PPC_FUNC_IMPL(__imp__sub_823B4590);
PPC_FUNC(sub_823B4590)
{
__imp__sub_823B4590(ctx, base);
App::s_pEvilSonicContext = nullptr;
App::s_isWerehog = false;
__imp__sub_823B4590(ctx, base);
SDL_User_EvilSonic(false);
}

View file

@ -20,7 +20,7 @@ PPC_FUNC(sub_824DCF38)
if (Config::TimeOfDayTransition == ETimeOfDayTransition::PlayStation)
{
ctx.r4.u32 = SWA::eLoadingDisplayType_ChangeTimeOfDay;
pLoading->m_IsNightToDay = App::s_isWerehog;
pLoading->m_IsNightToDay = App::s_pEvilSonicContext;
}
if (Config::UseArrowsForTimeOfDayTransition)

View file

@ -1087,41 +1087,20 @@ name = "AnimationDataMakeMidAsmHook"
address = 0x82BB38E4
registers = ["r31", "r29", "r28"]
[[midasm_hook]]
name = "EnableFreeCameraMidAsmHook"
address = 0x825389F0
jump_address_on_true = 0x825389F4
[[midasm_hook]]
name = "EnableFreeCameraMidAsmHook"
address = 0x82538A18
jump_address_on_true = 0x82538A1C
[[midasm_hook]]
name = "FreeCameraActivationInputMidAsmHook"
address = 0x824569BC
registers = ["r11", "r27", "r28"]
jump_address_on_true = 0x824569D4
[[midasm_hook]]
name = "FreeCameraTeleportToPlayerInputMidAsmHook"
address = 0x8245C21C
registers = ["r4"]
[[midasm_hook]]
name = "FreeCameraSpeedInputMidAsmHook"
address = 0x8245C318
registers = ["r31"]
jump_address_on_true = 0x8245C38C
address = 0x82472A7C
registers = ["r31", "r29", "f0"]
jump_address_on_true = 0x82472AC4
# Disable "change to free camera" input.
# Disable start/end tool input.
[[midasm_hook]]
name = "FreeCameraNullInputMidAsmHook"
address = 0x8245BCE4
jump_address_on_true = 0x8245BDB4
name = "FreeCameraActiveMidAsmHook"
address = 0x825D7690
jump_address_on_true = 0x825D7704
# Disable "change to pan camera" input.
# Disable deactivation input.
[[midasm_hook]]
name = "FreeCameraNullInputMidAsmHook"
address = 0x8245BDC4
jump_address_on_true = 0x8245BEAC
name = "FreeCameraActiveMidAsmHook"
address = 0x825D745C
jump_address_on_true = 0x825D768C