mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-25 07:35:34 -07:00
Forced Hyper Bosses
This commit is contained in:
parent
dc8374830c
commit
eace543250
9 changed files with 116 additions and 4 deletions
|
@ -34,6 +34,7 @@ uint8_t GameInteractor_ReverseControlsActive();
|
||||||
int32_t GameInteractor_DefenseModifier();
|
int32_t GameInteractor_DefenseModifier();
|
||||||
int32_t GameInteractor_RunSpeedModifier();
|
int32_t GameInteractor_RunSpeedModifier();
|
||||||
GIGravityLevel GameInteractor_GravityLevel();
|
GIGravityLevel GameInteractor_GravityLevel();
|
||||||
|
uint8_t GameInteractor_SecondCollisionUpdate();
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -66,6 +67,7 @@ public:
|
||||||
static int32_t DefenseModifier;
|
static int32_t DefenseModifier;
|
||||||
static int32_t RunSpeedModifier;
|
static int32_t RunSpeedModifier;
|
||||||
static GIGravityLevel GravityLevel;
|
static GIGravityLevel GravityLevel;
|
||||||
|
static uint8_t SecondCollisionUpdate;
|
||||||
|
|
||||||
static void SetPacifistMode(bool active);
|
static void SetPacifistMode(bool active);
|
||||||
};
|
};
|
||||||
|
@ -90,6 +92,7 @@ public:
|
||||||
DEFINE_HOOK(OnReceiveItem, void(u8 item));
|
DEFINE_HOOK(OnReceiveItem, void(u8 item));
|
||||||
DEFINE_HOOK(OnSceneInit, void(s16 sceneNum));
|
DEFINE_HOOK(OnSceneInit, void(s16 sceneNum));
|
||||||
DEFINE_HOOK(OnPlayerUpdate, void());
|
DEFINE_HOOK(OnPlayerUpdate, void());
|
||||||
|
DEFINE_HOOK(OnActorUpdate, void(void* actor));
|
||||||
|
|
||||||
DEFINE_HOOK(OnSaveFile, void(int32_t fileNum));
|
DEFINE_HOOK(OnSaveFile, void(int32_t fileNum));
|
||||||
DEFINE_HOOK(OnLoadFile, void(int32_t fileNum));
|
DEFINE_HOOK(OnLoadFile, void(int32_t fileNum));
|
||||||
|
@ -116,6 +119,7 @@ public:
|
||||||
static void GiveDekuShield();
|
static void GiveDekuShield();
|
||||||
static void SpawnCuccoStorm();
|
static void SpawnCuccoStorm();
|
||||||
static void ForceInterfaceUpdate();
|
static void ForceInterfaceUpdate();
|
||||||
|
static void UpdateActor(void* refActor);
|
||||||
|
|
||||||
static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams);
|
static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams);
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,6 +30,10 @@ void GameInteractor_ExecuteOnPlayerUpdate() {
|
||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerUpdate>();
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerUpdate>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameInteractor_ExecuteOnActorUpdate(void* actor) {
|
||||||
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnActorUpdate>(actor);
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Save Files
|
// MARK: - Save Files
|
||||||
|
|
||||||
void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) {
|
void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ extern "C" void GameInteractor_ExecuteOnGameFrameUpdate();
|
||||||
extern "C" void GameInteractor_ExecuteOnReceiveItemHooks(u8 item);
|
extern "C" void GameInteractor_ExecuteOnReceiveItemHooks(u8 item);
|
||||||
extern "C" void GameInteractor_ExecuteOnSceneInit(s16 sceneNum);
|
extern "C" void GameInteractor_ExecuteOnSceneInit(s16 sceneNum);
|
||||||
extern "C" void GameInteractor_ExecuteOnPlayerUpdate();
|
extern "C" void GameInteractor_ExecuteOnPlayerUpdate();
|
||||||
|
extern "C" void GameInteractor_ExecuteOnActorUpdate(void* actor);
|
||||||
|
|
||||||
// MARK: - Save Files
|
// MARK: - Save Files
|
||||||
extern "C" void GameInteractor_ExecuteOnSaveFile(int32_t fileNum);
|
extern "C" void GameInteractor_ExecuteOnSaveFile(int32_t fileNum);
|
||||||
|
|
|
@ -142,6 +142,27 @@ void GameInteractor::RawAction::ForceInterfaceUpdate() {
|
||||||
Interface_Update(gPlayState);
|
Interface_Update(gPlayState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameInteractor::RawAction::UpdateActor(void* refActor) {
|
||||||
|
// Update actor again outside of their normal update cycle.
|
||||||
|
|
||||||
|
Actor* actor = static_cast<Actor*>(refActor);
|
||||||
|
|
||||||
|
// Sometimes the actor is destroyed in the previous Update, so check if the update function still exists.
|
||||||
|
if (actor->update != NULL) {
|
||||||
|
// Fix for enemies sometimes taking a "fake" hit, where their invincibility timer is
|
||||||
|
// reset but damage isn't applied.
|
||||||
|
if (actor->colorFilterTimer > 0) {
|
||||||
|
actor->colorFilterTimer--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This variable is used to not let the collider subscribe a second time when the actor update function
|
||||||
|
// is ran a second time, incorrectly applying double damage in some cases.
|
||||||
|
GameInteractor::State::SecondCollisionUpdate = 1;
|
||||||
|
actor->update(actor, gPlayState);
|
||||||
|
GameInteractor::State::SecondCollisionUpdate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams) {
|
GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams) {
|
||||||
|
|
||||||
if (!GameInteractor::CanSpawnEnemy()) {
|
if (!GameInteractor::CanSpawnEnemy()) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ bool GameInteractor::State::ReverseControlsActive = 0;
|
||||||
int32_t GameInteractor::State::DefenseModifier = 0;
|
int32_t GameInteractor::State::DefenseModifier = 0;
|
||||||
int32_t GameInteractor::State::RunSpeedModifier = 0;
|
int32_t GameInteractor::State::RunSpeedModifier = 0;
|
||||||
GIGravityLevel GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL;
|
GIGravityLevel GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL;
|
||||||
|
uint8_t GameInteractor::State::SecondCollisionUpdate = 0;
|
||||||
|
|
||||||
void GameInteractor::State::SetPacifistMode(bool active) {
|
void GameInteractor::State::SetPacifistMode(bool active) {
|
||||||
PacifistModeActive = active;
|
PacifistModeActive = active;
|
||||||
|
@ -79,3 +80,8 @@ int32_t GameInteractor_RunSpeedModifier() {
|
||||||
GIGravityLevel GameInteractor_GravityLevel() {
|
GIGravityLevel GameInteractor_GravityLevel() {
|
||||||
return GameInteractor::State::GravityLevel;
|
return GameInteractor::State::GravityLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - GameInteractor::State::SecondCollisionUpdate
|
||||||
|
uint8_t GameInteractor_SecondCollisionUpdate() {
|
||||||
|
return GameInteractor::State::SecondCollisionUpdate;
|
||||||
|
}
|
||||||
|
|
|
@ -6,11 +6,9 @@ extern "C" {
|
||||||
#include <z64.h>
|
#include <z64.h>
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
|
#include "functions.h"
|
||||||
extern SaveContext gSaveContext;
|
extern SaveContext gSaveContext;
|
||||||
extern PlayState* gPlayState;
|
extern PlayState* gPlayState;
|
||||||
extern void Play_PerformSave(PlayState* play);
|
|
||||||
extern s32 Health_ChangeBy(PlayState* play, s16 healthChange);
|
|
||||||
extern void Rupees_ChangeBy(s16 rupeeChange);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterInfiniteMoney() {
|
void RegisterInfiniteMoney() {
|
||||||
|
@ -257,6 +255,46 @@ void RegisterRupeeDash() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegisterHyperBosses() {
|
||||||
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
|
||||||
|
// Run the update function a second time to make bosses move and act twice as fast.
|
||||||
|
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
Actor* actor = static_cast<Actor*>(refActor);
|
||||||
|
|
||||||
|
uint8_t isBossActor =
|
||||||
|
actor->id == ACTOR_BOSS_GOMA || // Gohma
|
||||||
|
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
|
||||||
|
actor->id == ACTOR_BOSS_VA || // Barinade
|
||||||
|
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
|
||||||
|
(actor->id == 0 && actor->category == ACTORCAT_BOSS) || // Phantom Ganon/Ganondorf Energy Ball/Thunder
|
||||||
|
actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse
|
||||||
|
actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying)
|
||||||
|
actor->id == ACTOR_BOSS_MO || // Morpha
|
||||||
|
actor->id == ACTOR_BOSS_SST || // Bongo Bongo
|
||||||
|
actor->id == ACTOR_BOSS_TW || // Twinrova
|
||||||
|
actor->id == ACTOR_BOSS_GANON || // Ganondorf
|
||||||
|
actor->id == ACTOR_BOSS_GANON2; // Ganon
|
||||||
|
|
||||||
|
// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses.
|
||||||
|
if (isBossActor && !Player_InBlockingCsMode(gPlayState, player)) {
|
||||||
|
// Barinade needs to be updated in sequence to avoid unintended behaviour.
|
||||||
|
if (actor->id == ACTOR_BOSS_VA) {
|
||||||
|
// params -1 is BOSSVA_BODY
|
||||||
|
if (actor->params == -1) {
|
||||||
|
Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head;
|
||||||
|
while (actorList != NULL) {
|
||||||
|
GameInteractor::RawAction::UpdateActor(actorList);
|
||||||
|
actorList = actorList->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GameInteractor::RawAction::UpdateActor(actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void InitMods() {
|
void InitMods() {
|
||||||
RegisterInfiniteMoney();
|
RegisterInfiniteMoney();
|
||||||
RegisterInfiniteHealth();
|
RegisterInfiniteHealth();
|
||||||
|
@ -270,4 +308,5 @@ void InitMods() {
|
||||||
RegisterSwitchAge();
|
RegisterSwitchAge();
|
||||||
RegisterRupeeDash();
|
RegisterRupeeDash();
|
||||||
RegisterAutoSave();
|
RegisterAutoSave();
|
||||||
|
RegisterHyperBosses();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "objects/object_bdoor/object_bdoor.h"
|
#include "objects/object_bdoor/object_bdoor.h"
|
||||||
#include "soh/frame_interpolation.h"
|
#include "soh/frame_interpolation.h"
|
||||||
#include "soh/Enhancements/enemyrandomizer.h"
|
#include "soh/Enhancements/enemyrandomizer.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__GNUC__)
|
#if defined(_MSC_VER) || defined(__GNUC__)
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -2595,6 +2596,7 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
|
||||||
actor->colorFilterTimer--;
|
actor->colorFilterTimer--;
|
||||||
}
|
}
|
||||||
actor->update(actor, play);
|
actor->update(actor, play);
|
||||||
|
GameInteractor_ExecuteOnActorUpdate(actor, play);
|
||||||
func_8003F8EC(play, &play->colCtx.dyna, actor);
|
func_8003F8EC(play, &play->colCtx.dyna, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include "overlays/effects/ovl_Effect_Ss_HitMark/z_eff_ss_hitmark.h"
|
#include "overlays/effects/ovl_Effect_Ss_HitMark/z_eff_ss_hitmark.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
|
|
||||||
typedef s32 (*ColChkResetFunc)(PlayState*, Collider*);
|
typedef s32 (*ColChkResetFunc)(PlayState*, Collider*);
|
||||||
typedef void (*ColChkBloodFunc)(PlayState*, Collider*, Vec3f*);
|
typedef void (*ColChkBloodFunc)(PlayState*, Collider*, Vec3f*);
|
||||||
|
@ -1177,6 +1178,10 @@ static ColChkResetFunc sATResetFuncs[] = {
|
||||||
s32 CollisionCheck_SetAT(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider) {
|
s32 CollisionCheck_SetAT(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider) {
|
||||||
s32 index;
|
s32 index;
|
||||||
|
|
||||||
|
if (GameInteractor_SecondCollisionUpdate()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (FrameAdvance_IsEnabled(play) == true) {
|
if (FrameAdvance_IsEnabled(play) == true) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1206,9 +1211,15 @@ s32 CollisionCheck_SetAT(PlayState* play, CollisionCheckContext* colChkCtx, Coll
|
||||||
s32 CollisionCheck_SetAT_SAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider,
|
s32 CollisionCheck_SetAT_SAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider,
|
||||||
s32 index) {
|
s32 index) {
|
||||||
ASSERT(collider->shape <= COLSHAPE_QUAD);
|
ASSERT(collider->shape <= COLSHAPE_QUAD);
|
||||||
|
|
||||||
|
if (GameInteractor_SecondCollisionUpdate()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (FrameAdvance_IsEnabled(play) == true) {
|
if (FrameAdvance_IsEnabled(play) == true) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sATResetFuncs[collider->shape](play, collider);
|
sATResetFuncs[collider->shape](play, collider);
|
||||||
if (collider->actor != NULL && collider->actor->update == NULL) {
|
if (collider->actor != NULL && collider->actor->update == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1246,6 +1257,10 @@ static ColChkResetFunc sACResetFuncs[] = {
|
||||||
s32 CollisionCheck_SetAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider) {
|
s32 CollisionCheck_SetAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider) {
|
||||||
s32 index;
|
s32 index;
|
||||||
|
|
||||||
|
if (GameInteractor_SecondCollisionUpdate()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (FrameAdvance_IsEnabled(play) == true) {
|
if (FrameAdvance_IsEnabled(play) == true) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1275,9 +1290,15 @@ s32 CollisionCheck_SetAC(PlayState* play, CollisionCheckContext* colChkCtx, Coll
|
||||||
s32 CollisionCheck_SetAC_SAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider,
|
s32 CollisionCheck_SetAC_SAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider,
|
||||||
s32 index) {
|
s32 index) {
|
||||||
ASSERT(collider->shape <= COLSHAPE_QUAD);
|
ASSERT(collider->shape <= COLSHAPE_QUAD);
|
||||||
|
|
||||||
|
if (GameInteractor_SecondCollisionUpdate()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (FrameAdvance_IsEnabled(play) == true) {
|
if (FrameAdvance_IsEnabled(play) == true) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sACResetFuncs[collider->shape](play, collider);
|
sACResetFuncs[collider->shape](play, collider);
|
||||||
if (collider->actor != NULL && collider->actor->update == NULL) {
|
if (collider->actor != NULL && collider->actor->update == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1315,6 +1336,10 @@ static ColChkResetFunc sOCResetFuncs[] = {
|
||||||
s32 CollisionCheck_SetOC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider) {
|
s32 CollisionCheck_SetOC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider) {
|
||||||
s32 index;
|
s32 index;
|
||||||
|
|
||||||
|
if (GameInteractor_SecondCollisionUpdate()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (FrameAdvance_IsEnabled(play) == true) {
|
if (FrameAdvance_IsEnabled(play) == true) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1345,9 +1370,15 @@ s32 CollisionCheck_SetOC(PlayState* play, CollisionCheckContext* colChkCtx, Coll
|
||||||
*/
|
*/
|
||||||
s32 CollisionCheck_SetOC_SAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider,
|
s32 CollisionCheck_SetOC_SAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider,
|
||||||
s32 index) {
|
s32 index) {
|
||||||
|
|
||||||
|
if (GameInteractor_SecondCollisionUpdate()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (FrameAdvance_IsEnabled(play) == true) {
|
if (FrameAdvance_IsEnabled(play) == true) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(collider->shape <= COLSHAPE_QUAD);
|
ASSERT(collider->shape <= COLSHAPE_QUAD);
|
||||||
sOCResetFuncs[collider->shape](play, collider);
|
sOCResetFuncs[collider->shape](play, collider);
|
||||||
if (collider->actor != NULL && collider->actor->update == NULL) {
|
if (collider->actor != NULL && collider->actor->update == NULL) {
|
||||||
|
@ -1380,6 +1411,10 @@ s32 CollisionCheck_SetOC_SAC(PlayState* play, CollisionCheckContext* colChkCtx,
|
||||||
s32 CollisionCheck_SetOCLine(PlayState* play, CollisionCheckContext* colChkCtx, OcLine* collider) {
|
s32 CollisionCheck_SetOCLine(PlayState* play, CollisionCheckContext* colChkCtx, OcLine* collider) {
|
||||||
s32 index;
|
s32 index;
|
||||||
|
|
||||||
|
if (GameInteractor_SecondCollisionUpdate()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (FrameAdvance_IsEnabled(play) == true) {
|
if (FrameAdvance_IsEnabled(play) == true) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ void BossDodongo_DrawEffects(PlayState* play);
|
||||||
void BossDodongo_UpdateEffects(PlayState* play);
|
void BossDodongo_UpdateEffects(PlayState* play);
|
||||||
|
|
||||||
const ActorInit Boss_Dodongo_InitVars = {
|
const ActorInit Boss_Dodongo_InitVars = {
|
||||||
ACTOR_EN_DODONGO,
|
ACTOR_BOSS_DODONGO,
|
||||||
ACTORCAT_BOSS,
|
ACTORCAT_BOSS,
|
||||||
FLAGS,
|
FLAGS,
|
||||||
OBJECT_KINGDODONGO,
|
OBJECT_KINGDODONGO,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue