Free Camera (#542)

* freecam wip

* added manual mode

* fix freecam collision

* made freecam into its own function

* Added settings & Radius modification when camer is higher up

---------

Co-authored-by: MelonSpeedruns <melonspeedruns@stratobox.net>
This commit is contained in:
MelonSpeedruns
2026-04-25 23:35:43 -04:00
committed by GitHub
parent f7b5350d60
commit ba58d2486e
7 changed files with 98 additions and 3 deletions
+6
View File
@@ -143,6 +143,12 @@ public:
/* 0x20 */ JORFile mFile;
#endif
#if TARGET_PC
/* 0x24 */ u8 mManualMode;
/* 0x25 */ f32 freeXAngle;
/* 0x29 */ f32 freeYAngle;
#endif
u32 Id(s32 i_style) { return mCamStyleData[i_style].field_0x0; }
int Algorythmn(s32 i_style) { return mCamStyleData[i_style].field_0x4; }
int Algorythmn() { return mCurrentStyle->field_0x4; }
+5
View File
@@ -273,6 +273,8 @@ public:
/* 0xA4 */ f32 field_0xa4;
/* 0xA8 */ int field_0xa8;
/* 0xAC */ f32 field_0xac;
f32 xAngle;
f32 yAngle;
};
struct LockOnData {
@@ -1024,6 +1026,9 @@ public:
bool colosseumCamera(s32);
bool test1Camera(s32);
bool test2Camera(s32);
#if TARGET_PC
bool freeCamera();
#endif
bool towerCamera(s32);
bool hookshotCamera(s32);
bool railCamera(s32);
+4 -1
View File
@@ -82,7 +82,6 @@ struct UserSettings {
// Preferences
ConfigVar<bool> enableMirrorMode;
ConfigVar<bool> invertCameraXAxis;
ConfigVar<bool> disableMainHUD;
ConfigVar<bool> pauseOnFocusLost;
ConfigVar<bool> enableLinkDollRotation;
@@ -112,6 +111,10 @@ struct UserSettings {
ConfigVar<float> gyroDeadband;
ConfigVar<bool> gyroInvertPitch;
ConfigVar<bool> gyroInvertYaw;
ConfigVar<bool> freeCamera;
ConfigVar<bool> invertCameraXAxis;
ConfigVar<bool> invertCameraYAxis;
ConfigVar<float> freeCameraSensitivity;
// Cheats
ConfigVar<bool> infiniteHearts;
+66
View File
@@ -800,6 +800,10 @@ void dCamera_c::updatePad() {
}
mLockLActive = 1;
#if TARGET_PC
mCamParam.mManualMode = 0;
#endif
} else {
mLockLJustActivated = 0;
mLockLActive = 0;
@@ -833,6 +837,12 @@ void dCamera_c::updatePad() {
mHoldB = mDoCPd_c::getHoldB(mPadID) ? true : false;
mTrigB = mDoCPd_c::getTrigB(mPadID) ? true : false;
#if TARGET_PC
if (mCamParam.mManualMode) {
return;
}
#endif
bool sp6B = true;
bool sp6C = true;
int temp1;
@@ -1167,6 +1177,13 @@ bool dCamera_c::Run() {
}
} else {
sp0F = (this->*engine_tbl[mCamParam.Algorythmn(mCamStyle)])(mCamStyle);
#if TARGET_PC
if (mCamParam.Algorythmn(mCamStyle) != 1) {
mCamParam.mManualMode = 0;
}
#endif
field_0x170++;
field_0x160++;
mCurCamStyleTimer++;
@@ -3078,6 +3095,11 @@ bool dCamera_c::bumpCheck(u32 i_flags) {
} else {
field_0x968 *= mMonitor.field_0xc / 5.0f;
}
#if TARGET_PC
if (!dusk::getSettings().game.freeCamera || !mCamParam.mManualMode) {
#endif
f32 tmp = field_0x96c * (mIsWolf == 1 ? 30.0f : 30.0f);
center += vec3.norm() * (tmp * globe.V().Sin());
cSGlobe globe2(vec2 - center);
@@ -3091,6 +3113,10 @@ bool dCamera_c::bumpCheck(u32 i_flags) {
vec = lin_chk1.GetCross();
}
#if TARGET_PC
}
#endif
#if DEBUG
if (mCamSetup.CheckFlag(0x8000)) {
dDbVw_Report(20, 235, " U");
@@ -4604,6 +4630,11 @@ bool dCamera_c::chaseCamera(s32 param_0) {
sp110 = mViewCache.mDirection.R();
mViewCache.mDirection.R(mViewCache.mDirection.R() + (fVar55 - mViewCache.mDirection.R()) * chase->field_0x74);
#if TARGET_PC
freeCamera();
#endif
chase->field_0x64 = mViewCache.mCenter + mViewCache.mDirection.Xyz();
mViewCache.mEye = chase->field_0x64;
@@ -7444,6 +7475,41 @@ bool dCamera_c::test2Camera(s32 param_0) {
return false;
}
#if TARGET_PC
bool dCamera_c::freeCamera() {
if (!dusk::getSettings().game.freeCamera) {
mCamParam.mManualMode = 0;
return false;
}
cXyz camMovement = {mPadInfo.mCStick.mLastPosX, mPadInfo.mCStick.mLastPosY, 0.0f};
f32 magnitude = sqrt(mPadInfo.mCStick.mLastPosX * mPadInfo.mCStick.mLastPosX + mPadInfo.mCStick.mLastPosY * mPadInfo.mCStick.mLastPosY);
if (mPadInfo.mCStick.mLastPosX != 0 || mPadInfo.mCStick.mLastPosY != 0) {
if (!mCamParam.mManualMode) {
mCamParam.mManualMode = 1;
mCamParam.freeXAngle = mViewCache.mDirection.mAzimuth.Degree();
mCamParam.freeYAngle = mViewCache.mDirection.mInclination.Degree();
}
camMovement = camMovement.normalize();
camMovement.x *= (dusk::getSettings().game.invertCameraXAxis ? 1.0f : -1.0f) * dusk::getSettings().game.freeCameraSensitivity * 4.0f;
camMovement.y *= (dusk::getSettings().game.invertCameraYAxis ? 1.0f : -1.0f) * dusk::getSettings().game.freeCameraSensitivity * 4.0f;
mCamParam.freeXAngle += camMovement.x * magnitude * dusk::getSettings().game.freeCameraSensitivity;
mCamParam.freeYAngle += camMovement.y * magnitude * dusk::getSettings().game.freeCameraSensitivity;
}
if (mCamParam.mManualMode) {
mCamParam.freeYAngle = std::clamp(mCamParam.freeYAngle, -35.0f, 60.0f);
mViewCache.mDirection.mAzimuth = cSAngle(mCamParam.freeXAngle);
mViewCache.mDirection.mInclination = cSAngle(mCamParam.freeYAngle);
mViewCache.mDirection.mRadius = std::clamp(mCamParam.freeYAngle * 15.0f, 300.0f, 10000.0f);
}
return mCamParam.mManualMode;
}
#endif
bool dCamera_c::towerCamera(s32 param_0) {
cSAngle stack_444 = cSAngle(mCamSetup.ChargeLatitude());
f32 sp224 = mCamSetup.ChargeBRatio();
+1
View File
@@ -29,6 +29,7 @@ static void ApplyPresetHD() {
s.game.fastTears.setValue(true);
s.game.biggerWallets.setValue(true);
s.game.invertCameraXAxis.setValue(true);
s.game.freeCamera.setValue(true);
}
static void ApplyPresetDusk() {
+9 -1
View File
@@ -383,7 +383,15 @@ namespace dusk {
ImGui::SeparatorText("Camera");
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
config::ImGuiCheckbox("Free Camera", getSettings().game.freeCamera);
if (getSettings().game.freeCamera) {
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
config::ImGuiCheckbox("Invert Camera Y Axis", getSettings().game.invertCameraYAxis);
config::ImGuiSliderFloat("Free Camera Sensitivity", getSettings().game.freeCameraSensitivity, 0.5f, 2.0f, "%.1f");
} else {
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
}
ImGui::SeparatorText("Gyro");
+7 -1
View File
@@ -42,7 +42,6 @@ UserSettings g_userSettings = {
// Preferences
.enableMirrorMode {"game.enableMirrorMode", false},
.invertCameraXAxis {"game.invertCameraXAxis", false},
.disableMainHUD {"game.disableMainHUD", false},
.pauseOnFocusLost {"game.pauseOnFocusLost", false},
.enableLinkDollRotation = {"game.enableLinkDollRotation", false },
@@ -71,6 +70,10 @@ UserSettings g_userSettings = {
.gyroDeadband {"game.gyroDeadband", 0.04f},
.gyroInvertPitch {"game.gyroInvertPitch", false},
.gyroInvertYaw {"game.gyroInvertYaw", false},
.freeCamera {"game.freeCamera", false},
.invertCameraXAxis {"game.invertCameraXAxis", false},
.invertCameraYAxis {"game.invertCameraYAxis", false},
.freeCameraSensitivity {"game.freeCameraSensitivity", 1.0f},
// Cheats
.infiniteHearts {"game.infiniteHearts", false},
@@ -144,6 +147,8 @@ void registerSettings() {
Register(g_userSettings.game.sunsSong);
Register(g_userSettings.game.enableMirrorMode);
Register(g_userSettings.game.invertCameraXAxis);
Register(g_userSettings.game.invertCameraYAxis);
Register(g_userSettings.game.freeCameraSensitivity);
Register(g_userSettings.game.disableMainHUD);
Register(g_userSettings.game.pauseOnFocusLost);
Register(g_userSettings.game.bloomMode);
@@ -183,6 +188,7 @@ void registerSettings() {
Register(g_userSettings.game.gyroSmoothing);
Register(g_userSettings.game.gyroInvertPitch);
Register(g_userSettings.game.gyroInvertYaw);
Register(g_userSettings.game.freeCamera);
Register(g_userSettings.backend.isoPath);
Register(g_userSettings.backend.graphicsBackend);