Add options for first person aiming (#596)
Some checks are pending
generate-builds / generate-2ship-otr (push) Waiting to run
generate-builds / build-macos (push) Blocked by required conditions
generate-builds / build-linux (push) Blocked by required conditions
generate-builds / build-windows (push) Blocked by required conditions

This commit is contained in:
Garrett Cox 2024-10-06 20:55:16 -05:00 committed by GitHub
parent da793a5bf2
commit 790d36bfbc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 326 additions and 8 deletions

View File

@ -348,6 +348,50 @@ void DrawEnhancementsMenu() {
{ .tooltip =
"Fixes the camera snap that occurs when you are moving and press the targetting button." });
ImGui::SeparatorText("First Person");
UIWidgets::CVarCheckbox("Disable Auto-Centering",
"gEnhancements.Camera.FirstPerson.DisableFirstPersonAutoCenterView");
UIWidgets::CVarCheckbox("Invert X Axis", "gEnhancements.Camera.FirstPerson.InvertX");
UIWidgets::CVarCheckbox("Invert Y Axis", "gEnhancements.Camera.FirstPerson.InvertY",
{ .defaultValue = true });
UIWidgets::CVarSliderFloat("X Axis Sensitivity: %.0f%%", "gEnhancements.Camera.FirstPerson.SensitivityX",
0.1f, 2.0f, 1.0f, { .isPercentage = true });
UIWidgets::CVarSliderFloat("Y Axis Sensitivity: %.0f%%", "gEnhancements.Camera.FirstPerson.SensitivityY",
0.1f, 2.0f, 1.0f, { .isPercentage = true });
UIWidgets::CVarCheckbox(
"Gyro Aiming", "gEnhancements.Camera.FirstPerson.GyroEnabled",
{ .tooltip = "Enables gyro aiming in first person mode. Requires a controller with gyro support, and "
"for it to be mapped in the Controller Mapping menu" });
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.GyroEnabled", 0)) {
UIWidgets::CVarCheckbox("Invert Gyro X Axis", "gEnhancements.Camera.FirstPerson.GyroInvertX");
UIWidgets::CVarCheckbox("Invert Gyro Y Axis", "gEnhancements.Camera.FirstPerson.GyroInvertY");
UIWidgets::CVarSliderFloat("Gyro X Axis Sensitivity: %.0f%%",
"gEnhancements.Camera.FirstPerson.GyroSensitivityX", 0.1f, 2.0f, 1.0f,
{ .isPercentage = true });
UIWidgets::CVarSliderFloat("Gyro Y Axis Sensitivity: %.0f%%",
"gEnhancements.Camera.FirstPerson.GyroSensitivityY", 0.1f, 2.0f, 1.0f,
{ .isPercentage = true });
}
UIWidgets::CVarCheckbox(
"Right Stick Aiming", "gEnhancements.Camera.FirstPerson.RightStickEnabled",
{ .tooltip = "Enables right stick aiming in first person mode. Requires the controller right stick to "
"be mapped in the Controller Mapping menu" });
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.RightStickEnabled", 0)) {
UIWidgets::CVarCheckbox("Move with left stick while in first person",
"gEnhancements.Camera.FirstPerson.MoveInFirstPerson");
UIWidgets::CVarCheckbox("Invert Right Stick X Axis",
"gEnhancements.Camera.FirstPerson.RightStickInvertX");
UIWidgets::CVarCheckbox("Invert Right Stick Y Axis",
"gEnhancements.Camera.FirstPerson.RightStickInvertY", { .defaultValue = true });
UIWidgets::CVarSliderFloat("Right Stick X Axis Sensitivity: %.0f%%",
"gEnhancements.Camera.FirstPerson.RightStickSensitivityX", 0.1f, 2.0f, 1.0f,
{ .isPercentage = true });
UIWidgets::CVarSliderFloat("Right Stick Y Axis Sensitivity: %.0f%%",
"gEnhancements.Camera.FirstPerson.RightStickSensitivityY", 0.1f, 2.0f, 1.0f,
{ .isPercentage = true });
}
ImGui::SeparatorText("Free Look");
if (UIWidgets::CVarCheckbox(
"Free Look", "gEnhancements.Camera.FreeLook.Enable",

View File

@ -31,6 +31,9 @@ typedef enum {
DISABLE_FOR_DEBUG_CAM_OFF,
DISABLE_FOR_FREE_LOOK_ON,
DISABLE_FOR_FREE_LOOK_OFF,
DISABLE_FOR_GYRO_OFF,
DISABLE_FOR_GYRO_ON,
DISABLE_FOR_RIGHT_STICK_OFF,
DISABLE_FOR_AUTO_SAVE_OFF,
DISABLE_FOR_NULL_PLAY_STATE,
DISABLE_FOR_DEBUG_MODE_OFF,
@ -278,6 +281,17 @@ static std::map<DisableOption, disabledInfo> disabledMap = {
{ DISABLE_FOR_FREE_LOOK_OFF,
{ [](disabledInfo& info) -> bool { return !CVarGetInteger("gEnhancements.Camera.FreeLook.Enable", 0); },
"Free Look is Disabled" } },
{ DISABLE_FOR_GYRO_OFF,
{ [](disabledInfo& info) -> bool { return !CVarGetInteger("gEnhancements.Camera.FirstPerson.GyroEnabled", 0); },
"Gyro Aiming is Disabled" } },
{ DISABLE_FOR_GYRO_ON,
{ [](disabledInfo& info) -> bool { return CVarGetInteger("gEnhancements.Camera.FirstPerson.GyroEnabled", 0); },
"Gyro Aiming is Enabled" } },
{ DISABLE_FOR_RIGHT_STICK_OFF,
{ [](disabledInfo& info) -> bool {
return !CVarGetInteger("gEnhancements.Camera.FirstPerson.RightStickEnabled", 0);
},
"Right Stick Aiming is Disabled" } },
{ DISABLE_FOR_AUTO_SAVE_OFF,
{ [](disabledInfo& info) -> bool { return !CVarGetInteger("gEnhancements.Saving.Autosave", 0); },
"AutoSave is Disabled" } },
@ -703,12 +717,118 @@ void AddEnhancements() {
enhancementsSidebar.push_back(
{ "Camera",
3,
{ { { .widgetName = "Fixes", .widgetType = WIDGET_SEPARATOR_TEXT },
{ "Fix Targetting Camera Snap",
"gEnhancements.Camera.FixTargettingCameraSnap",
"Fixes the camera snap that occurs when you are moving and press the targetting button.",
WIDGET_CVAR_CHECKBOX,
{} } },
{ {
{ .widgetName = "Fixes", .widgetType = WIDGET_SEPARATOR_TEXT },
{ "Fix Targetting Camera Snap",
"gEnhancements.Camera.FixTargettingCameraSnap",
"Fixes the camera snap that occurs when you are moving and press the targetting button.",
WIDGET_CVAR_CHECKBOX,
{} },
{ .widgetName = "First Person", .widgetType = WIDGET_SEPARATOR_TEXT },
{ "Disable Auto-Centering",
"gEnhancements.Camera.FirstPerson.DisableFirstPersonAutoCenterView",
"Disables the auto-centering of the camera in first person mode.",
WIDGET_CVAR_CHECKBOX,
{},
nullptr,
[](widgetInfo& info) {
if (disabledMap.at(DISABLE_FOR_GYRO_ON).active)
info.activeDisables.push_back(DISABLE_FOR_GYRO_ON);
} },
{ "Invert X Axis", "gEnhancements.Camera.FirstPerson.InvertX",
"Inverts the X Axis of the Camera in First Person Mode.", WIDGET_CVAR_CHECKBOX },
{ "Invert Y Axis",
"gEnhancements.Camera.FirstPerson.InvertY",
"Inverts the Y Axis of the Camera in First Person Mode.",
WIDGET_CVAR_CHECKBOX,
{ .defaultVariant = true } },
{ "X Axis Sensitivity: %.0f%%",
"gEnhancements.Camera.FirstPerson.SensitivityX",
"Adjusts the Sensitivity of the X Axis in First Person Mode.",
WIDGET_CVAR_SLIDER_FLOAT,
{ .min = 10.0f, .max = 200.0f, .defaultVariant = 100.0f, .format = "%.0f%%", .isPercentage = true },
nullptr },
{ "Y Axis Sensitivity: %.0f%%",
"gEnhancements.Camera.FirstPerson.SensitivityY",
"Adjusts the Sensitivity of the Y Axis in First Person Mode.",
WIDGET_CVAR_SLIDER_FLOAT,
{ .min = 10.0f, .max = 200.0f, .defaultVariant = 100.0f, .format = "%.0f%%", .isPercentage = true },
nullptr },
{ "Gyro Aiming",
"gEnhancements.Camera.FirstPerson.GyroEnabled",
"Enables Gyro Aiming in First Person Mode.",
WIDGET_CVAR_CHECKBOX,
{},
nullptr },
{ "Invert Gyro X Axis",
"gEnhancements.Camera.FirstPerson.GyroInvertX",
"Inverts the X Axis of the Gyro in First Person Mode.",
WIDGET_CVAR_CHECKBOX,
{},
nullptr,
[](widgetInfo& info) { info.isHidden = disabledMap.at(DISABLE_FOR_GYRO_OFF).active; } },
{ "Invert Gyro Y Axis",
"gEnhancements.Camera.FirstPerson.GyroInvertY",
"Inverts the Y Axis of the Gyro in First Person Mode.",
WIDGET_CVAR_CHECKBOX,
{},
nullptr,
[](widgetInfo& info) { info.isHidden = disabledMap.at(DISABLE_FOR_GYRO_OFF).active; } },
{ "Gyro X Axis Sensitivity: %.0f%%",
"gEnhancements.Camera.FirstPerson.GyroSensitivityX",
"Adjusts the Sensitivity of the X Axis of the Gyro in First Person Mode.",
WIDGET_CVAR_SLIDER_FLOAT,
{ .min = 10.0f, .max = 200.0f, .defaultVariant = 100.0f, .format = "%.0f%%", .isPercentage = true },
nullptr,
[](widgetInfo& info) { info.isHidden = disabledMap.at(DISABLE_FOR_GYRO_OFF).active; } },
{ "Gyro Y Axis Sensitivity: %.0f%%",
"gEnhancements.Camera.FirstPerson.GyroSensitivityY",
"Adjusts the Sensitivity of the Y Axis of the Gyro in First Person Mode.",
WIDGET_CVAR_SLIDER_FLOAT,
{ .min = 10.0f, .max = 200.0f, .defaultVariant = 100.0f, .format = "%.0f%%", .isPercentage = true },
nullptr,
[](widgetInfo& info) { info.isHidden = disabledMap.at(DISABLE_FOR_GYRO_OFF).active; } },
{ "Right Stick Aiming", "gEnhancements.Camera.FirstPerson.RightStickEnabled",
"Enables Right Stick Aiming in First Person Mode.", WIDGET_CVAR_CHECKBOX },
{ "Move while aiming",
"gEnhancements.Camera.FirstPerson.MoveInFirstPerson",
"Allows movement with the left stick while in first person mode.",
WIDGET_CVAR_CHECKBOX,
{},
nullptr,
[](widgetInfo& info) {
if (disabledMap.at(DISABLE_FOR_RIGHT_STICK_OFF).active)
info.activeDisables.push_back(DISABLE_FOR_RIGHT_STICK_OFF);
} },
{ "Invert Right Stick X Axis",
"gEnhancements.Camera.FirstPerson.RightStickInvertX",
"Inverts the X Axis of the Right Stick in First Person Mode.",
WIDGET_CVAR_CHECKBOX,
{},
nullptr,
[](widgetInfo& info) { info.isHidden = disabledMap.at(DISABLE_FOR_RIGHT_STICK_OFF).active; } },
{ "Invert Right Stick Y Axis",
"gEnhancements.Camera.FirstPerson.RightStickInvertY",
"Inverts the Y Axis of the Right Stick in First Person Mode.",
WIDGET_CVAR_CHECKBOX,
{ .defaultVariant = true },
nullptr,
[](widgetInfo& info) { info.isHidden = disabledMap.at(DISABLE_FOR_RIGHT_STICK_OFF).active; } },
{ "Right Stick X Axis Sensitivity: %.0f%%",
"gEnhancements.Camera.FirstPerson.RightStickSensitivityX",
"Adjusts the Sensitivity of the X Axis of the Right Stick in First Person Mode.",
WIDGET_CVAR_SLIDER_FLOAT,
{ .min = 10.0f, .max = 200.0f, .defaultVariant = 100.0f, .format = "%.0f%%", .isPercentage = true },
nullptr,
[](widgetInfo& info) { info.isHidden = disabledMap.at(DISABLE_FOR_RIGHT_STICK_OFF).active; } },
{ "Right Stick Y Axis Sensitivity: %.0f%%",
"gEnhancements.Camera.FirstPerson.RightStickSensitivityY",
"Adjusts the Sensitivity of the Y Axis of the Right Stick in First Person Mode.",
WIDGET_CVAR_SLIDER_FLOAT,
{ .min = 10.0f, .max = 200.0f, .defaultVariant = 100.0f, .format = "%.0f%%", .isPercentage = true },
nullptr,
[](widgetInfo& info) { info.isHidden = disabledMap.at(DISABLE_FOR_RIGHT_STICK_OFF).active; } },
},
// Camera Enhancements
{ { .widgetName = "Cameras", .widgetType = WIDGET_SEPARATOR_TEXT },
{ "Free Look",

View File

@ -266,6 +266,36 @@ int GameInteractor_InvertControl(GIInvertType type) {
result *= -1;
}
break;
case GI_INVERT_FIRST_PERSON_AIM_X:
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.InvertX", 0)) {
result *= -1;
}
break;
case GI_INVERT_FIRST_PERSON_AIM_Y:
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.InvertY", 1)) {
result *= -1;
}
break;
case GI_INVERT_FIRST_PERSON_GYRO_X:
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.GyroInvertX", 0)) {
result *= -1;
}
break;
case GI_INVERT_FIRST_PERSON_GYRO_Y:
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.GyroInvertY", 0)) {
result *= -1;
}
break;
case GI_INVERT_FIRST_PERSON_RIGHT_STICK_X:
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.RightStickInvertX", 0)) {
result *= -1;
}
break;
case GI_INVERT_FIRST_PERSON_RIGHT_STICK_Y:
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.RightStickInvertY", 1)) {
result *= -1;
}
break;
}
// Invert all X axis inputs if the Mirrored World mode is enabled
@ -273,13 +303,16 @@ int GameInteractor_InvertControl(GIInvertType type) {
switch (type) {
case GI_INVERT_CAMERA_RIGHT_STICK_X:
case GI_INVERT_MOVEMENT_X:
case GI_INVERT_FIRST_PERSON_AIM_X:
case GI_INVERT_SHIELD_X:
case GI_INVERT_SHOP_X:
case GI_INVERT_HORSE_X:
case GI_INVERT_ZORA_SWIM_X:
case GI_INVERT_DEBUG_DPAD_X:
case GI_INVERT_TELESCOPE_X:
case GI_INVERT_FIRST_PERSON_AIM_X:
case GI_INVERT_FIRST_PERSON_GYRO_X:
case GI_INVERT_FIRST_PERSON_RIGHT_STICK_X:
case GI_INVERT_FIRST_PERSON_MOVING_X:
result *= -1;
break;
default:

View File

@ -69,13 +69,19 @@ typedef enum {
GI_INVERT_CAMERA_RIGHT_STICK_X,
GI_INVERT_CAMERA_RIGHT_STICK_Y,
GI_INVERT_MOVEMENT_X,
GI_INVERT_FIRST_PERSON_AIM_X,
GI_INVERT_SHIELD_X,
GI_INVERT_SHOP_X,
GI_INVERT_HORSE_X,
GI_INVERT_ZORA_SWIM_X,
GI_INVERT_DEBUG_DPAD_X,
GI_INVERT_TELESCOPE_X,
GI_INVERT_FIRST_PERSON_AIM_X,
GI_INVERT_FIRST_PERSON_AIM_Y,
GI_INVERT_FIRST_PERSON_GYRO_X,
GI_INVERT_FIRST_PERSON_GYRO_Y,
GI_INVERT_FIRST_PERSON_RIGHT_STICK_X,
GI_INVERT_FIRST_PERSON_RIGHT_STICK_Y,
GI_INVERT_FIRST_PERSON_MOVING_X,
} GIInvertType;
typedef enum {

View File

@ -13004,7 +13004,122 @@ void Player_Destroy(Actor* thisx, PlayState* play) {
func_80831454(this);
}
s32 Ship_HandleFirstPersonAiming(PlayState* play, Player* this, s32 arg2) {
s16 var_s0;
s32 stickX = 0;
s32 stickY = 0;
float gyroX = 0.0f;
float gyroY = 0.0f;
if (!CVarGetInteger("gEnhancements.Camera.FirstPerson.MoveInFirstPerson", 0)) {
s32 leftStickX = sPlayerControlInput->rel.stick_x; // -60 to 60
s32 leftStickY = sPlayerControlInput->rel.stick_y; // -60 to 60
leftStickX *= GameInteractor_InvertControl(GI_INVERT_FIRST_PERSON_AIM_X);
leftStickY *= -GameInteractor_InvertControl(GI_INVERT_FIRST_PERSON_AIM_Y);
stickX += leftStickX * CVarGetFloat("gEnhancements.Camera.FirstPerson.SensitivityX", 1.0f);
stickY += leftStickY * CVarGetFloat("gEnhancements.Camera.FirstPerson.SensitivityY", 1.0f);
}
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.GyroEnabled", 0)) {
gyroX = sPlayerControlInput->cur.gyro_y * 720; // -40 to 40, avg -4 to 4
gyroY = sPlayerControlInput->cur.gyro_x * 720; // -20 to 20, avg -2 to 2
gyroX *= GameInteractor_InvertControl(GI_INVERT_FIRST_PERSON_GYRO_X);
gyroY *= -GameInteractor_InvertControl(GI_INVERT_FIRST_PERSON_GYRO_Y);
gyroX *= CVarGetFloat("gEnhancements.Camera.FirstPerson.GyroSensitivityX", 1.0f);
gyroY *= CVarGetFloat("gEnhancements.Camera.FirstPerson.GyroSensitivityY", 1.0f);
}
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.RightStickEnabled", 0)) {
s32 rightStickX = sPlayerControlInput->cur.right_stick_x; // -40 to 40, avg -4 to 4
s32 rightStickY = sPlayerControlInput->cur.right_stick_y; // -20 to 20, avg -2 to 2
rightStickX *= GameInteractor_InvertControl(GI_INVERT_FIRST_PERSON_RIGHT_STICK_X);
rightStickY *= -GameInteractor_InvertControl(GI_INVERT_FIRST_PERSON_RIGHT_STICK_Y);
stickX += rightStickX * CVarGetFloat("gEnhancements.Camera.FirstPerson.RightStickSensitivityX", 1.0f);
stickY += rightStickY * CVarGetFloat("gEnhancements.Camera.FirstPerson.RightStickSensitivityY", 1.0f);
}
stickX = CLAMP(stickX, -60, 60);
stickY = CLAMP(stickY, -60, 60);
if (!func_800B7128(this) && !func_8082EF20(this) && !arg2) { // First person without weapon
var_s0 = stickY * 0xF0;
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.DisableFirstPersonAutoCenterView", 0) ||
CVarGetInteger("gEnhancements.Camera.FirstPerson.GyroEnabled", 0)) {
this->actor.focus.rot.x += var_s0 * 0.1f;
} else {
Math_SmoothStepToS(&this->actor.focus.rot.x, var_s0, 0xE, 0xFA0, 0x1E);
}
this->actor.focus.rot.x += gyroY;
this->actor.focus.rot.x = CLAMP(this->actor.focus.rot.x, -14000, 14000);
var_s0 = stickX * -0x10;
var_s0 = CLAMP(var_s0, -0xBB8, 0xBB8);
this->actor.focus.rot.y += var_s0 + gyroX;
} else { // First person with weapon
s16 temp3;
temp3 = ((stickY >= 0) ? 1 : -1) * (s32)((1.0f - Math_CosS(stickY * 0xC8)) * 1500.0f);
this->actor.focus.rot.x += temp3 + gyroY;
if (this->stateFlags1 & PLAYER_STATE1_800000) {
this->actor.focus.rot.x = CLAMP(this->actor.focus.rot.x, -0x1F40, 0xFA0);
} else {
this->actor.focus.rot.x = CLAMP(this->actor.focus.rot.x, -0x36B0, 0x36B0);
}
var_s0 = this->actor.focus.rot.y - this->actor.shape.rot.y;
temp3 = ((stickX >= 0) ? 1 : -1) * (s32)((1.0f - Math_CosS(stickX * 0xC8)) * -1500.0f);
var_s0 += temp3;
this->actor.focus.rot.y = CLAMP(var_s0 + gyroX, -0x4AAA, 0x4AAA) + this->actor.shape.rot.y;
}
if (CVarGetInteger("gEnhancements.Camera.FirstPerson.MoveInFirstPerson", 0) &&
CVarGetInteger("gEnhancements.Camera.FirstPerson.RightStickEnabled", 0)) {
f32 movementSpeed = 8.25f; // account for form
if (this->currentMask == PLAYER_MASK_BUNNY) {
movementSpeed *= 1.5f;
}
f32 relX =
(-sPlayerControlInput->rel.stick_x / 10) * GameInteractor_InvertControl(GI_INVERT_FIRST_PERSON_MOVING_X);
f32 relY = (sPlayerControlInput->rel.stick_y / 10);
// Normalize so that diagonal movement isn't faster
f32 relMag = sqrtf((relX * relX) + (relY * relY));
if (relMag > 1.0f) {
relX /= relMag;
relY /= relMag;
}
// Determine what left and right mean based on camera angle
f32 relX2 = relX * Math_CosS(this->actor.focus.rot.y) + relY * Math_SinS(this->actor.focus.rot.y);
f32 relY2 = relY * Math_CosS(this->actor.focus.rot.y) - relX * Math_SinS(this->actor.focus.rot.y);
// Calculate distance for footstep sound
f32 distance = sqrtf((relX2 * relX2) + (relY2 * relY2)) * movementSpeed;
func_8083EA44(this, distance / 4.5f);
this->actor.world.pos.x += (relX2 * movementSpeed) + this->actor.colChkInfo.displacement.x;
this->actor.world.pos.z += (relY2 * movementSpeed) + this->actor.colChkInfo.displacement.z;
}
this->unk_AA6 |= 2;
return func_80832754(this, (play->bButtonAmmoPlusOne != 0) || func_800B7128(this) || func_8082EF20(this));
}
s32 func_80847190(PlayState* play, Player* this, s32 arg2) {
// #region 2S2H [Enhancements] Use our own heavily modified version of this for customizations
return Ship_HandleFirstPersonAiming(play, this, arg2);
// #endregion
s32 pad;
s16 var_s0;
s32 stickX = sPlayerControlInput->rel.stick_x;