Skip to content

Commit

Permalink
Add initial free camera for Legend
Browse files Browse the repository at this point in the history
  • Loading branch information
TheIndra55 committed Jan 28, 2024
1 parent 0ad8d2e commit 32522e5
Show file tree
Hide file tree
Showing 8 changed files with 305 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "modules/ModLoader.h"
#include "modules/Patches.h"
#include "modules/Frontend.h"
#include "modules/camera/FreeCamera.h"

#include "cdc/render/PCDeviceManager.h"

Expand Down Expand Up @@ -127,6 +128,7 @@ void Hook::RegisterModules()
RegisterModule<Skew>();
RegisterModule<ModLoader>();
RegisterModule<Patches>();
RegisterModule<FreeCamera>();

#ifndef TR8
RegisterModule<LevelModule>();
Expand Down
14 changes: 14 additions & 0 deletions src/game/Camera.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "Camera.h"
#include "util/Hooking.h"

Camera* CAMERA_GetCamera()
{
return (Camera*)GET_ADDRESS(0x000000, 0x850670, 0x000000);
}

void CAMERA_CalcPosition(cdc::Vector3* position, cdc::Vector3* base, cdc::Euler* rotation, float distance)
{
auto addr = GET_ADDRESS(0x48D8B0, 0x491320, 0x000000);

Hooking::Call(addr, position, base, rotation, distance);
}
23 changes: 23 additions & 0 deletions src/game/Camera.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include "cdc/math/Vector.h"

struct CameraCore
{
cdc::Vector3 position;
char pad1[608];
cdc::Euler rotation;
char pad2[128];
};

struct Camera : CameraCore
{
char pad3[12];

int flags;
int lock;
__int16 mode;
};

Camera* CAMERA_GetCamera();
void CAMERA_CalcPosition(cdc::Vector3* position, cdc::Vector3* base, cdc::Euler* rotation, float distance);
24 changes: 24 additions & 0 deletions src/input/Input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,28 @@
void Input::DisableInput(bool disable)
{
*(bool*)GET_ADDRESS(0x1101689, 0x8551A9, 0xA02B79) = disable;
}

void Input::DisablePlayerControl(bool disable)
{
*(bool*)GET_ADDRESS(0xF15AB4, 0x666C34, 0x8AB4E6) = !disable;
}

bool Input::IsInputActionPressed(int action)
{
auto inputSystem = GetInputSystem();

return (inputSystem->m_pActionMapper->m_pActionResults[action].state & 4) == 4;
}

InputSystem* Input::GetInputSystem()
{
return *(InputSystem**)GET_ADDRESS(0x1101680, 0x8551A0, 0xA02B68);
}

float InputSystem::GetAxisValue(int axisID)
{
auto addr = GET_ADDRESS(0x4E3FC0, 0x4E38C0, 0x480E50);

return Hooking::ThisCallReturn<float>(addr, this, axisID);
}
31 changes: 31 additions & 0 deletions src/input/Input.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,38 @@
#pragma once

class InputActionMapper
{
public:
struct ActionResult
{
unsigned int state;

char pad1[20];
};

ActionResult* m_pActionResults;
};

class InputSystem
{
public:
unsigned int m_numButtons;
unsigned int m_numAxis;

char pad1[16];

InputActionMapper* m_pActionMapper;

public:
float GetAxisValue(int axisID);
};

class Input
{
public:
static void DisableInput(bool disable);
static void DisablePlayerControl(bool disable);
static bool IsInputActionPressed(int action);

static InputSystem* GetInputSystem();
};
96 changes: 96 additions & 0 deletions src/modules/camera/FreeCamera.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "FreeCamera.h"

#include "input/Input.h"
#include "game/Game.h"
#include "render/Font.h"

FreeCameraBase::FreeCameraBase() : m_vKeys()
{
}

void FreeCameraBase::ToggleMode()
{
// Switch between disabled -> enabled -> no control
m_mode = m_mode == Disabled ? Enabled : m_mode == NoControl ? Disabled : NoControl;

// Disable player control when the free camera is enabled
Input::DisablePlayerControl(m_mode == Enabled);
}

void FreeCameraBase::OnInput(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_KEYUP && wParam == VK_F4)
{
ToggleMode();
}

// 1-3 virtual keys, kinda hack.. TODO global thing like this?
if (msg == WM_KEYDOWN && wParam >= 0x31 && wParam <= 0x33)
{
m_vKeys[wParam - 0x31] = true;
}

if (msg == WM_KEYUP && wParam >= 0x31 && wParam <= 0x33)
{
m_vKeys[wParam - 0x31] = false;
}
}

void FreeCameraBase::OnControl()
{
auto input = Input::GetInputSystem();
auto gameTracker = Game::GetGameTracker();

// Camera rotation based on mouse/controller axis
auto rotX = input->GetAxisValue(17) * gameTracker->timeMult;
auto rotZ = input->GetAxisValue(16) * gameTracker->timeMult;

Rotate(rotX, rotZ);

// Camera roll
if (m_vKeys[0] || m_vKeys[2])
{
// TODO
auto roll = m_vKeys[0] ? 0.02454f : -0.02454f;

Rotate(roll * gameTracker->timeMult);
}

// Change the speed depending on if shift/alt is pressed
auto shift = Input::IsInputActionPressed(18);
auto control = Input::IsInputActionPressed(23);

auto speed = shift ? 200.f : control ? 20.f : 80.f;

// Camera forward/backward
if (Input::IsInputActionPressed(1) || Input::IsInputActionPressed(2))
{
auto distance = Input::IsInputActionPressed(1) ? -speed : speed;

MoveForward(distance * gameTracker->timeMult);
}

// Camera left/right
if (Input::IsInputActionPressed(3) || Input::IsInputActionPressed(4))
{
auto distance = Input::IsInputActionPressed(3) ? -speed : speed;

MoveLeft(distance * gameTracker->timeMult);
}

// Camera up/down
if (Input::IsInputActionPressed(16) || Input::IsInputActionPressed(17))
{
auto distance = Input::IsInputActionPressed(16) ? -speed : speed;

MoveUp(distance * gameTracker->timeMult);
}
}

void FreeCameraBase::OnLoop()
{
if (m_mode == Enabled)
{
OnControl();
}
}
52 changes: 52 additions & 0 deletions src/modules/camera/FreeCamera.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

#include "modules/Module.h"

// Base class for both free camera implementations
class FreeCameraBase : public Module
{
public:
enum ControlMode
{
Disabled,
Enabled,
NoControl
};

private:
bool m_vKeys[3];

protected:
ControlMode m_mode = Disabled;

virtual void ToggleMode();
virtual void OnControl();

// Game specific
virtual void Rotate(float x, float z) = 0;
virtual void Rotate(float y) = 0;
virtual void MoveForward(float distance) = 0;
virtual void MoveLeft(float distance) = 0;
virtual void MoveUp(float distance) = 0;

public:
FreeCameraBase();

void OnInput(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void OnLoop();
};

// Free camera implementation for Legend and Anniversary
class LegendCamera : public FreeCameraBase
{
protected:
void ToggleMode();

void Rotate(float x, float z);
void Rotate(float y);
void MoveForward(float distance);
void MoveLeft(float distance);
void MoveUp(float distance);
};

using FreeCamera = LegendCamera;
63 changes: 63 additions & 0 deletions src/modules/camera/Legend.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#define _USE_MATH_DEFINES
#include <cmath>

#include "FreeCamera.h"
#include "game/Camera.h"

void LegendCamera::ToggleMode()
{
FreeCameraBase::ToggleMode();

auto camera = CAMERA_GetCamera();

if (m_mode == Enabled)
{
camera->mode = 7;
}

if (m_mode == Disabled)
{
// Switch back to gameplay camera
camera->mode = 2;
}
}

void LegendCamera::Rotate(float x, float z)
{
auto camera = CAMERA_GetCamera();

camera->rotation.x -= x;
camera->rotation.z -= z;
}

void LegendCamera::Rotate(float y)
{
auto camera = CAMERA_GetCamera();

camera->rotation.y += y;
}

void LegendCamera::MoveForward(float distance)
{
auto camera = CAMERA_GetCamera();

CAMERA_CalcPosition(&camera->position, &camera->position, &camera->rotation, distance);
}

void LegendCamera::MoveLeft(float distance)
{
auto camera = CAMERA_GetCamera();
auto rotation = camera->rotation;

rotation.x = 0.f;
rotation.z += static_cast<float>(M_PI) / 2.f;

CAMERA_CalcPosition(&camera->position, &camera->position, &rotation, distance);
}

void LegendCamera::MoveUp(float distance)
{
auto camera = CAMERA_GetCamera();

camera->position.z += distance;
}

0 comments on commit 32522e5

Please sign in to comment.