mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-06-10 05:03:29 -04:00
Ivan: Hookify and improve spawning (#6707)
Spawn/despawn Ivan immediately (not on next scene) Move Ivan’s boomerang code out of z_player.c
This commit is contained in:
committed by
GitHub
parent
44888584c4
commit
1c58bcc3e9
@@ -0,0 +1,48 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
#include "functions.h"
|
||||
extern PlayState* gPlayState;
|
||||
extern s16 gEnPartnerId;
|
||||
}
|
||||
|
||||
#define CVAR_NAME CVAR_ENHANCEMENT("IvanCoopModeEnabled")
|
||||
#define CVAR_VALUE CVarGetInteger(CVAR_NAME, 0)
|
||||
|
||||
static void SpawnIvan() {
|
||||
if (!gPlayState)
|
||||
return;
|
||||
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
if (Actor_Find(&gPlayState->actorCtx, gEnPartnerId, ACTORCAT_ITEMACTION))
|
||||
return;
|
||||
|
||||
PosRot& world = player->actor.world;
|
||||
Actor_Spawn(&gPlayState->actorCtx, gPlayState, gEnPartnerId, world.pos.x,
|
||||
world.pos.y + Player_GetHeight(player) + 5.0f, world.pos.z, 0, world.rot.y, 0, 1);
|
||||
}
|
||||
|
||||
static void KillIvan() {
|
||||
if (!gPlayState)
|
||||
return;
|
||||
|
||||
Actor* ivan = Actor_Find(&gPlayState->actorCtx, gEnPartnerId, ACTORCAT_ITEMACTION);
|
||||
if (ivan)
|
||||
Actor_Kill(ivan);
|
||||
}
|
||||
|
||||
static void RegisterIvanCoop() {
|
||||
if (CVAR_VALUE)
|
||||
SpawnIvan();
|
||||
else
|
||||
KillIvan();
|
||||
|
||||
COND_ID_HOOK(OnActorSpawn, ACTOR_PLAYER, CVAR_VALUE, [](void*) { SpawnIvan(); });
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterIvanCoop, { CVAR_NAME });
|
||||
@@ -1641,8 +1641,8 @@ void SohMenu::AddMenuEnhancements() {
|
||||
AddWidget(path, "Ivan the Fairy (Coop Mode)", WIDGET_CVAR_CHECKBOX)
|
||||
.CVar(CVAR_ENHANCEMENT("IvanCoopModeEnabled"))
|
||||
.Options(CheckboxOptions().Tooltip(
|
||||
"Enables Ivan the Fairy upon the next map change. Player 2 can control Ivan and press the C-Buttons to "
|
||||
"use items and mess with Player 1!"));
|
||||
"Enables Ivan the Fairy. Player 2 can control Ivan and press the C-Buttons to use items and mess with "
|
||||
"Player 1!"));
|
||||
AddWidget(path, "Dogs Follow You Everywhere", WIDGET_CVAR_CHECKBOX)
|
||||
.CVar(CVAR_ENHANCEMENT("DogFollowsEverywhere"))
|
||||
.Options(CheckboxOptions().Tooltip("Allows dogs to follow you anywhere you go, even if you leave the Market."));
|
||||
|
||||
@@ -683,12 +683,6 @@ void Play_Init(GameState* thisx) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0)) {
|
||||
Actor_Spawn(&play->actorCtx, play, gEnPartnerId, GET_PLAYER(play)->actor.world.pos.x,
|
||||
GET_PLAYER(play)->actor.world.pos.y + Player_GetHeight(GET_PLAYER(play)) + 5.0f,
|
||||
GET_PLAYER(play)->actor.world.pos.z, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
// nextEntranceIndex was not initialized, so the previous value was carried over during soft resets.
|
||||
gPlayState->nextEntranceIndex = gSaveContext.entranceIndex;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ void EnPartner_Draw(Actor* thisx, PlayState* play);
|
||||
void EnPartner_SpawnSparkles(EnPartner* this, PlayState* play, s32 sparkleLife);
|
||||
|
||||
void Player_RequestQuake(PlayState* play, s32 speed, s32 y, s32 countdown);
|
||||
s32 spawn_boomerang_ivan(EnPartner* this, PlayState* play);
|
||||
|
||||
static InitChainEntry sInitChain[] = {
|
||||
ICHAIN_VEC3F_DIV1000(scale, 8, ICHAIN_STOP),
|
||||
@@ -114,6 +113,17 @@ void EnPartner_Destroy(Actor* thisx, PlayState* play) {
|
||||
s32 pad;
|
||||
EnPartner* this = (EnPartner*)thisx;
|
||||
|
||||
if (this->hookshotTarget != NULL) {
|
||||
Actor_Kill(this->hookshotTarget);
|
||||
this->hookshotTarget = NULL;
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(play);
|
||||
if (player) {
|
||||
player->ivanFloating = 0;
|
||||
player->ivanDamageMultiplier = 1;
|
||||
}
|
||||
|
||||
LightContext_RemoveLight(play, &play->lightCtx, this->lightNodeGlow);
|
||||
LightContext_RemoveLight(play, &play->lightCtx, this->lightNodeNoGlow);
|
||||
|
||||
@@ -408,7 +418,19 @@ void UseBoomerang(Actor* thisx, PlayState* play, u8 started) {
|
||||
if (this->itemTimer <= 0) {
|
||||
if (started == 1) {
|
||||
this->itemTimer = 20;
|
||||
spawn_boomerang_ivan(&this->actor, play);
|
||||
|
||||
f32 posX = (Math_SinS(this->actor.shape.rot.y) * 1.0f) + this->actor.world.pos.x;
|
||||
f32 posZ = (Math_CosS(this->actor.shape.rot.y) * 1.0f) + this->actor.world.pos.z;
|
||||
s32 yaw = this->actor.shape.rot.y;
|
||||
EnBoom* boomerang =
|
||||
(EnBoom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOOM, posX, this->actor.world.pos.y + 7.0f, posZ,
|
||||
this->actor.focus.rot.x, yaw, 0, 0);
|
||||
|
||||
this->boomerangActor = &boomerang->actor;
|
||||
if (boomerang != NULL) {
|
||||
boomerang->returnTimer = 20;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_IT_BOOMERANG_THROW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
||||
#include <overlays/actors/ovl_En_Partner/z_en_partner.h>
|
||||
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
|
||||
#include "soh/Enhancements/enhancementTypes.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
@@ -346,26 +345,6 @@ void Player_Action_CsAction(Player* this, PlayState* play);
|
||||
#pragma region[SoH]
|
||||
u8 gWalkSpeedToggle;
|
||||
|
||||
s32 spawn_boomerang_ivan(EnPartner* this, PlayState* play) {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
f32 posX = (Math_SinS(this->actor.shape.rot.y) * 1.0f) + this->actor.world.pos.x;
|
||||
f32 posZ = (Math_CosS(this->actor.shape.rot.y) * 1.0f) + this->actor.world.pos.z;
|
||||
s32 yaw = this->actor.shape.rot.y;
|
||||
EnBoom* boomerang = (EnBoom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOOM, posX, this->actor.world.pos.y + 7.0f,
|
||||
posZ, this->actor.focus.rot.x, yaw, 0, 0);
|
||||
|
||||
this->boomerangActor = &boomerang->actor;
|
||||
if (boomerang != NULL) {
|
||||
boomerang->returnTimer = 20;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_IT_BOOMERANG_THROW);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Sets a flag according to which type of flag is specified in player->pendingFlag.flagType
|
||||
// and which flag is specified in player->pendingFlag.flagID.
|
||||
void Player_SetPendingFlag(Player* this, PlayState* play) {
|
||||
|
||||
Reference in New Issue
Block a user