mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-07-01 04:20:23 -04:00
Hookifying Various Cheats and FixVineFall (#6827)
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
static void RegisterClimbEverything() {
|
||||
COND_VB_SHOULD(VB_SURFACE_IS_CLIMBABLE, CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0), { *should = true; });
|
||||
COND_VB_SHOULD(VB_SURFACE_ANGLE_IS_CLIMBABLE, CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0),
|
||||
{ *should = true; });
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterClimbEverything, { CVAR_CHEAT("ClimbEverything") });
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
static void RegisterFireproofDekuShield() {
|
||||
COND_VB_SHOULD(VB_BURN_SHIELD, CVarGetInteger(CVAR_CHEAT("FireproofDekuShield"), 0), { *should = false; });
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterFireproofDekuShield, { CVAR_CHEAT("FireproofDekuShield") });
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
static void RegisterHookshotEverything() {
|
||||
COND_VB_SHOULD(VB_SURFACE_IS_HOOKSHOT, CVarGetInteger(CVAR_CHEAT("HookshotEverything"), 0), { *should = true; });
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterHookshotEverything, { CVAR_CHEAT("HookshotEverything") });
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
static void RegisterInfiniteEponaBoost() {
|
||||
COND_VB_SHOULD(VB_CONSUME_EPONA_BOOST, CVarGetInteger(CVAR_CHEAT("InfiniteEponaBoost"), 0), { *should = false; });
|
||||
COND_VB_SHOULD(VB_DRAW_EPONA_BOOST_CARROTS, CVarGetInteger(CVAR_CHEAT("InfiniteEponaBoost"), 0),
|
||||
{ *should = false; });
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterInfiniteEponaBoost, { CVAR_CHEAT("InfiniteEponaBoost") });
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
static void RegisterNoClip() {
|
||||
COND_VB_SHOULD(VB_PERFORM_WALL_COLLISION_CHECK, CVarGetInteger(CVAR_CHEAT("NoClip"), 0), {
|
||||
Actor* actor = va_arg(args, Actor*);
|
||||
if (actor != NULL && actor->id == ACTOR_PLAYER) {
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterNoClip, { CVAR_CHEAT("NoClip") });
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "functions.h"
|
||||
}
|
||||
|
||||
static void RegisterFixVineFall() {
|
||||
// conflicts arise from these two being enabled at once, and with ClimbEverything on, FixVineFall is redundant
|
||||
// anyway
|
||||
COND_VB_SHOULD(
|
||||
VB_REVALIDATE_CLIMBED_WALL,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("FixVineFall"), 0) && !CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0), {
|
||||
PlayState* play = va_arg(args, PlayState*);
|
||||
Player* player = va_arg(args, Player*);
|
||||
u32* touchedWallFlags = va_arg(args, u32*);
|
||||
s16* yawDiff = va_arg(args, s16*);
|
||||
|
||||
/* This fixes the "started climbing a wall and then immediately fell off" bug.
|
||||
* The main idea is if a climbing wall is detected, double-check that it will
|
||||
* still be valid once climbing begins by doing a second raycast with a small
|
||||
* margin to make sure it still hits a climbable poly. Then update the flags
|
||||
* in touchedWallFlags again and proceed as normal.
|
||||
*/
|
||||
if (*touchedWallFlags & 8) {
|
||||
Vec3f checkPosA;
|
||||
Vec3f checkPosB;
|
||||
Vec3f raycastResult;
|
||||
CollisionPoly* wallPoly;
|
||||
s32 wallBgId;
|
||||
f32 yawCos;
|
||||
f32 yawSin;
|
||||
s32 hitWall;
|
||||
|
||||
/* Angle the raycast slightly out towards the side based on the angle of
|
||||
* attack the player takes coming at the climb wall. This is necessary because
|
||||
* the player's XZ position actually wobbles very slightly while climbing
|
||||
* due to small rounding errors in the sin/cos lookup tables. This wobble
|
||||
* can cause wall checks while climbing to be slightly left or right of
|
||||
* the wall check to start the climb. By adding this buffer it accounts for
|
||||
* any possible wobble. The end result is the player has to be further than
|
||||
* some epsilon distance from the edge of the climbing poly to actually
|
||||
* start the climb. I divide it by 2 to make that epsilon slightly smaller,
|
||||
* mainly for visuals. Using the full yawDiff leaves a noticeable gap on
|
||||
* the edges that can't be climbed. But with the half distance it looks like
|
||||
* the player is climbing right on the edge, and still works.
|
||||
*/
|
||||
yawCos = Math_CosS(player->actor.wallYaw - (*yawDiff / 2) + 0x8000);
|
||||
yawSin = Math_SinS(player->actor.wallYaw - (*yawDiff / 2) + 0x8000);
|
||||
checkPosA.x = player->actor.world.pos.x + (-20.0f * yawSin);
|
||||
checkPosA.z = player->actor.world.pos.z + (-20.0f * yawCos);
|
||||
checkPosB.x = player->actor.world.pos.x + (50.0f * yawSin);
|
||||
checkPosB.z = player->actor.world.pos.z + (50.0f * yawCos);
|
||||
checkPosB.y = checkPosA.y = player->actor.world.pos.y + 26.0f;
|
||||
|
||||
hitWall = BgCheck_EntityLineTest1(&play->colCtx, &checkPosA, &checkPosB, &raycastResult, &wallPoly,
|
||||
true, false, false, true, &wallBgId);
|
||||
|
||||
if (hitWall) {
|
||||
player->actor.wallPoly = wallPoly;
|
||||
player->actor.wallBgId = wallBgId;
|
||||
player->actor.wallYaw = Math_Atan2S(wallPoly->normal.z, wallPoly->normal.x);
|
||||
*yawDiff = player->actor.shape.rot.y - (s16)(player->actor.wallYaw + 0x8000);
|
||||
|
||||
*touchedWallFlags = func_80041DB8(&play->colCtx, player->actor.wallPoly, player->actor.wallBgId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterFixVineFall,
|
||||
{ CVAR_ENHANCEMENT("FixVineFall"), CVAR_CHEAT("ClimbEverything") });
|
||||
@@ -285,6 +285,14 @@ typedef enum {
|
||||
// - `*EnPoField`
|
||||
VB_BOTTLE_BIG_POE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// this->currentShield == PLAYER_SHIELD_DEKU
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*Player`
|
||||
VB_BURN_SHIELD,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
@@ -367,6 +375,14 @@ typedef enum {
|
||||
// - None
|
||||
VB_CLOSE_PAUSE_MENU,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*EnHorse`
|
||||
VB_CONSUME_EPONA_BOOST,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
@@ -612,6 +628,14 @@ typedef enum {
|
||||
// - `*int16_t` (item id)
|
||||
VB_DRAW_AMMO_COUNT,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_DRAW_EPONA_BOOST_CARROTS,
|
||||
|
||||
// #### `args`
|
||||
// - `Player*` player
|
||||
// - `PlayState*` play
|
||||
@@ -1642,6 +1666,14 @@ typedef enum {
|
||||
// - `*EnOwl`
|
||||
VB_OWL_INTERACTION,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*Actor`
|
||||
VB_PERFORM_WALL_COLLISION_CHECK,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
@@ -2145,6 +2177,17 @@ typedef enum {
|
||||
// - `**Gfx` (`&POLY_OPA_DISP`)
|
||||
VB_RENDER_YES_ON_CONTINUE_PROMPT,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*PlayState`
|
||||
// - `*Player`
|
||||
// - `*u32`
|
||||
// - `*s16`
|
||||
VB_REVALIDATE_CLIMBED_WALL,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
@@ -2488,6 +2531,30 @@ typedef enum {
|
||||
// - `*BgIceTurara`
|
||||
VB_STALAGMITE_DROP_ITEM,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// ABS(wallPoly->normal.y) < 600
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_SURFACE_ANGLE_IS_CLIMBABLE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// false
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_SURFACE_IS_CLIMBABLE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// SurfaceType_GetData(colCtx, poly, bgId, 1) >> 17 & 1
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_SURFACE_IS_HOOKSHOT,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// varies, never set should to true
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ResourceManagerHelpers.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define SS_NULL 0xFFFF
|
||||
@@ -1892,7 +1893,7 @@ s32 BgCheck_CheckWallImpl(CollisionContext* colCtx, u16 xpFlags, Vec3f* posResul
|
||||
s32 bgId2;
|
||||
f32 nx, ny, nz; // unit normal of polygon
|
||||
|
||||
if (CVarGetInteger(CVAR_CHEAT("NoClip"), 0) && actor != NULL && actor->id == ACTOR_PLAYER) {
|
||||
if (!GameInteractor_Should(VB_PERFORM_WALL_COLLISION_CHECK, true, actor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4011,7 +4012,7 @@ u32 func_80041D94(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) {
|
||||
* SurfaceType Get Wall Flags
|
||||
*/
|
||||
s32 func_80041DB8(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) {
|
||||
if (CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0) != 0) {
|
||||
if (GameInteractor_Should(VB_SURFACE_IS_CLIMBABLE, false)) {
|
||||
return (1 << 3) | D_80119D90[func_80041D94(colCtx, poly, bgId)];
|
||||
} else {
|
||||
return D_80119D90[func_80041D94(colCtx, poly, bgId)];
|
||||
@@ -4108,7 +4109,7 @@ u32 SurfaceType_GetEcho(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId)
|
||||
* SurfaceType Is Hookshot Surface
|
||||
*/
|
||||
u32 SurfaceType_IsHookshotSurface(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) {
|
||||
return CVarGetInteger(CVAR_CHEAT("HookshotEverything"), 0) || SurfaceType_GetData(colCtx, poly, bgId, 1) >> 17 & 1;
|
||||
return GameInteractor_Should(VB_SURFACE_IS_HOOKSHOT, SurfaceType_GetData(colCtx, poly, bgId, 1) >> 17 & 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5776,7 +5776,7 @@ void Interface_Draw(PlayState* play) {
|
||||
if ((play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0)) {
|
||||
if (gSaveContext.minigameState != 1) {
|
||||
// Carrots rendering if the action corresponds to riding a horse
|
||||
if (interfaceCtx->unk_1EE == 8 && !CVarGetInteger(CVAR_CHEAT("InfiniteEponaBoost"), 0)) {
|
||||
if (interfaceCtx->unk_1EE == 8 && GameInteractor_Should(VB_DRAW_EPONA_BOOST_CARROTS, true)) {
|
||||
// Load Carrot Icon
|
||||
gDPLoadTextureBlock(OVERLAY_DISP++, gCarrotIconTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 16, 16, 0,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "objects/object_horse/object_horse.h"
|
||||
#include "objects/object_hni/object_hni.h"
|
||||
#include "scenes/overworld/spot09/spot09_scene.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define FLAGS ACTOR_FLAG_UPDATE_CULLING_DISABLED
|
||||
@@ -3332,7 +3333,7 @@ void EnHorse_CheckBoost(EnHorse* thisx, PlayState* play2) {
|
||||
this->stateFlags |= ENHORSE_BOOST;
|
||||
this->stateFlags |= ENHORSE_FIRST_BOOST_REGEN;
|
||||
this->stateFlags |= ENHORSE_FLAG_8;
|
||||
if (!CVarGetInteger(CVAR_CHEAT("InfiniteEponaBoost"), 0)) {
|
||||
if (GameInteractor_Should(VB_CONSUME_EPONA_BOOST, true, this)) {
|
||||
this->numBoosts--;
|
||||
}
|
||||
this->boostTimer = 0;
|
||||
|
||||
@@ -4681,7 +4681,7 @@ int func_8083816C(s32 arg0) {
|
||||
}
|
||||
|
||||
void func_8083819C(Player* this, PlayState* play) {
|
||||
if (this->currentShield == PLAYER_SHIELD_DEKU && (CVarGetInteger(CVAR_CHEAT("FireproofDekuShield"), 0) == 0)) {
|
||||
if (GameInteractor_Should(VB_BURN_SHIELD, this->currentShield == PLAYER_SHIELD_DEKU, this)) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_SHIELD, this->actor.world.pos.x, this->actor.world.pos.y,
|
||||
this->actor.world.pos.z, 0, 0, 0, 1);
|
||||
Inventory_DeleteEquipment(play, EQUIP_TYPE_SHIELD);
|
||||
@@ -5705,7 +5705,7 @@ s32 func_8083A6AC(Player* this, PlayState* play) {
|
||||
|
||||
if (BgCheck_EntityLineTest1(&play->colCtx, &this->actor.world.pos, &sp74, &sp68, &sp84, true, false, false,
|
||||
true, &sp80) &&
|
||||
((ABS(sp84->normal.y) < 600) || (CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0) != 0))) {
|
||||
GameInteractor_Should(VB_SURFACE_ANGLE_IS_CLIMBABLE, ABS(sp84->normal.y) < 600)) {
|
||||
f32 nx = COLPOLY_GET_NORMAL(sp84->normal.x);
|
||||
f32 ny = COLPOLY_GET_NORMAL(sp84->normal.y);
|
||||
f32 nz = COLPOLY_GET_NORMAL(sp84->normal.z);
|
||||
@@ -11305,56 +11305,7 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) {
|
||||
|
||||
sTouchedWallFlags = func_80041DB8(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId);
|
||||
|
||||
// conflicts arise from these two being enabled at once, and with ClimbEverything on, FixVineFall is redundant
|
||||
// anyway
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("FixVineFall"), 0) && !CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0)) {
|
||||
/* This fixes the "started climbing a wall and then immediately fell off" bug.
|
||||
* The main idea is if a climbing wall is detected, double-check that it will
|
||||
* still be valid once climbing begins by doing a second raycast with a small
|
||||
* margin to make sure it still hits a climbable poly. Then update the flags
|
||||
* in sTouchedWallFlags again and proceed as normal.
|
||||
*/
|
||||
if (sTouchedWallFlags & 8) {
|
||||
Vec3f checkPosA;
|
||||
Vec3f checkPosB;
|
||||
f32 yawCos;
|
||||
f32 yawSin;
|
||||
s32 hitWall;
|
||||
|
||||
/* Angle the raycast slightly out towards the side based on the angle of
|
||||
* attack the player takes coming at the climb wall. This is necessary because
|
||||
* the player's XZ position actually wobbles very slightly while climbing
|
||||
* due to small rounding errors in the sin/cos lookup tables. This wobble
|
||||
* can cause wall checks while climbing to be slightly left or right of
|
||||
* the wall check to start the climb. By adding this buffer it accounts for
|
||||
* any possible wobble. The end result is the player has to be further than
|
||||
* some epsilon distance from the edge of the climbing poly to actually
|
||||
* start the climb. I divide it by 2 to make that epsilon slightly smaller,
|
||||
* mainly for visuals. Using the full yawDiff leaves a noticeable gap on
|
||||
* the edges that can't be climbed. But with the half distance it looks like
|
||||
* the player is climbing right on the edge, and still works.
|
||||
*/
|
||||
yawCos = Math_CosS(this->actor.wallYaw - (yawDiff / 2) + 0x8000);
|
||||
yawSin = Math_SinS(this->actor.wallYaw - (yawDiff / 2) + 0x8000);
|
||||
checkPosA.x = this->actor.world.pos.x + (-20.0f * yawSin);
|
||||
checkPosA.z = this->actor.world.pos.z + (-20.0f * yawCos);
|
||||
checkPosB.x = this->actor.world.pos.x + (50.0f * yawSin);
|
||||
checkPosB.z = this->actor.world.pos.z + (50.0f * yawCos);
|
||||
checkPosB.y = checkPosA.y = this->actor.world.pos.y + 26.0f;
|
||||
|
||||
hitWall = BgCheck_EntityLineTest1(&play->colCtx, &checkPosA, &checkPosB, &sInteractWallCheckResult,
|
||||
&wallPoly, true, false, false, true, &wallBgId);
|
||||
|
||||
if (hitWall) {
|
||||
this->actor.wallPoly = wallPoly;
|
||||
this->actor.wallBgId = wallBgId;
|
||||
this->actor.wallYaw = Math_Atan2S(wallPoly->normal.z, wallPoly->normal.x);
|
||||
yawDiff = this->actor.shape.rot.y - (s16)(this->actor.wallYaw + 0x8000);
|
||||
|
||||
sTouchedWallFlags = func_80041DB8(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId);
|
||||
}
|
||||
}
|
||||
}
|
||||
GameInteractor_Should(VB_REVALIDATE_CLIMBED_WALL, true, play, this, &sTouchedWallFlags, &yawDiff);
|
||||
|
||||
sShapeYawToTouchedWall = ABS(yawDiff);
|
||||
|
||||
@@ -11380,7 +11331,7 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) {
|
||||
if ((this->actor.bgCheckFlags & 0x200) && (sShapeYawToTouchedWall < 0x3000)) {
|
||||
CollisionPoly* wallPoly = this->actor.wallPoly;
|
||||
|
||||
if (ABS(wallPoly->normal.y) < 600 || (CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0) != 0)) {
|
||||
if (GameInteractor_Should(VB_SURFACE_ANGLE_IS_CLIMBABLE, ABS(wallPoly->normal.y) < 600)) {
|
||||
f32 wallPolyNormalX = COLPOLY_GET_NORMAL(wallPoly->normal.x);
|
||||
f32 wallPolyNormalY = COLPOLY_GET_NORMAL(wallPoly->normal.y);
|
||||
f32 wallPolyNormalZ = COLPOLY_GET_NORMAL(wallPoly->normal.z);
|
||||
|
||||
Reference in New Issue
Block a user