mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-06-13 14:07:25 -04:00
Ivan: New Farore’s Wind (#6735)
This commit is contained in:
committed by
GitHub
parent
eb4142835e
commit
8a1547a6e5
@@ -951,7 +951,6 @@ typedef struct Player {
|
||||
// #region SOH [Enhancements]
|
||||
// Upstream TODO: Rename this to make it more obvious it is apart of an enhancement
|
||||
/* */ u8 boomerangQuickRecall; // Has the player pressed the boomerang button while it's in the air still?
|
||||
/* */ u8 ivanFloating;
|
||||
/* */ u8 ivanDamageMultiplier;
|
||||
// #endregion
|
||||
} Player; // size = 0xA94
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <overlays/actors/ovl_Obj_Switch/z_obj_switch.h>
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ResourceManagerHelpers.h"
|
||||
#include <assets/objects/object_efc_tw/object_efc_tw.h>
|
||||
|
||||
#define FLAGS \
|
||||
(ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED | ACTOR_FLAG_HOOKSHOT_PULLS_PLAYER | \
|
||||
@@ -70,7 +71,6 @@ void EnPartner_Init(Actor* thisx, PlayState* play) {
|
||||
this->canMove = 1;
|
||||
this->shouldDraw = 1;
|
||||
this->hookshotTarget = NULL;
|
||||
GET_PLAYER(play)->ivanFloating = 0;
|
||||
|
||||
this->innerColor.r = 255.0f;
|
||||
this->innerColor.g = 255.0f;
|
||||
@@ -118,9 +118,13 @@ void EnPartner_Destroy(Actor* thisx, PlayState* play) {
|
||||
this->hookshotTarget = NULL;
|
||||
}
|
||||
|
||||
if (this->windEffect != NULL) {
|
||||
Actor_Kill(this->windEffect);
|
||||
this->windEffect = NULL;
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(play);
|
||||
if (player) {
|
||||
player->ivanFloating = 0;
|
||||
player->ivanDamageMultiplier = 1;
|
||||
}
|
||||
|
||||
@@ -360,6 +364,123 @@ void UseDekuStick(Actor* thisx, PlayState* play, u8 started) {
|
||||
}
|
||||
}
|
||||
|
||||
// #region IvanWindEffect
|
||||
|
||||
// Custom DemoEffect based on the effect that beams down on timeblocks when playing Song of Time
|
||||
|
||||
extern void DemoEffect_TimewarpShrink(f32 size);
|
||||
|
||||
void IvanWindEffect_UpdateShrink(DemoEffect* this, PlayState* play) {
|
||||
this->timeWarp.shrinkTimer += 20;
|
||||
|
||||
if (this->timeWarp.shrinkTimer <= 100) {
|
||||
f32 shrinkProgress = (100 - this->timeWarp.shrinkTimer) * 0.010f;
|
||||
DemoEffect_TimewarpShrink(shrinkProgress);
|
||||
} else {
|
||||
DemoEffect_TimewarpShrink(1.0f); // reset shared resource before killing
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
}
|
||||
|
||||
void IvanWindEffect_SetupFadeOut(DemoEffect* this) {
|
||||
this->updateFunc = IvanWindEffect_UpdateShrink;
|
||||
this->timeWarp.shrinkTimer = 0;
|
||||
}
|
||||
|
||||
void IvanWindEffect_UpdateIdle(DemoEffect* this, PlayState* play) {
|
||||
SkelCurve_Update(play, &this->skelCurve);
|
||||
}
|
||||
|
||||
void IvanWindEffect_Init(DemoEffect* this, PlayState* play) {
|
||||
SkelCurve_Init(play, &this->skelCurve, &gTimeWarpSkel, &gTimeWarpAnim);
|
||||
SkelCurve_SetAnim(&this->skelCurve, &gTimeWarpAnim, 1.0f, 59.0f, 1.0f, 8.0f);
|
||||
SkelCurve_Update(play, &this->skelCurve);
|
||||
|
||||
this->updateFunc = IvanWindEffect_UpdateIdle;
|
||||
|
||||
Actor_SetScale(&this->actor, 0.10f);
|
||||
DemoEffect_TimewarpShrink(1.0f);
|
||||
}
|
||||
|
||||
DemoEffect* IvanWindEffect_Spawn(EnPartner* ivan, PlayState* play) {
|
||||
PosRot spawn = {
|
||||
ivan->actor.world.pos,
|
||||
{ DEGF_TO_BINANG(90.0f), ivan->actor.world.rot.y, 0 },
|
||||
};
|
||||
|
||||
DemoEffect* windEffect =
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, spawn.pos.x, spawn.pos.y, spawn.pos.z, spawn.rot.x,
|
||||
spawn.rot.y, spawn.rot.z, DEMO_EFFECT_TIMEWARP_TIMEBLOCK_LARGE);
|
||||
|
||||
windEffect->envXluColor[1] = 100;
|
||||
windEffect->envXluColor[2] = 0;
|
||||
windEffect->initUpdateFunc = IvanWindEffect_Init;
|
||||
|
||||
return windEffect;
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
void EndFaroresWind(EnPartner* this, PlayState* play) {
|
||||
IvanWindEffect_SetupFadeOut(this->windEffect);
|
||||
this->windEffect = NULL;
|
||||
gSaveContext.magicState = MAGIC_STATE_RESET;
|
||||
this->itemTimer = 5;
|
||||
this->usedItem = 0xFF;
|
||||
}
|
||||
|
||||
void UseFaroresWind(EnPartner* this, PlayState* play, u8 started) {
|
||||
Player* player = GET_PLAYER(play);
|
||||
|
||||
if (started == 1) {
|
||||
if (gSaveContext.magic <= 0 || gSaveContext.magicState != MAGIC_STATE_IDLE) {
|
||||
Sfx_PlaySfxCentered(NA_SE_SY_ERROR);
|
||||
this->usedItem = 0xFF;
|
||||
return;
|
||||
}
|
||||
|
||||
this->windEffect = IvanWindEffect_Spawn(this, play);
|
||||
this->magicTimer = 0;
|
||||
}
|
||||
|
||||
if (started == 1 || started == 2) {
|
||||
func_8002F974(&this->actor, NA_SE_EV_WIND_TRAP - SFX_FLAG);
|
||||
|
||||
this->windEffect->actor.world.pos.x = this->actor.world.pos.x;
|
||||
this->windEffect->actor.world.pos.y = this->actor.world.pos.y;
|
||||
this->windEffect->actor.world.pos.z = this->actor.world.pos.z;
|
||||
this->windEffect->actor.shape.rot.y = this->actor.world.rot.y;
|
||||
|
||||
// based on BgHakaTrap_FanBlade_UpdateFanRotation
|
||||
Vec3f playerRel;
|
||||
Actor_WorldToActorCoords(&this->actor, &playerRel, &player->actor.world.pos);
|
||||
if ((fabsf(playerRel.x) < 70.0f) && (fabsf(playerRel.y) < 100.0f) && (playerRel.z < 400.0f) &&
|
||||
(playerRel.z > 0) && (player->currentBoots != PLAYER_BOOTS_IRON)) {
|
||||
float factor = (1.0f - (playerRel.z / 400.0f));
|
||||
factor = sqrtf(factor);
|
||||
player->pushedSpeed = factor * 10.0f;
|
||||
player->pushedYaw = this->actor.shape.rot.y;
|
||||
}
|
||||
|
||||
gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1;
|
||||
this->magicTimer--;
|
||||
if (this->magicTimer <= 0) {
|
||||
if (gSaveContext.magic <= 0) {
|
||||
gSaveContext.magic = 0;
|
||||
EndFaroresWind(this, play);
|
||||
return;
|
||||
}
|
||||
gSaveContext.magic--; // Note: after the `if` statement so that the last tick of magic
|
||||
this->magicTimer = 20; // gives the full count of frames
|
||||
}
|
||||
}
|
||||
|
||||
if (started == 0) {
|
||||
EndFaroresWind(this, play);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UseNuts(Actor* thisx, PlayState* play, u8 started) {
|
||||
EnPartner* this = (EnPartner*)thisx;
|
||||
|
||||
@@ -486,9 +607,6 @@ void UseSpell(Actor* thisx, PlayState* play, u8 started, u8 spellType) {
|
||||
case 1:
|
||||
GET_PLAYER(play)->ivanDamageMultiplier = 1;
|
||||
break;
|
||||
case 3:
|
||||
GET_PLAYER(play)->ivanFloating = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
this->usedSpell = 0;
|
||||
@@ -506,10 +624,6 @@ void UseSpell(Actor* thisx, PlayState* play, u8 started, u8 spellType) {
|
||||
case 2: // Nayru's
|
||||
GET_PLAYER(play)->invincibilityTimer = -10;
|
||||
break;
|
||||
case 3: // Farore's
|
||||
GET_PLAYER(play)->hoverBootsTimer = 10;
|
||||
GET_PLAYER(play)->ivanFloating = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1;
|
||||
@@ -577,7 +691,7 @@ void UseItem(uint8_t usedItem, u8 started, Actor* thisx, PlayState* play) {
|
||||
UseSpell(this, play, started, 2);
|
||||
break;
|
||||
case ITEM_FARORES_WIND:
|
||||
UseSpell(this, play, started, 3);
|
||||
UseFaroresWind(this, play, started);
|
||||
break;
|
||||
case ITEM_HAMMER:
|
||||
UseHammer(this, play, started);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <libultraship/libultra.h>
|
||||
#include "global.h"
|
||||
#include <overlays/actors/ovl_En_Boom/z_en_boom.h>
|
||||
#include <overlays/actors/ovl_Demo_Effect/z_demo_effect.h>
|
||||
|
||||
struct EnPartner;
|
||||
|
||||
@@ -43,6 +44,7 @@ typedef struct EnPartner {
|
||||
|
||||
EnBoom* boomerangActor;
|
||||
Actor* hookshotTarget;
|
||||
DemoEffect* windEffect;
|
||||
} EnPartner;
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -56,4 +58,4 @@ void EnPartner_Draw(Actor* thisx, PlayState* play);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -8070,11 +8070,7 @@ void func_8084029C(Player* this, f32 arg1) {
|
||||
arg1 = 7.25f;
|
||||
}
|
||||
|
||||
if ((this->currentBoots == PLAYER_BOOTS_HOVER ||
|
||||
(CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0) && this->ivanFloating)) &&
|
||||
!(this->actor.bgCheckFlags & 1) &&
|
||||
(this->hoverBootsTimer != 0 ||
|
||||
(CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0) && this->ivanFloating))) {
|
||||
if ((this->currentBoots == PLAYER_BOOTS_HOVER) && !(this->actor.bgCheckFlags & 1) && (this->hoverBootsTimer != 0)) {
|
||||
func_8002F8F0(&this->actor, NA_SE_PL_HOBBERBOOTS_LV - SFX_FLAG);
|
||||
} else if (func_8084021C(this->unk_868, arg1, 29.0f, 10.0f) || func_8084021C(this->unk_868, arg1, 29.0f, 24.0f)) {
|
||||
Player_PlaySteppingSfx(this, this->linearVelocity);
|
||||
@@ -11123,17 +11119,14 @@ void Player_UpdateInterface(PlayState* play, Player* this) {
|
||||
s32 Player_UpdateHoverBoots(Player* this) {
|
||||
s32 canHoverOnGround;
|
||||
|
||||
if ((this->currentBoots == PLAYER_BOOTS_HOVER ||
|
||||
(CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0) && this->ivanFloating)) &&
|
||||
(this->hoverBootsTimer != 0)) {
|
||||
if ((this->currentBoots == PLAYER_BOOTS_HOVER) && (this->hoverBootsTimer != 0)) {
|
||||
this->hoverBootsTimer--;
|
||||
} else {
|
||||
this->hoverBootsTimer = 0;
|
||||
}
|
||||
|
||||
canHoverOnGround =
|
||||
(this->currentBoots == PLAYER_BOOTS_HOVER ||
|
||||
(CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0) && this->ivanFloating)) &&
|
||||
(this->currentBoots == PLAYER_BOOTS_HOVER) &&
|
||||
((this->actor.yDistToWater >= 0.0f) || (func_80838144(sFloorType) >= 0) || func_8083816C(sFloorType));
|
||||
|
||||
if (canHoverOnGround && (this->actor.bgCheckFlags & 1) && (this->hoverBootsTimer != 0)) {
|
||||
@@ -12439,10 +12432,8 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList,
|
||||
Matrix_Pop();
|
||||
}
|
||||
|
||||
if ((this->currentBoots == PLAYER_BOOTS_HOVER ||
|
||||
(CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0) && this->ivanFloating)) &&
|
||||
!(this->actor.bgCheckFlags & 1) && !(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) &&
|
||||
(this->hoverBootsTimer != 0)) {
|
||||
if ((this->currentBoots == PLAYER_BOOTS_HOVER) && !(this->actor.bgCheckFlags & 1) &&
|
||||
!(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->hoverBootsTimer != 0)) {
|
||||
s32 sp5C;
|
||||
s32 hoverBootsTimer = this->hoverBootsTimer;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user