From 6ee69baf2f72e5ee44b142bf5717d728a957f759 Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Sun, 9 Aug 2026 01:32:31 -0400 Subject: [PATCH 1/4] BossSB2 and BossPlankton work --- configure.py | 2 +- src/SB/Game/zNPCTypeBossPlankton.cpp | 154 +++++++++++++++++---------- src/SB/Game/zNPCTypeBossPlankton.h | 19 ++-- src/SB/Game/zNPCTypeBossSB2.cpp | 121 ++++++++++++++++++--- src/SB/Game/zNPCTypeBossSB2.h | 15 ++- 5 files changed, 223 insertions(+), 88 deletions(-) diff --git a/configure.py b/configure.py index 89dd620ba..0cc24fa2d 100644 --- a/configure.py +++ b/configure.py @@ -610,7 +610,7 @@ def MatchingFor(*versions): Object(Matching, "SB/Game/zNPCGoalBoss.cpp"), Object(NonMatching, "SB/Game/zNPCTypePrawn.cpp"), Object(Equivalent, "SB/Game/zNPCTypeBossSB1.cpp"), - Object(NonMatching, "SB/Game/zNPCTypeBossSB2.cpp"), + Object(NonMatching, "SB/Game/zNPCTypeBossSB2.cpp", extra_cflags=["-sym on"]), Object(Matching, "SB/Core/x/xJaw.cpp"), Object(NonMatching, "SB/Game/zNPCTypeBossPatrick.cpp"), Object(NonMatching, "SB/Game/zNPCTypeBossPlankton.cpp"), diff --git a/src/SB/Game/zNPCTypeBossPlankton.cpp b/src/SB/Game/zNPCTypeBossPlankton.cpp index b270d2f4b..fbbffcfbc 100644 --- a/src/SB/Game/zNPCTypeBossPlankton.cpp +++ b/src/SB/Game/zNPCTypeBossPlankton.cpp @@ -1055,21 +1055,22 @@ xAnimTable* ZNPC_AnimTable_BossPlankton() return table; } -void zNPCBPlankton::Init(xEntAsset* asset) //66% +// Can't do this until zNPCBoss has a constructor? +// zNPCBPlankton::zNPCBPlankton(S32 myType) +// { +// } + +void zNPCBPlankton::Init(xEntAsset* asset) // 83.97% { - ::init_sound(); + init_sound(); zNPCCommon::Init(asset); - flg_move = 1; - flg_vuln = 1; + this->flg_move = 1; + this->flg_vuln = 1; xNPCBasic::RestoreColFlags(); - territory_size = 0; - played_intro = 0; - zNPCBPlankton::init_beam(); - xAnimPlay* play = 0; - - // Is being called incorrectly. - // play is a temp fix to get it to build - zNPCBPlankton::aim_gun(play, &gun_tilt, &move.dest, 0); + this->territory_size = 0; + this->played_intro = 0; + this->init_beam(); + this->model->Anim->BeforeAnimMatrices = aim_gun; } void zNPCBPlankton::Setup() @@ -1091,12 +1092,54 @@ void zNPCBPlankton::Reset() { if (newsfish != 0) { + newsfish->Reset(); } + reset_sound(); zNPCCommon::Reset(); - zNPCBPlankton::reset_beam(); - memset((void*)flag.updated, 0, 0x10); - zNPCBPlankton::face_player(); + this->reset_beam(); + memset(&flag, 0, 0x10); + this->face_player(); + this->turn.vel = 0.0f; + this->move.vel = 0.0f; + this->move.dest = this->location(); + this->flag.move = MOVE_ORBIT; + this->ambush_delay = 0.0f; + this->old_player_health = 0; + scan_cronies(); + + if (crony != 0) + { + this->mode = MODE_BUDDY; + this->stun_duration = tweak.mode_buddy.stun_duration; + this->newsfish = 0; + } + else + { + this->mode = MODE_HARASS; + this->active_territory = 0; + this->stun_duration = tweak.mode_harass.stun_duration; + + if (this->newsfish != 0) + { + this->newsfish->TalkOnScreen(TRUE); + } + } + + this->reset_speed(); + this->refresh_orbit(); + this->follow_player(); + this->reset_territories(); + + if (mode == MODE_BUDDY) + { + psy_instinct->GoalSet(0x4e47424b, 1); // 'NGBK' + } + else + { + vanish(); + psy_instinct->GoalSet(0x4e47424d, 1); // 'NGBM' + } } void zNPCBPlankton::Destroy() @@ -1106,59 +1149,53 @@ void zNPCBPlankton::Destroy() void zNPCBPlankton::Process(xScene* xscn, F32 dt) { - // This function needs a lot of work, writing most of these comments - // so that i can resume where i left off when i return to it - - // territory_data& t ; - //xCollis& coll; - xEnt* platform; - S32 i; - - //xVec3& player_loc; xPsyche* psy = psy_instinct; - if ((flag.updated == false) && (flag.updated = 1, played_intro == false)) + if ((this->flag.updated == false) && (this->flag.updated = 1, this->played_intro == false)) { - zNPCBPlankton::say(0, 0, true); - played_intro = true; + this->say(0, 0, true); + this->played_intro = true; } - beam.update(dt); - delay = delay + dt; - if ((mode == 1) && (territory->fuse_detected = player_left_territory(), psy_instinct != 0)) + + this->beam.update(dt); + this->delay = this->delay + dt; + + if ((this->mode == MODE_HARASS) && (this->player_left_territory() & 0xFF)) { - stun_duration = 0.0f; + this->ambush_delay = 0.0f; psy_instinct->GoalSet(NPC_GOAL_BPLANKTONAMBUSH, 1); } - // uvar1 = zNPCCommon::SomethingWonderful(); - //if ((uVar1 & 0x23) == 0) - // { - // psy_instinct->xPsyche::Timestep(dt, 0) - // } - if (flag.face_player = false) + + if ((zNPCCommon::SomethingWonderful() & 0x23) == 0) { - // iVar4 = *(int *)(DAT_803c0c5c + 0x4c); - // pfVar2 = (float *)location__13zNPCBPlanktonCFv(param_9); - // param_3 = (double)*(float *)(iVar4 + 0x30); - // param_2 = (double)(*(float *)(iVar4 + 0x38) - pfVar2[2]); - // assign__5xVec2Fff((double)(float)(param_3 - (double)*pfVar2),param_2,(float *)(param_9 + 0x460)); - // normalize__5xVec2Fv((float *)(param_9 + 0x460)); + psy_instinct->Timestep(dt, 0); } - update_follow(dt); - update_turn(dt); - update_move(dt); - update_animation(dt); //uvar5 = update anim - check_player_damage(); //uvar1 = check_player_damage - if (psy_instinct != 0) //psy_instinct isnt right, needs (uvar1 & 0xff) + + if (this->flag.face_player != FALSE) { - zEntPlayer_Damage(0, 1); //needs xBase* instead of 0 + RwMatrix* mat = globals.player.ent.model->Mat; + const xVec3& loc = location(); + this->turn.dir.assign(mat->pos.x - loc.x, mat->pos.z - loc.z); + this->turn.dir.normalize(); } - update_aim_gun(dt); - update_dialog(dt); - //bVar3 = visible__17xLaserBoltEmitterCFv(param_9 + 0x3b8); - //if (bVar3) { - // *(uint *)(param_9 + 0x234) = *(uint *)(param_9 + 0x234) | 2; - //} - //Process__10zNPCCommonFP6xScenef(param_1,param_9,param_10); + + this->update_follow(dt); + this->update_turn(dt); + this->update_move(dt); + this->update_animation(dt); + + if (this->check_player_damage() & 0xFF) + { + zEntPlayer_Damage((xBase*)this, 1); + } + + this->update_aim_gun(dt); + this->update_dialog(dt); + if (this->beam.visible() & 0xFF) + { + this->flg_xtrarend = this->flg_xtrarend | 2; + } + zNPCCommon::Process(xscn, dt); } S32 zNPCBPlankton::SysEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam, @@ -1323,9 +1360,10 @@ void zNPCBPlankton::update_follow(F32 dt) } } -void zNPCBPlankton::check_player_damage() +U8 zNPCBPlankton::check_player_damage() { // TODO + return 0; } void zNPCBPlankton::init_beam() diff --git a/src/SB/Game/zNPCTypeBossPlankton.h b/src/SB/Game/zNPCTypeBossPlankton.h index 205e92d85..7de61c6c3 100644 --- a/src/SB/Game/zNPCTypeBossPlankton.h +++ b/src/SB/Game/zNPCTypeBossPlankton.h @@ -44,8 +44,8 @@ struct zNPCBPlankton : zNPCBoss struct move_info { - xVec3 dest; - xVec3 vel; + xVec3 dest; // 0x474 + xVec3 vel; // 0x480 xVec3 accel; xVec3 max_vel; }; @@ -76,7 +76,7 @@ struct zNPCBPlankton : zNPCBoss mode_enum mode; F32 delay; //0x2c8 xQuat gun_tilt; - F32 ambush_delay; + F32 ambush_delay; // 0x2dc F32 beam_duration; // 0x2e0 F32 stun_duration; // 0x2e4 xDecalEmitter beam_ring; @@ -90,8 +90,8 @@ struct zNPCBPlankton : zNPCBoss } orbit; struct { - xVec2 dir; - F32 vel; + xVec2 dir; // 0x460 + F32 vel; // 0x468 F32 accel; F32 max_vel; } turn; @@ -108,7 +108,7 @@ struct zNPCBPlankton : zNPCBoss zNPCBoss* crony; territory_data territory[8]; S32 territory_size; //0x694 - S32 active_territory; + S32 active_territory; // 0x698 zNPCNewsFish* newsfish; U32 old_player_health; //0x6a0 U8 played_intro; //0x6a4 @@ -129,7 +129,7 @@ struct zNPCBPlankton : zNPCBoss S32 next_goal(); void update_turn(F32); void update_move(F32); - void check_player_damage(); + U8 check_player_damage(); void reset_territories(); void update_animation(F32); void update_follow(F32); @@ -145,15 +145,16 @@ struct zNPCBPlankton : zNPCBoss U32 crony_attacking() const; void next_territory(); S32 have_cronies() const; - S32 player_left_territory(); + S32 player_left_territory() const; void say(int, int, bool); void sickum(); - void aim_gun(xAnimPlay*, xQuat*, xVec3*, int); + static void aim_gun(xAnimPlay*, xQuat*, xVec3*, int); void here_boy(); void follow_player(); void follow_camera(); void reset_speed(); void refresh_orbit(); + void scan_cronies(); xVec3& location() const; void face_player(); diff --git a/src/SB/Game/zNPCTypeBossSB2.cpp b/src/SB/Game/zNPCTypeBossSB2.cpp index caac06720..97449e3d7 100644 --- a/src/SB/Game/zNPCTypeBossSB2.cpp +++ b/src/SB/Game/zNPCTypeBossSB2.cpp @@ -1,6 +1,7 @@ #include "zNPCTypeBossSB2.h" #include "PowerPC_EABI_Support/MSL_C++/MSL_Common/Include/new.h" +#include "rwplcore.h" #include "xLightKit.h" #include "zNPCGoalCommon.h" #include @@ -1174,6 +1175,23 @@ void zNPCB_SB2::Init(xEntAsset* asset) this->init_slugs(); } +namespace +{ + + void response_curve::init(U64, const void*, U64, const char*, const char**, const tweak_callback*, + void*) + { + + } + +} + +void zNPCB_SB2::ParseINI() +{ + zNPCCommon::ParseINI(); + tweak.load(parmdata, pdatsize); +} + void zNPCB_SB2::Setup() { xEnt* ent; @@ -1353,15 +1371,13 @@ void zNPCB_SB2::decompose() void zNPCB_SB2::show_nodes() { - // Haven't found 0x74 S32 i; for (i = 0; i < 9; i++) { - if (nodes->ent != 0){ - xEntShow(nodes->ent); + if (nodes[i].ent != 0){ + xEntShow(nodes[i].ent); } } - } void zNPCB_SB2::ouchie() @@ -1409,32 +1425,56 @@ void zNPCB_SB2::reset_speed() S32 zNPCB_SB2::player_platform() { - if (((globals.player.ent.collis->colls->flags & 1) != 0)) + if (((globals.player.ent.collis->colls->flags & 1) == 0) + || (globals.player.ent.collis->colls->optr == 0) + || (((xEnt*)globals.player.ent.collis->colls->optr)->baseType != 6)) { - return 1; + return 0; } + // &platforms offset 0x92C, size 0x5C0 + return NULL; } -void zNPCB_SB2::activate_hand(zNPCB_SB2::hand_enum hand, bool) +void zNPCB_SB2::activate_hand(zNPCB_SB2::hand_enum hand, bool active) { - hands[0].hurt_player = 1; - hands[0].hit_platforms = 0x10; - hands[0].ent->penby = 0x10; + this->hands[hand].hurt_player = 1; + this->hands[hand].hit_platforms = active; + this->hands[hand].ent->penby = 0x10; } void zNPCB_SB2::deactivate_hand(zNPCB_SB2::hand_enum hand) { - hands[0].hit_platforms = 0; - hands[0].hurt_player = 0x10; - hands[0].ent->penby = 0; + this->hands[hand].hit_platforms = 0; + this->hands[hand].hurt_player = 0; + this->hands[hand].ent->penby = 0x10; } S32 zNPCB_SB2::player_on_ground() const { - return 0; - // TODO + RwMatrix* mat = globals.player.ent.model->Mat; + + if (globals.player.Health == 0) + { + return FALSE; + } + + if (mat->pos.y >= tweak.ground_y + tweak.ground_zone_height) + { + return FALSE; + } + + const xVec3& home = get_home(); + + F32 dx = mat->pos.x - home.x; + F32 dz = mat->pos.z - home.z; + + xVec2 pos = {}; + pos.x = dx; + pos.y = dz; + + return pos.length2() < tweak.ground_radius * tweak.ground_radius; } void zNPCB_SB2::emit_slug(zNPCB_SB2::slug_enum which) @@ -1457,6 +1497,28 @@ void zNPCB_SB2::emit_slug(zNPCB_SB2::slug_enum which) } } +S32 zNPCB_SB2::slugs_ready() const { + const slug_data* slug = &slugs[0]; + const slug_data* end = &slug[3]; + for (; slug != end; slug++) { + if (slug->stage != SLUG_AIM || (slug->stage_delay > 0.0f)) { + return FALSE; + } + } + return TRUE; +} + +S32 zNPCB_SB2::slugs_inactive() const { + const slug_data* slug = &slugs[0]; + const slug_data* end = &slug[3]; + for (; slug != end; slug++) { + if (slug->stage != SLUG_INACTIVE) { + return FALSE; + } + } + return TRUE; +} + void zNPCB_SB2::fire_slug(zNPCB_SB2::slug_enum which, zNPCB_SB2::platform_data& target) { slug_data& slug = slugs[which]; @@ -1482,6 +1544,11 @@ void zNPCB_SB2::reset_stage() stage_delay = 0; } +void zNPCB_SB2::set_vulnerable(bool vulnerable) +{ + +} + void zNPCB_SB2::destroy_glow_light() { xLightKit_Destroy(&glow_light.kit); @@ -1708,6 +1775,19 @@ S32 zNPCGoalBossSB2Chop::Exit(F32 dt, void* updCtxt) return xGoal::Exit(dt, updCtxt); } +S32 zNPCGoalBossSB2Chop::can_start() const +{ + if (owner.player_platform() == 0) + { + return 0; + } else + { + + } + + return 0; +} + xFactoryInst* zNPCGoalBossSB2Karate::create(S32 who, RyzMemGrow* grow, void* info) { return new (who, grow) zNPCGoalBossSB2Karate(who, (zNPCB_SB2&)*info); @@ -1715,6 +1795,17 @@ xFactoryInst* zNPCGoalBossSB2Karate::create(S32 who, RyzMemGrow* grow, void* inf S32 zNPCGoalBossSB2Karate::Enter(F32 dt, void* updCtxt) { + U8* it = this->emitted; + U8* end = it + sizeof(this->emitted); + + this->started = 0; + this->owner.flag.face_player = 1; + + while (it != end) + { + *it++ = 0; + } + return zNPCGoalCommon::Enter(dt, updCtxt); } diff --git a/src/SB/Game/zNPCTypeBossSB2.h b/src/SB/Game/zNPCTypeBossSB2.h index e7d735c12..33a5eae2b 100644 --- a/src/SB/Game/zNPCTypeBossSB2.h +++ b/src/SB/Game/zNPCTypeBossSB2.h @@ -23,9 +23,11 @@ struct response_curve U32 nodes; // offset 0x8, U32 active_node; // offset 0xC, - static void init(U32, const void*, U32, const char*, const char**, const tweak_callback*, + // static void init(U32, const void*, U32, const char*, const char**, const tweak_callback*, + // void*); + static void init(U64, const void*, U64, const char*, const char**, const tweak_callback*, void*); - void end_t() const; + static void end_t(); }; struct node @@ -120,7 +122,7 @@ struct zNPCB_SB2 : zNPCBoss enum slug_stage { - SLUG_INACTIVE, //0x152c if is used slugs[0].stage + SLUG_INACTIVE, SLUG_AIM, SLUG_DELAY, SLUG_DYING, @@ -131,7 +133,7 @@ struct zNPCB_SB2 : zNPCBoss { slug_stage stage; U8 spun; - U8 abandoned; //0x1531 if [0] + U8 abandoned; F32 time; F32 stage_delay; xEnt* ent; @@ -227,6 +229,7 @@ struct zNPCB_SB2 : zNPCBoss zNPCB_SB2(S32 myType); void Init(xEntAsset* asset); + void ParseINI(); void Setup(); void SelfSetup(); void Reset(); @@ -269,10 +272,11 @@ struct zNPCB_SB2 : zNPCBoss S32 player_on_ground() const; void emit_slug(zNPCB_SB2::slug_enum which); S32 slugs_ready() const; + S32 slugs_inactive() const; void reset_stage(); void fire_slug(zNPCB_SB2::slug_enum which, zNPCB_SB2::platform_data& target); void abandon_slugs(); - void set_vulnerable(bool); + void set_vulnerable(bool vulnerable); void say(int); void choose_hand(); xVec3& location() const; @@ -404,6 +408,7 @@ struct zNPCGoalBossSB2Chop : zNPCGoalCommon static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); S32 Enter(F32 dt, void* updCtxt); S32 Exit(F32 dt, void* updCtxt); + S32 can_start() const; }; struct zNPCGoalBossSB2Karate : zNPCGoalCommon From 9fc4d106c70e1062e2c6e0789b4a410371634420 Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Sun, 9 Aug 2026 19:51:56 -0400 Subject: [PATCH 2/4] player_update 40% --- src/SB/Game/zEntPlayer.cpp | 1338 +++++++++++++++++++++++++++++++++++- 1 file changed, 1337 insertions(+), 1 deletion(-) diff --git a/src/SB/Game/zEntPlayer.cpp b/src/SB/Game/zEntPlayer.cpp index 0dcc3dadb..572d3dd54 100644 --- a/src/SB/Game/zEntPlayer.cpp +++ b/src/SB/Game/zEntPlayer.cpp @@ -104,6 +104,8 @@ static xVec3 lastDeltaPos; static xVec3 lastFloorNorm; static xEnt* lastFloorEnt; static U32 surfSticky; +static const U8 SBBBashBones[] = { 0, 1, 2, 3, 4, 5, 0 }; +static const U8 SBBBounceBones[] = { 0, 1, 2, 3, 0 }; static F32 surfSlideStart = DEG2RAD(20); static F32 surfSlideStop = DEG2RAD(10); F32 surfSlickRatio; @@ -146,6 +148,9 @@ static F32 sReticleAlpha; static xMat4x3 sReticleMat; static S32 sTypeOfTarget; static F32 sTimeToRetarget; +static F32 sRingDelay; +static F32 sLastInvulnEmit; +static xEntCollis old_collis; class xEnt* gReticleTarget; // This struct was anonymous in the dwarf but it seemed to do better with codegen to name it @@ -173,6 +178,7 @@ static xVec3 req_motion; static xVec3 precollide_motion; static RwRaster* sBowlingLaneRast; _CurrentPlayer gCurrentPlayer; +_CurrentPlayer lastgCurrentPlayer; F32 floor_safe_tmr; static F32 bbash_start_ht; static F32 bbash_end_tmr; @@ -264,6 +270,51 @@ static float sTongueDblSpeedMult; static void PlayerSwingUpdate(xEnt* ent, F32 mag, F32 angle, F32 dt); static S32 CheckObjectAgainstMeleeBound(xEnt* ent, void* data); static void zEntPlayer_PredictionUpdate(xEnt* ent, F32 dt); +static void zEntPlayerEGenUpdate(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayer_SNDPlayDelayed(F32 seconds); +static void zEntPlayer_UpdateVelocityBlur(); +static void speak_update(F32 dt); +static void zEntPlayer_SpringboardFX(xEnt* ent, F32 dt); +void zEntPlayer_SNDPlay(_tagePlayerSnd player_snd, F32 delay); +void zEntPlayer_SNDStop(_tagePlayerSnd player_snd); +void zEntPickup_CheckAllPickupsAgainstPlayer(xScene* sc, F32 dt); +static xEnt* GetPatrickTarget(xEnt* ent); +static xEnt* zEntPlayer_FindGrabEnt(xEnt* ent, zScene* zsc, S32* failed); +static U8 StunBubbleTrail(xAnimSingle* anim); +void zFXPatrickStun(const xVec3* pos); +extern zParEmitter* gEmitBFX; +static S32 MeleeAttackBoundCollide(xEnt* ent, zScene* zscn, xBound* meleeB); +static U8 BubbleBashContrails(xAnimSingle* anim); +static U8 BubbleBounceContrails(xAnimSingle* anim); +void zEntPlayer_setBoulderMode(U32 mode); +void xScrFxFade(iColor_tag* base, iColor_tag* dest, F32 seconds, void (*callback)(), S32 hold); +S32 xScrFxIsFading(); +static void DoWallJumpCheck(); +U32 iRayHitsEnv(const xRay3* r, const xEnv* env, xCollis* coll); +void zGustUpdateEnt(xEnt*, xScene*, F32, void*); +void zEntPlayerCollide(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayer_CheckCritterContact(xEnt* ent, F32 dt); +void xEntBoulder_ApplyForces(xEntCollis* collis); +xSurface* zSurfaceGetSurface(const xCollis* coll); +S32 zSurfaceGetStep(const xSurface* surf); +void xEntBoulder_AddForce(xEntBoulder* boulder, xVec3* force); +void PlayerLedgeUpdate(xEnt* ent, xScene* sc, F32 dt); +static S32 zEntPlayerKnockToSafety(xEnt* ent); +void zEntPlayerFloorUpdate(xEnt* ent, xScene* sc, F32 dt); +void PlayerTeeterCheck(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerSurfDamageUpdate(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerDriveUpdate(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerJumpUpdate(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerTSlideUpdate(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerVelUpdate(xEnt* ent, xScene* sc, F32 dt); +namespace oob_state +{ + void force_start(); +} +namespace bungee_state +{ + bool update(xScene* s, F32 dt); +} void zEntPlayer_SpawnWandBubbles(xVec3* center, U32 count) { @@ -2555,7 +2606,1292 @@ static U32 BoulderRollDoneCheck() boulderRollShouldEnd; } -static void zEntPlayer_Update(xEnt* ent, xScene* sc, F32 dt); +static void zEntPlayer_Update(xEnt* ent, xScene* sc, F32 dt) +{ + if (((gCurrentPlayer == eCurrentPlayerPatrick) && (globals.player.model_patrick == NULL)) || + ((gCurrentPlayer == eCurrentPlayerSandy && (globals.player.model_sandy == NULL)))) + { + gCurrentPlayer = eCurrentPlayerSpongeBob; + } + + if (dt < 0.00001f) + { + return; + } + + last_update_dt = update_dt; + update_dt = dt; + zEntPlayer_SNDPlayDelayed(dt); + + for (S32 i = 0; i < ePlayerStreamSnd_Total; i++) + { + if (sPlayerStreamSndTimer[i].timer > 0.0f) + { + sPlayerStreamSndTimer[i].timer -= dt; + if (sPlayerStreamSndTimer[i].timer < 0.0f) + { + sPlayerStreamSndTimer[i].timer = 0.0f; + } + } + } + + gSpongeBall = 0; + if (sLassoInfo->swingTarget == NULL) + { + zEntPlayer_UpdateVelocityBlur(); + } + + zEntPlayer_PredictionUpdate(ent, dt); + zEntPlayerEGenUpdate(ent, sc, dt); + + if (gReticleTarget != NULL) + { + sReticleRot += 8.0f * dt; + if (sReticleRot > 6.2831854820251465f) + { + sReticleRot -= 6.2831854820251465f; + } + + sReticleAlpha += 3.0f * dt; + if (sReticleAlpha > 1.0f) + { + sReticleAlpha = 1.0f; + } + } + + if (globals.player.ControlOff || globals.player.Health == 0 || in_goo) + { + if (globals.player.bubblebowl != NULL && globals.player.bubblebowl->update != NULL) + { + zEntEvent(&globals.player.ent, globals.player.bubblebowl, 0x25); + } + } + + if (bungee_state::update(sc, dt)) + { + return; + } + if (cruise_bubble::update(sc, dt)) + { + return; + } + if (oob_state::update(*sc, dt)) + { + return; + } + + zEntPlayer_SpringboardFX(ent, dt); + ::speak_update(dt); + + if (gCurrentPlayer == eCurrentPlayerSpongeBob) + { + U32 flags = globals.player.ent.model->Anim->Single->State->UserFlags & 0x1e; + if (flags == 2 || flags == 4) + { + if (sPlayerSndID[gCurrentPlayer][ePlayerSnd_Sneak] == 0 && sPlayerSndSneakDelay == 0.0f) + { + zEntPlayer_SNDPlay(ePlayerSnd_Sneak, 0.0f); + } + } + else + { + zEntPlayer_SNDStop(ePlayerSnd_Sneak); + sPlayerSndSneakDelay = 0.3f; + } + } + else + { + xSndStop(sPlayerSndID[0][ePlayerSnd_Sneak]); + sPlayerSndID[0][ePlayerSnd_Sneak] = 0; + sPlayerSndSneakDelay = 0.3f; + } + + if (strcmp(ent->model->Anim->Single->State->Name, "BbowlWindup01") == 0) + { + ent->model->Anim->Single->CurrentSpeed = + 1.0f + sBubbleBowlTimer / globals.player.g.BubbleBowlTimeDelay; + if (ent->model->Anim->Single->CurrentSpeed > 2.0f) + { + ent->model->Anim->Single->CurrentSpeed = 2.0f; + } + + sBubbleBowlTimer += dt; + if (!sShouldBubbleBowl) + { + if (globals.player.ControlOff || !(globals.pad0->on & XPAD_BUTTON_O) || + sBubbleBowlTimer > globals.player.g.BubbleBowlTimeDelay) + { + if (sBubbleBowlTimer > globals.player.g.BubbleBowlTimeDelay) + { + sBubbleBowlTimer = globals.player.g.BubbleBowlTimeDelay; + } + sShouldBubbleBowl = 1; + sBubbleBowlMultiplier = + 1.0f + globals.player.g.BubbleBowlPercentIncrease * + (sBubbleBowlTimer / globals.player.g.BubbleBowlTimeDelay); + } + } + } + + zEntPickup_CheckAllPickupsAgainstPlayer(sc, dt); + + if (globals.player.g.CheatPlayerSwitch && globals.player.carry.grabbed == NULL && + globals.player.SundaeTimer < 0.0f) + { + if (globals.player.ControlOff == 0) + { + if (globals.pad0->pressed & XPAD_BUTTON_UP) + { + gCurrentPlayer = eCurrentPlayerSpongeBob; + } + else if ((globals.pad0->pressed & XPAD_BUTTON_LEFT) && + globals.player.model_patrick != NULL) + { + gCurrentPlayer = eCurrentPlayerPatrick; + } + else if ((globals.pad0->pressed & XPAD_BUTTON_RIGHT) && + globals.player.model_sandy != NULL) + { + gCurrentPlayer = eCurrentPlayerSandy; + } + } + } + + if (gCurrentPlayer != lastgCurrentPlayer) + { + if (gCurrentPlayer == eCurrentPlayerSpongeBob) + { + *globals.player.model_spongebob->Mat = *ent->model->Mat; + ent->model = globals.player.model_spongebob; + globals.player.s = &globals.player.sb; + gReticleTarget = NULL; + globals.player.IsCoptering = 0; + } + else if (gCurrentPlayer == eCurrentPlayerPatrick) + { + if (globals.player.model_patrick != NULL) + { + *globals.player.model_patrick->Mat = *ent->model->Mat; + ent->model = globals.player.model_patrick; + globals.player.s = &globals.player.patrick; + gReticleTarget = NULL; + globals.player.IsBubbleBowling = 0; + globals.player.IsCoptering = 0; + } + } + else if (gCurrentPlayer == eCurrentPlayerSandy) + { + if (globals.player.model_sandy != NULL) + { + *globals.player.model_sandy->Mat = *ent->model->Mat; + ent->model = globals.player.model_sandy; + globals.player.s = &globals.player.sandy; + gReticleTarget = NULL; + globals.player.IsBubbleBowling = 0; + } + } + } + + lastgCurrentPlayer = gCurrentPlayer; + globals.player.Inv_PatsSock_CurrentLevel = globals.player.Inv_PatsSock[zSceneGetLevelIndex()]; + globals.player.Inv_LevelPickups_CurrentLevel = + globals.player.Inv_LevelPickups[zSceneGetLevelIndex()]; + + xMat4x3* targetMat = xEntGetFrame(&globals.player.ent); + xCameraSetTargetMatrix(&globals.camera, targetMat); + xCameraSetTargetOMatrix(&globals.camera, &sCameraLastMat); + zCameraSetPlayerVel(&globals.player.ent.frame->vel); + + sGrabFound = NULL; + sGrabFailed = 0; + + if (ent->model == globals.player.model_patrick) + { + if (globals.player.carry.grabbed != NULL) + { + sTimeToRetarget -= dt; + if (sTimeToRetarget < 0.0f) + { + xEnt* oldTarget = gReticleTarget; + sTimeToRetarget = 0.25f; + gReticleTarget = GetPatrickTarget(ent); + sTypeOfTarget = 3; + if (gReticleTarget != oldTarget) + { + sReticleAlpha = 0.0f; + } + } + } + else + { + sTimeToRetarget -= dt; + if (sTimeToRetarget < 0.0f) + { + xEnt* oldTarget = gReticleTarget; + sTimeToRetarget = 0.25f; + gReticleTarget = zEntPlayer_FindGrabEnt(ent, (zScene*)sc, NULL); + sTypeOfTarget = 2; + if (gReticleTarget != oldTarget) + { + sReticleAlpha = 0.0f; + } + } + } + + if (globals.player.carry.grabbed == NULL && globals.player.ControlOff == 0 && + (globals.pad0->pressed & XPAD_BUTTON_O)) + { + if (gReticleTarget != NULL && sTypeOfTarget == 2) + { + sGrabFound = gReticleTarget; + } + else + { + sGrabFound = zEntPlayer_FindGrabEnt(ent, (zScene*)sc, &sGrabFailed); + } + } + + xVec3 pos = *(xVec3*)&ent->model->Mat->pos; + xAnimSingle* single = globals.player.ent.model->Anim->Single; + xAnimState* state = single->State; + if (gPTankDisable == 0 && StunBubbleTrail(single)) + { + zFX_SpawnBubbleTrail((xVec3*)&globals.player.ent.model->Mat->pos, 1); + } + + if (sRingDelay > 0.0f) + { + F32 delta = dt; + if (delta > sRingDelay) + { + delta = sRingDelay; + } + sRingDelay -= delta; + } + + if (strcmp(state->Name, "Stunfall") == 0 && single->Time < 0.25f) + { + xEntCollis* collis = ent->collis; + if (sRingDelay != 0.0f || collis->colls[0].dist <= 2.0f) + { + if (sRingDelay == 0.0f) + { + pos.x += collis->colls[0].tohit.x * collis->colls[0].dist; + pos.y += collis->colls[0].tohit.y * collis->colls[0].dist + 0.2f; + pos.z += collis->colls[0].tohit.z * collis->colls[0].dist; + zFXPatrickStun(&pos); + sRingDelay = 2.0f; + } + + if (gPTankDisable) + { + xParEmitterCustomSettings info; + info.custom_flags = 0x30e; + info.pos = pos; + + for (S32 i = 0; i < 100; i++) + { + F32 angle = (6.2831854820251465f * (F32)i) / 100.0f; + info.vel.x = 4.0f * icos(angle); + info.vel.y = 1.25f; + info.vel.z = 4.0f * isin(angle); + info.life.set(1.0f, 1.0f, 1.0f, 0); + info.size_birth.set(0.05f, 0.05f, 1.0f, 0); + info.size_death.set(0.25f, 0.25f, 1.0f, 0); + xParEmitterEmitCustom(gEmitBFX, 0.01666666753590107f, &info); + } + } + else + { + zFX_SpawnBubbleSlam(&pos, 24, 10.0f, 12.0f, 2.0f); + } + } + } + } + + if (globals.player.SundaeTimer >= 0.0f) + { + globals.player.SundaeTimer -= dt; + if (globals.player.SundaeTimer <= 0.0f) + { + globals.player.SpeedMult = 1.0f; + globals.player.SundaeTimer = -1.0f; + } + else + { + sLastInvulnEmit += dt; + if (sLastInvulnEmit > 0.02f) + { + sLastInvulnEmit = 0.0f; + + xParEmitterCustomSettings info2; + xVec3Copy(&info2.pos, xBoundCenter(&ent->bound)); + + xVec3 scaledDir; + xVec3SMul(&scaledDir, &globals.player.PredictCurrDir, + globals.player.PredictCurrVel); + xVec3 rightVec; + xVec3SMul(&rightVec, (xVec3*)&ent->model->Mat->right, 1.0f); + xVec3Add(&scaledDir, &scaledDir, &rightVec); + xVec3 atVec; + xVec3SMul(&atVec, (xVec3*)&ent->model->Mat->at, 1.0f); + xVec3Add(&info2.vel, &scaledDir, &atVec); + + info2.vel_angle_variation = 0.075f; + info2.rate.set(150.0f, 150.0f, 1.0f, 0); + info2.life.set(1.5f, 2.0f, 1.0f, 2); + xParEmitterEmitCustom(sEmitStankBreath, 0.01666666753590107f, &info2); + } + } + } + + if ((ent->model->Anim->Single->State->UserFlags & 0x1000) || tslide_ground != 0) + { + xBound meleeB; + meleeB.sph.center.x = + ent->bound.sph.center.x + (1.25f * dt) * globals.player.SlideTrackVel.x; + meleeB.sph.center.y = ent->bound.sph.center.y + (1.25f * dt) * ent->frame->vel.y; + meleeB.sph.center.z = + ent->bound.sph.center.z + (1.25f * dt) * globals.player.SlideTrackVel.z; + meleeB.sph.r = ent->bound.sph.r + 0.3f; + + xQCData qc; + xQuickCullForBound(&qc, &meleeB); + MeleeAttackBoundCollide(ent, (zScene*)sc, &meleeB); + } + + const U8* boneList = NULL; + if (ent->model == globals.player.model_spongebob) + { + xAnimSingle* single = globals.player.ent.model->Anim->Single; + if (BubbleBashContrails(single)) + { + boneList = SBBBashBones; + } + else if (BubbleBounceContrails(single)) + { + boneList = SBBBounceBones; + } + } + + if (boneList != NULL) + { + U32 count = 0; + for (const U8* p = boneList; *p != 0; p++) + { + count++; + } + + xVec3* posbuf = (xVec3*)xMemPushTemp(count * 2 * sizeof(xVec3)); + xVec3* velbuf = posbuf + count; + if (posbuf != NULL) + { + const U8* bp = boneList; + xVec3* pp = posbuf; + xVec3* vp = velbuf; + for (U32 j = 0; j < count; j++, pp++, vp++, bp++) + { + xMat4x3 boneMat; + xMat4x3Mul(&boneMat, &((xMat4x3*)ent->model->Mat)[*bp], (xMat4x3*)ent->model->Mat); + *pp = *(xVec3*)&boneMat.pos; + + pp->x += 0.1f * (xurand() - 0.5f); + pp->y += 0.1f * (xurand() - 0.5f); + pp->z += 0.1f * (xurand() - 0.5f); + + vp->x = 0.2f * (xurand() - 0.5f); + vp->y = 0.2f * (xurand() - 0.5f); + vp->z = 0.2f * (xurand() - 0.5f); + } + + zParPTankSpawnBubbles(posbuf, velbuf, count, 1.0f); + xMemPopTemp(posbuf); + } + } + + if ((globals.player.ControlOff & ~0x4400) || globals.cmgr != NULL) + { + globals.player.ControlOffTimer = 0.0f; + } + else if (globals.sceneCur->sceneID == 'PG12') + { + zEntPlayer_setBoulderMode(1); + } + + globals.player.KnockBackTimer -= dt; + if (globals.player.KnockBackTimer < 0.0f) + { + globals.player.KnockBackTimer = 0.0f; + } + + globals.player.KnockIntoAirTimer -= dt; + if (globals.player.KnockIntoAirTimer < 0.0f) + { + globals.player.KnockIntoAirTimer = 0.0f; + } + + globals.player.Sneak = 0; + xAnimSingle* single2 = globals.player.ent.model->Anim->Single; + + if (globals.player.ControlOff == 0 && globals.pad0->on == 0 && + abs(globals.pad0->analog1.x) <= globals.player.g.AnalogMin && + abs(globals.pad0->analog1.y) <= globals.player.g.AnalogMin) + { + if (single2->State != NULL && (single2->State->UserFlags & 1)) + { + globals.player.IdleMinorTimer += dt; + globals.player.IdleMajorTimer += dt; + if (!surfSticky) + { + globals.player.IdleSitTimer += dt; + } + + if (globals.player.IdleMinorTimer == 0.0f) + { + globals.player.IdleMinorTimer = 0.0001f; + } + } + } + else + { + globals.player.IdleMinorTimer = 0.0f; + globals.player.IdleMajorTimer = -3.0f; + globals.player.IdleSitTimer = 0.0f; + } + + if (globals.player.ScareTimer > 0.0f) + { + globals.player.ScareTimer -= dt; + if (globals.player.ScareTimer < 0.0f) + { + globals.player.ScareTimer = 0.0f; + } + } + + if (globals.player.VictoryTimer > 0.0f) + { + globals.player.VictoryTimer -= dt; + if (globals.player.VictoryTimer < 0.0f) + { + globals.player.VictoryTimer = 0.0f; + } + } + + if (globals.player.BadGuyNearTimer > 0.0f) + { + globals.player.BadGuyNearTimer -= dt; + if (globals.player.BadGuyNearTimer < 0.0f) + { + globals.player.BadGuyNearTimer = 0.0f; + } + } + + if (globals.player.DamageTimer > 0.0f) + { + globals.player.DamageTimer -= dt; + if (globals.player.DamageTimer < 0.0f) + { + globals.player.DamageTimer = 0.0f; + } + } + + if (globals.player.ControlOffTimer > 0.0f) + { + globals.player.ControlOffTimer -= dt; + if (globals.player.ControlOffTimer < 0.0f) + { + globals.player.ControlOffTimer = 0.0f; + } + } + + if (globals.player.CowerTimer > 0.0f) + { + globals.player.CowerTimer -= dt; + if (globals.player.CowerTimer < 0.0f) + { + globals.player.CowerTimer = 0.0f; + } + } + + if (globals.player.FallDeathTimer > 0.0f) + { + globals.player.FallDeathTimer -= dt; + if (globals.player.FallDeathTimer < 0.0f) + { + globals.player.FallDeathTimer = 0.0f; + } + } + + if (globals.player.HelmetTimer > 0.0f) + { + globals.player.HelmetTimer -= dt; + if (globals.player.HelmetTimer < 0.0f) + { + globals.player.HelmetTimer = 0.0f; + } + } + + if (sPlayerSndSneakDelay > 0.0f) + { + sPlayerSndSneakDelay -= dt; + if (sPlayerSndSneakDelay < 0.0f) + { + sPlayerSndSneakDelay = 0.0f; + } + } + + idle_tmr += dt; + if (globals.player.ControlOff & 0x8) + { + idle_tmr = 0.0f; + } + + if (inact_tmr > 0.0f) + { + inact_tmr -= dt; + if (inact_tmr < 0.0f) + { + inact_tmr = 0.0f; + } + } + + stun_power_tmr += dt; + + iColor_tag black = { 0, 0, 0, 255 }; + iColor_tag clear = { 0, 0, 0, 0 }; + + if (globals.player.Health == 0) + { + if (globals.player.DamageTimer >= 0.3f && single2->Time == 0.0f && !xScrFxIsFading() && + (single2->State->UserFlags & 0x400)) + { + xScrFxFade(&clear, &black, 0.3f, NULL, 1); + globals.player.DamageTimer = 0.33333301544189453f; + } + + if (globals.player.DamageTimer <= 0.0f) + { + zGameStateSwitch(2); + HealthReset(); + } + } + + sCameraLastMat = *(xMat4x3*)ent->model->Mat; + sWallJumpResult = WallJumpResult_NoJump; + + U32 flags2 = globals.player.ent.model->Anim->Single->State->UserFlags & 0x1e; + if (flags2 == 10) + { + DoWallJumpCheck(); + } + + if (gCurrentPlayer == eCurrentPlayerSpongeBob) + { + xAnimSingle* sbSingle = ent->model->Anim->Single; + if (sbSingle->CurrentSpeed == 0.0f && sbSingle->Blend->State == NULL && + strcmp(sbSingle->State->Name, "Idle01") == 0) + { + sbSingle->CurrentSpeed = sbSingle->State->Speed; + } + } + + xEntBeginUpdate(ent, sc, dt); + + xAnimState* state = globals.player.ent.model->Anim->Single->State; + if (bbash_end_tmr != 0.0f) + { + if (strncmp(state->Name, "Bbash", 5) != 0) + { + bbash_end_tmr -= dt; + if (bbash_end_tmr < 0.0f) + { + bbash_end_tmr = 0.0f; + } + zCameraMinTargetHeightClear(); + } + } + + S32 spinFlag = 0; + S32 spinFlag2 = 0; + if (strcmp(state->Name, "Idle01") == 0 && single2->Time != 0.0f) + { + if (single2->Time >= globals.player.g.BSpinMinFrame) + { + spinFlag = 1; + } + if (spinFlag && single2->Time < globals.player.g.BSpinMaxFrame) + { + spinFlag2 = 1; + } + } + globals.player.IsBubbleSpinning = spinFlag2; + + if (tslide_ground == 0 && + (strcmp(state->Name, "JumpStart01") == 0 || strcmp(state->Name, "JumpLift01") == 0 || + strcmp(state->Name, "Fall01") == 0 || + (strcmp(state->Name, "DJumpApex01") == 0 && ent->frame->vel.y > 0.0f))) + { + if (sPlayerCollAdjust <= 0.5f) + { + sPlayerCollAdjust += 3.0f * dt; + if (sPlayerCollAdjust > 0.5f) + { + sPlayerCollAdjust = 0.5f; + } + } + else + { + sPlayerCollAdjust -= 5.0f * dt; + if (sPlayerCollAdjust < 0.5f) + { + sPlayerCollAdjust = 0.5f; + } + } + } + else if (tslide_ground == 0 && ent->frame->vel.y > 0.5f) + { + if (sPlayerCollAdjust <= 0.25f) + { + sPlayerCollAdjust += 3.0f * dt; + if (sPlayerCollAdjust > 0.25f) + { + sPlayerCollAdjust = 0.25f; + } + } + else + { + sPlayerCollAdjust -= 5.0f * dt; + if (sPlayerCollAdjust < 0.25f) + { + sPlayerCollAdjust = 0.25f; + } + } + } + else + { + sPlayerCollAdjust -= 5.0f * dt; + if (sPlayerCollAdjust < 0.0f) + { + sPlayerCollAdjust = 0.0f; + } + } + + ent->frame->oldmat.pos.y += sPlayerCollAdjust; + ent->frame->mat.pos.y += sPlayerCollAdjust; + + if (globals.player.ShockRadius != 0.0f) + { + globals.player.ShockRadius += 6.0f * dt; + if (globals.player.ShockRadius > 4.0f) + { + globals.player.ShockRadius = 4.0f; + } + + S32 count = 0; + for (S32 i = 0; i < sc->num_npcs; i++) + { + count++; + } + + if (globals.player.ShockRadius == 4.0f) + { + globals.player.ShockRadius = 0.0f; + } + else + { + globals.player.ShockRadiusOld = globals.player.ShockRadius; + } + } + + zGooCollsBegin(); + + if (globals.player.WallJumpState == k_WALLJUMP_LAUNCH || + globals.player.WallJumpState == k_WALLJUMP_FLIGHT || strncmp(state->Name, "Bbash", 5) == 0) + { + sHackStuckTimer = 0.0f; + } + else + { + F32 velLen2 = xVec3Length2(&ent->frame->vel); + F32 lastVelLen2 = xVec3Length2(&tslide_lastrealvel); + xEntCollis* collis = ent->collis; + + if (collis->colls[0].flags & 1) + { + if (sHackStuckTimer == 0.0f) + { + ent->frame->vel = sHackStuckVel; + ent->frame->oldvel = sHackStuckVel; + } + sHackStuckTimer = 0.0f; + } + else if (velLen2 >= 36.0f && lastVelLen2 <= 0.25f && + ((collis->colls[2].flags & 1) || (collis->colls[3].flags & 1) || + (collis->colls[4].flags & 1) || (collis->colls[5].flags & 1))) + { + if (sHackStuckTimer == 0.0f) + { + sHackStuckVel = ent->frame->vel; + } + sHackStuckTimer = 0.15000000596046448f; + } + else if (sHackStuckTimer != 0.0f) + { + sHackStuckTimer -= dt; + if (sHackStuckTimer < 0.0f) + { + sHackStuckTimer = 0.0f; + } + ent->frame->vel = sHackStuckVel; + ent->frame->oldvel = sHackStuckVel; + } + + if (sHackStuckTimer != 0.0f) + { + if (!sHackStuckSetDir) + { + xRay3 ray; + ray.origin = ent->frame->oldmat.pos; + ray.origin.y += 0.5f; + ray.dir.x = 0.0f; + ray.dir.y = -1.0f; + ray.dir.z = 0.0f; + ray.max_t = 1.5f; + ray.flags = 0xc00; + + xCollis rayColl; + rayColl.flags = 0x200; + + iRayHitsEnv(&ray, globals.sceneCur->env, &rayColl); + if (rayColl.flags & 1) + { + if (xabs(rayColl.norm.y) < 0.9998499751091003f) + { + sHackStuckDir.x = rayColl.norm.x * rayColl.norm.y; + sHackStuckDir.y = + -(rayColl.norm.x * rayColl.norm.x + rayColl.norm.z * rayColl.norm.z); + sHackStuckDir.z = rayColl.norm.z * rayColl.norm.y; + xVec3Normalize(&sHackStuckDir, &sHackStuckDir); + sHackStuckSetDir = 1; + } + } + } + + if (sHackStuckSetDir) + { + F32 speed = xsqrt(velLen2); + if (speed > 10.0f) + { + speed = 10.0f; + } + + ent->frame->vel.x = speed * sHackStuckDir.x; + ent->frame->vel.y = speed * sHackStuckDir.y; + ent->frame->vel.z = speed * sHackStuckDir.z; + ent->frame->oldvel = ent->frame->vel; + } + else + { + sHackStuckDir.x = 0.0f; + sHackStuckDir.y = 0.0f; + sHackStuckDir.z = 0.0f; + } + } + } + + sDriveVel.x = 0.0f; + sDriveVel.y = 0.0f; + sDriveVel.z = 0.0f; + + S32 numSubsteps = 1; + if (globals.player.HangEnt == NULL && sLassoInfo->swingTarget == NULL) + { + if (dt > 0.1f) + { + numSubsteps = 6; + } + else if (dt > 0.0833333358168602f) + { + numSubsteps = 5; + } + else if (dt > 0.06666667014360428f) + { + numSubsteps = 4; + } + else if (dt > 0.05f) + { + numSubsteps = 3; + } + else + { + numSubsteps = 2; + } + } + + F32 substepDt = dt / (F32)numSubsteps; + F32 halfSubstepDt = 0.5f * substepDt; + F32 thirteenSubstepDt = 13.0f * substepDt; + + for (S32 i = 0; i < numSubsteps; i++) + { + xVec3 prePhysicsPos = ent->frame->mat.pos; + xEntApplyPhysics(ent, sc, substepDt); + xEntMove(ent, sc, substepDt); + req_motion = ent->frame->dpos; + + xVec3 preDrivePos = ent->frame->mat.pos; + xEntDriveUpdate(&globals.player.drv, sc, substepDt, NULL); + sDriveVel.x += ent->frame->mat.pos.x - preDrivePos.x; + sDriveVel.y += ent->frame->mat.pos.y - preDrivePos.y; + sDriveVel.z += ent->frame->mat.pos.z - preDrivePos.z; + + if (((zScene*)sc)->baseCount[eBaseTypeGust] != 0) + { + xFFX* ffx = ent->ffx; + while (ffx != NULL) + { + if (ffx->doEffect == zGustUpdateEnt) + { + if (globals.player.JumpState == 3 || surfSlickRatio == 0.0f) + { + xFFXTurnOn(ffx); + } + else + { + xFFXTurnOff(ffx); + if (gust_data.gust_on != 0) + { + memset(&gust_data, 0, sizeof(gust_data)); + } + } + } + ffx = ffx->next; + } + } + else + { + gust_data.gust_on = 0; + } + + xFFXApply(ent, sc, substepDt); + + xVec3 posDelta; + xVec3Sub(&posDelta, &ent->frame->mat.pos, &prePhysicsPos); + + if (globals.player.cheat_mode == 0 && + (globals.player.JumpState == 0 || globals.player.JumpState == 1) && + globals.player.FallDeathTimer == 0.0f) + { + ent->frame->mat.pos.y -= halfSubstepDt; + + F32 dotVal = + globals.player.floor_norm.x * posDelta.x + globals.player.floor_norm.z * posDelta.z; + if (dotVal > 0.0f && + !(req_motion.x == 0.0f && req_motion.z == 0.0f && surfSlickRatio == 0.0f)) + { + globals.player.slope = -1; + F32 speed = xsqrt(dotVal); + ent->frame->mat.pos.y -= speed; + } + else + { + globals.player.slope = (dotVal >= 0.0f) ? 0 : 1; + } + } + + if (lastFloorEnt != NULL) + { + if (surfSlickRatio == 0.0f) + { + if (globals.player.SlipFadeTimer > 0.0f) + { + F32 f = (globals.player.SlipFadeTimer / 0.800000011920929f) * substepDt * 30.0f; + ent->frame->mat.pos.x += f * lastFloorNorm.x; + ent->frame->mat.pos.z += f * lastFloorNorm.z; + } + } + else + { + ent->frame->mat.pos.x += thirteenSubstepDt * globals.player.floor_norm.x; + F32 mag = xsqrt(globals.player.floor_norm.x * globals.player.floor_norm.x + + globals.player.floor_norm.z * globals.player.floor_norm.z); + ent->frame->mat.pos.y -= thirteenSubstepDt * mag; + ent->frame->mat.pos.z += thirteenSubstepDt * globals.player.floor_norm.z; + } + } + + xVec3Sub(&precollide_motion, &ent->frame->mat.pos, &ent->frame->oldmat.pos); + zEntPlayerCollide(ent, sc, substepDt); + + xEntCollis* collis2 = ent->collis; + S32 anyStuck = (collis2->colls[2].flags & 1) || (collis2->colls[3].flags & 1) || + (collis2->colls[4].flags & 1); + S32 stuckAgainstWall = anyStuck || (collis2->colls[5].flags & 1); + + if (!(collis2->colls[0].flags & 1) && !(globals.player.ControlOff & ~0x4000)) + { + if (stuckAgainstWall) + { + xVec3* modelPos = (xVec3*)&globals.player.ent.model->Mat->pos; + if (stuck_timer == 0.0f) + { + not_stuck_timer = 0.0f; + stuck_start_loc = *modelPos; + } + + xVec3 diff; + xVec3Sub(&diff, modelPos, &stuck_start_loc); + F32 dist2 = xVec3Length2(&diff); + if (dist2 <= 1.0f) + { + stuck_timer += substepDt; + if (stuck_timer > 1.5f && globals.player.Health != 0 && in_goo == 0) + { + oob_state::force_start(); + } + } + else + { + stuck_timer = 0.0f; + not_stuck_timer = 0.0f; + } + + F32 speed2 = xsqrt(dist2); + xprintf("Stuck: %.2f %.2f %.2f\n", stuck_timer, not_stuck_timer, speed2); + } + else + { + not_stuck_timer += substepDt; + if (not_stuck_timer > 0.2f) + { + stuck_timer = 0.0f; + not_stuck_timer = 0.0f; + } + } + } + else + { + stuck_timer = 0.0f; + not_stuck_timer = 0.0f; + } + + memcpy(&old_collis, ent->collis, sizeof(old_collis)); + zEntPlayerCollide(ent, sc, substepDt); + memcpy(ent->collis, &old_collis, sizeof(old_collis)); + zEntPlayer_CheckCritterContact(ent, substepDt); + xEntBoulder_ApplyForces(ent->collis); + } + + if (dt > 0.0001f) + { + sDriveVel.x /= dt; + sDriveVel.y /= dt; + sDriveVel.z /= dt; + } + + xVec3Sub(&update_motion, &ent->frame->mat.pos, &ent->frame->oldmat.pos); + + if (globals.player.cheat_mode == 0) + { + xCollis qcCollis; + qcCollis.flags = 0; + + RwBBox* bbox = xEnvGetBBox(globals.sceneCur->env); + xBox envBox; + envBox.upper = *(xVec3*)&bbox->sup; + envBox.lower = *(xVec3*)&bbox->inf; + + if (((zScene*)globals.sceneCur)->zen != NULL) + { + envBox.upper.y += ((zScene*)globals.sceneCur)->zen->easset->loldHeight; + } + + xSphereHitsBox(&ent->bound.sph, &envBox, &qcCollis); + if ((qcCollis.flags & 0x11) == 0) + { + zEntEvent(ent, 0x11); + } + } + + if (sCatchCapsuleTimer != 0.0f) + { + sCatchCapsuleTimer -= 0.01666666753590107f; + if (sCatchCapsuleTimer <= 0.0f) + { + sCatchCapsuleTimer = 0.0f; + } + } + + if (globals.player.cheat_mode == 0) + { + sHackStuckSetDir = 0; + if (xVec3Length(&update_motion) > 0.00001f) + { + S32 firstPass = 1; + for (;;) + { + xVec3 start = ent->frame->oldmat.pos; + F32 r = ent->bound.sph.r; + start.y += r * 0.7f; + xVec3 end; + xVec3Add(&end, &start, &update_motion); + + xSweptSphere sws; + xSweptSpherePrepare(&sws, &start, &end, r * 0.45f); + if (!xSweptSphereToScene(&sws, sc, ent, ent->collType)) + { + break; + } + xSweptSphereGetResults(&sws); + + if (sCatchCapsuleTimer == 0.0f) + { + sCatchCapsuleTimer = 0.3f; + } + + if (!firstPass) + { + ent->frame->mat.pos = ent->frame->oldmat.pos; + break; + } + + xVec3 pos = start; + xVec3 nextEnd; + xVec3Add(&nextEnd, &pos, &update_motion); + + static xSweptSphere sSweptSphereStack[3]; + xVec3 dir = { 0.0f, 0.0f, 0.0f }; + S32 restart = 0; + + for (S32 i = 0; i < 3; i++) + { + xSweptSphere* cur = &sSweptSphereStack[i]; + xSweptSpherePrepare(cur, &pos, &nextEnd, r * 0.45f); + if (!xSweptSphereToScene(cur, sc, ent, ent->collType)) + { + if (i != 0) + { + pos = nextEnd; + break; + } + xVec3Add(&nextEnd, &pos, &update_motion); + *cur = sws; + } + else + { + xSweptSphereGetResults(cur); + } + + if (i == 0) + { + dir = cur->worldTangent; + sHackStuckSetDir = 1; + } + else + { + xVec3Cross(&dir, &cur->worldNormal, &sSweptSphereStack[i - 1].worldNormal); + if (xVec3Length2(&dir) < 0.0000001f) + { + restart = 1; + break; + } + xVec3Normalize(&dir, &dir); + if (xVec3Dot(&dir, (xVec3*)&ent->model->Mat->at) < 0.0f) + { + dir.x = -dir.x; + dir.y = -dir.y; + dir.z = -dir.z; + } + if (i == 1) + { + sHackStuckSetDir = 1; + } + } + + F32 delta = cur->dist - cur->curdist; + xVec3 hd; + hd.x = delta * ent->model->Mat->at.x; + hd.y = delta * ent->model->Mat->at.y; + hd.z = delta * ent->model->Mat->at.z; + F32 dp = xVec3Dot(&hd, &dir); + pos = cur->worldPos; + nextEnd.x = pos.x + dp * dir.x; + nextEnd.y = pos.y + dp * dir.y; + nextEnd.z = pos.z + dp * dir.z; + } + + if (restart) + { + ent->frame->mat.pos = ent->frame->oldmat.pos; + break; + } + + ent->frame->mat.pos.x = pos.x; + ent->frame->mat.pos.y = pos.y + r * 0.7f; + ent->frame->mat.pos.z = pos.z; + zEntPlayerCollide(ent, sc, 0.01666666753590107f); + xVec3Sub(&update_motion, &ent->frame->mat.pos, &ent->frame->oldmat.pos); + firstPass = 0; + } + } + } + + xEntCollis* floorColl = ent->collis; + F32 stepAmount = dt * 1.5f; + for (S32 i = 2; i < 6; i++) + { + xCollis* c = &floorColl->colls[i]; + if (c->flags & 1) + { + F32 dotVal = c->hdng.x * req_motion.x + c->hdng.z * req_motion.z; + xSurface* surf = zSurfaceGetSurface(c); + if (dotVal > 0.0f && c->hdng.y < 0.0f && zSurfaceGetStep(surf)) + { + ent->frame->mat.pos.y += stepAmount; + floorColl->colls[0] = *c; + c->flags = 0; + } + } + } + + zGooCollsEnd(); + if (globals.player.JumpState == 0 && in_goo == 0) + { + sGooKnockedTimer -= dt; + if (sGooKnockedTimer < 0.0f) + { + sGooKnockedToSafety = 0; + sGooKnockedTimer = 0.0f; + } + } + + lin_goo = in_goo; + xCollis* floorHit = &ent->collis->colls[0]; + if (floorHit->flags & 1) + { + xBase* floorObj = (xBase*)floorHit->optr; + if (floorObj == NULL) + { + in_goo = 0; + } + else + { + if (floorObj->baseType == eBaseTypeButton) + { + zEntButton_Hold((_zEntButton*)floorObj, 0x400); + } + + F32 gooDepth; + if (!zGooIs((xEnt*)floorObj, gooDepth, 1)) + { + in_goo = 0; + } + else if (sGooKnockedToSafety == 0 && zEntPlayerKnockToSafety(ent)) + { + globals.player.DamageTimer = 0.0f; + zEntPlayer_Damage(floorObj, 0); + sGooKnockedToSafety = 1; + sGooKnockedTimer = 0.25f; + } + else + { + in_goo = 1; + } + + globals.player.CanJump = 1; + globals.player.Jump_CanDouble = 1; + } + } + + if (in_goo == 0) + { + in_goo_tmr = 0.0f; + } + else if (ent->collis->colls[0].flags & 1) + { + in_goo_tmr += dt; + if (xrand() > 0x40) + { + zFX_SpawnBubbleTrail((xVec3*)&ent->model->Mat->pos, 1); + } + } + + if (globals.player.drv.driver != NULL) + { + zCameraTranslate(&globals.camera, sDriveVel.x, sDriveVel.y, sDriveVel.z); + } + + if (zcam_bbounce) + { + F32 y0 = ent->frame->mat.pos.y; + F32 y1 = ent->frame->oldmat.pos.y; + if (y1 < y0) + { + zCameraTranslate(&globals.camera, 0.0f, y0 - y1, 0.0f); + } + } + + PlayerLedgeUpdate(ent, sc, dt); + + if (sRingDelay >= 1.1f) + { + F32 f = (2.0f - sRingDelay) * 1.25f; + if (f > 1.0f) + { + f = 1.0f; + } + zNPCMsg_AreaPlayerStun(5.0f, f * 5.0f + (1.0f - f), NULL); + } + + zEntPlayerFloorUpdate(ent, sc, dt); + PlayerTeeterCheck(ent, sc, dt); + zEntPlayerSurfDamageUpdate(ent, sc, dt); + zEntPlayerDriveUpdate(ent, sc, dt); + zEntPlayerJumpUpdate(ent, sc, dt); + zEntPlayerTSlideUpdate(ent, sc, dt); + zEntPlayerCollTrigger(ent, sc); + + if (globals.player.RootUp.y != globals.player.RootUpTarget.y || globals.player.RootUp.y != 1.0f) + { + xVec3 diff; + xVec3Sub(&diff, &globals.player.RootUpTarget, &globals.player.RootUp); + F32 len2 = xVec3Dot(&diff, &diff); + + F32 speed; + if (globals.player.HangElapsed > 0.25f) + { + speed = 0.5f; + if (globals.player.HangElapsed < 0.5f) + { + speed = (globals.player.HangElapsed - 0.25f) * 1.72f; + } + } + else + { + speed = 0.07f; + } + + if (len2 >= speed * speed) + { + F32 dlen = xsqrt(len2); + xVec3SMul(&diff, &diff, (1.0f / dlen) * speed); + xVec3Add(&globals.player.RootUp, &globals.player.RootUp, &diff); + xVec3Normalize(&globals.player.RootUp, &globals.player.RootUp); + } + else + { + globals.player.RootUp = globals.player.RootUpTarget; + } + } + + zEntPlayerVelUpdate(ent, sc, dt); + + ent->frame->oldmat.pos.y -= sPlayerCollAdjust; + ent->frame->mat.pos.y -= sPlayerCollAdjust; + + xEntEndUpdate(ent, sc, dt); +} + static void zEntPlayer_Move(xEnt*, xScene*, F32, xEntFrame* frame); static void zEntPlayer_Render(xEnt*); From 6c0091e2d84b13470b2243731842f37b8a0306da Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Sun, 9 Aug 2026 20:14:54 -0400 Subject: [PATCH 3/4] cleanup declarations and fix review --- src/SB/Core/x/xEntBoulder.h | 2 ++ src/SB/Game/zEntPlayer.cpp | 30 +++++----------------------- src/SB/Game/zEntPlayer.h | 15 ++++++++++++++ src/SB/Game/zFX.h | 3 ++- src/SB/Game/zGust.h | 1 + src/SB/Game/zNPCTypeBossPlankton.cpp | 6 +++--- src/SB/Game/zNPCTypeBossSB2.h | 2 -- src/SB/Game/zSurface.h | 10 +++++----- 8 files changed, 33 insertions(+), 36 deletions(-) diff --git a/src/SB/Core/x/xEntBoulder.h b/src/SB/Core/x/xEntBoulder.h index ed667f88c..607f8a263 100644 --- a/src/SB/Core/x/xEntBoulder.h +++ b/src/SB/Core/x/xEntBoulder.h @@ -84,5 +84,7 @@ void xBoulderGenerator_Init(xBase& data, xDynAsset& asset, size_t); void xBoulderGenerator_Init(xBoulderGenerator* bg, xBoulderGeneratorAsset* asset); void xBoulderGenerator_Init(xBase& data, xDynAsset& asset); S32 xEntBoulderEventCB(xBase*, xBase*, U32, const F32*, xBase*); +void xEntBoulder_ApplyForces(xEntCollis* collis); +void xEntBoulder_AddForce(xEntBoulder* boulder, xVec3* force); #endif diff --git a/src/SB/Game/zEntPlayer.cpp b/src/SB/Game/zEntPlayer.cpp index 572d3dd54..0aba0a834 100644 --- a/src/SB/Game/zEntPlayer.cpp +++ b/src/SB/Game/zEntPlayer.cpp @@ -7,6 +7,7 @@ #include "iAnim.h" #include "iAnimSKB.h" +#include "iCollide.h" #include "iMath.h" #include "iSnd.h" #include "iTRC.h" @@ -20,6 +21,7 @@ #include "xMathInlines.h" #include "xMemMgr.h" #include "xRay3.h" +#include "xScrFx.h" #include "xSnd.h" #include "xstransvc.h" #include "xTRC.h" @@ -32,6 +34,7 @@ #include "zEntButton.h" #include "zEntCruiseBubble.h" #include "zEntDestructObj.h" +#include "zEntPickup.h" #include "zEntPlayer.h" #include "zEntPlayerBungeeState.h" #include "zEntPlayerOOBState.h" @@ -271,42 +274,19 @@ static void PlayerSwingUpdate(xEnt* ent, F32 mag, F32 angle, F32 dt); static S32 CheckObjectAgainstMeleeBound(xEnt* ent, void* data); static void zEntPlayer_PredictionUpdate(xEnt* ent, F32 dt); static void zEntPlayerEGenUpdate(xEnt* ent, xScene* sc, F32 dt); -void zEntPlayer_SNDPlayDelayed(F32 seconds); static void zEntPlayer_UpdateVelocityBlur(); static void speak_update(F32 dt); static void zEntPlayer_SpringboardFX(xEnt* ent, F32 dt); -void zEntPlayer_SNDPlay(_tagePlayerSnd player_snd, F32 delay); -void zEntPlayer_SNDStop(_tagePlayerSnd player_snd); -void zEntPickup_CheckAllPickupsAgainstPlayer(xScene* sc, F32 dt); static xEnt* GetPatrickTarget(xEnt* ent); static xEnt* zEntPlayer_FindGrabEnt(xEnt* ent, zScene* zsc, S32* failed); static U8 StunBubbleTrail(xAnimSingle* anim); -void zFXPatrickStun(const xVec3* pos); extern zParEmitter* gEmitBFX; static S32 MeleeAttackBoundCollide(xEnt* ent, zScene* zscn, xBound* meleeB); static U8 BubbleBashContrails(xAnimSingle* anim); static U8 BubbleBounceContrails(xAnimSingle* anim); -void zEntPlayer_setBoulderMode(U32 mode); -void xScrFxFade(iColor_tag* base, iColor_tag* dest, F32 seconds, void (*callback)(), S32 hold); -S32 xScrFxIsFading(); static void DoWallJumpCheck(); -U32 iRayHitsEnv(const xRay3* r, const xEnv* env, xCollis* coll); -void zGustUpdateEnt(xEnt*, xScene*, F32, void*); -void zEntPlayerCollide(xEnt* ent, xScene* sc, F32 dt); -void zEntPlayer_CheckCritterContact(xEnt* ent, F32 dt); -void xEntBoulder_ApplyForces(xEntCollis* collis); -xSurface* zSurfaceGetSurface(const xCollis* coll); -S32 zSurfaceGetStep(const xSurface* surf); -void xEntBoulder_AddForce(xEntBoulder* boulder, xVec3* force); -void PlayerLedgeUpdate(xEnt* ent, xScene* sc, F32 dt); static S32 zEntPlayerKnockToSafety(xEnt* ent); -void zEntPlayerFloorUpdate(xEnt* ent, xScene* sc, F32 dt); -void PlayerTeeterCheck(xEnt* ent, xScene* sc, F32 dt); -void zEntPlayerSurfDamageUpdate(xEnt* ent, xScene* sc, F32 dt); -void zEntPlayerDriveUpdate(xEnt* ent, xScene* sc, F32 dt); -void zEntPlayerJumpUpdate(xEnt* ent, xScene* sc, F32 dt); -void zEntPlayerTSlideUpdate(xEnt* ent, xScene* sc, F32 dt); -void zEntPlayerVelUpdate(xEnt* ent, xScene* sc, F32 dt); + namespace oob_state { void force_start(); @@ -3514,7 +3494,7 @@ static void zEntPlayer_Update(xEnt* ent, xScene* sc, F32 dt) { ent->frame->mat.pos.x += thirteenSubstepDt * globals.player.floor_norm.x; F32 mag = xsqrt(globals.player.floor_norm.x * globals.player.floor_norm.x + - globals.player.floor_norm.z * globals.player.floor_norm.z); + globals.player.floor_norm.z * globals.player.floor_norm.z); ent->frame->mat.pos.y -= thirteenSubstepDt * mag; ent->frame->mat.pos.z += thirteenSubstepDt * globals.player.floor_norm.z; } diff --git a/src/SB/Game/zEntPlayer.h b/src/SB/Game/zEntPlayer.h index d4e3ad6fe..3b504dd60 100644 --- a/src/SB/Game/zEntPlayer.h +++ b/src/SB/Game/zEntPlayer.h @@ -470,4 +470,19 @@ void zEntPlayer_PredictPos(xVec3* pos, F32 timeIntoFuture, F32 leadFactor, S32 u void zEntPlayerCollTrigger(xEnt* ent, xScene* sc); +void zEntPlayer_SNDPlayDelayed(F32 seconds); +void zEntPlayer_SNDPlay(_tagePlayerSnd player_snd, F32 delay); +void zEntPlayer_SNDStop(_tagePlayerSnd player_snd); +void zEntPlayer_setBoulderMode(U32 mode); +void zEntPlayerCollide(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayer_CheckCritterContact(xEnt* ent, F32 dt); +void PlayerLedgeUpdate(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerFloorUpdate(xEnt* ent, xScene* sc, F32 dt); +void PlayerTeeterCheck(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerSurfDamageUpdate(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerDriveUpdate(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerJumpUpdate(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerTSlideUpdate(xEnt* ent, xScene* sc, F32 dt); +void zEntPlayerVelUpdate(xEnt* ent, xScene* sc, F32 dt); + #endif diff --git a/src/SB/Game/zFX.h b/src/SB/Game/zFX.h index 0fa51da6c..875339c72 100644 --- a/src/SB/Game/zFX.h +++ b/src/SB/Game/zFX.h @@ -21,7 +21,7 @@ enum zFXGooState zFXGooStateForce32Bit = 0xffffffff }; -// Definition updated based on Rat proto data. +// Definition updated based on Rat proto data. struct zFXGooInstance { RpAtomic* atomic; @@ -51,6 +51,7 @@ void on_spawn_bubble_wall(const tweak_info& tweak); void zFX_SceneEnter(RpWorld* world); void zFX_SceneExit(RpWorld* world); void zFX_SceneReset(); +void zFXPatrickStun(const xVec3* pos); void zFXHammer(const xVec3* pos); void zFXPorterWave(const xVec3* pos); diff --git a/src/SB/Game/zGust.h b/src/SB/Game/zGust.h index a30bf70e8..9ad577d50 100644 --- a/src/SB/Game/zGust.h +++ b/src/SB/Game/zGust.h @@ -37,6 +37,7 @@ struct zGustData void zGustInit(); void zGustSetup(); zGust* zGustGetGust(U16 n); +void zGustUpdateEnt(xEnt* ent, xScene* sc, float dt, void* gdata); void zGustSave(zGust* ent, xSerial* s); void zGustLoad(zGust* ent, xSerial* s); void zGustUpdateFX(F32 seconds); diff --git a/src/SB/Game/zNPCTypeBossPlankton.cpp b/src/SB/Game/zNPCTypeBossPlankton.cpp index fbbffcfbc..c219447c3 100644 --- a/src/SB/Game/zNPCTypeBossPlankton.cpp +++ b/src/SB/Game/zNPCTypeBossPlankton.cpp @@ -1133,12 +1133,12 @@ void zNPCBPlankton::Reset() if (mode == MODE_BUDDY) { - psy_instinct->GoalSet(0x4e47424b, 1); // 'NGBK' + psy_instinct->GoalSet('NGBK', 1); } else { vanish(); - psy_instinct->GoalSet(0x4e47424d, 1); // 'NGBM' + psy_instinct->GoalSet('NGBM', 1); } } @@ -1184,7 +1184,7 @@ void zNPCBPlankton::Process(xScene* xscn, F32 dt) this->update_move(dt); this->update_animation(dt); - if (this->check_player_damage() & 0xFF) + if (this->check_player_damage()) { zEntPlayer_Damage((xBase*)this, 1); } diff --git a/src/SB/Game/zNPCTypeBossSB2.h b/src/SB/Game/zNPCTypeBossSB2.h index 33a5eae2b..0209abe5e 100644 --- a/src/SB/Game/zNPCTypeBossSB2.h +++ b/src/SB/Game/zNPCTypeBossSB2.h @@ -23,8 +23,6 @@ struct response_curve U32 nodes; // offset 0x8, U32 active_node; // offset 0xC, - // static void init(U32, const void*, U32, const char*, const char**, const tweak_callback*, - // void*); static void init(U64, const void*, U64, const char*, const char**, const tweak_callback*, void*); static void end_t(); diff --git a/src/SB/Game/zSurface.h b/src/SB/Game/zSurface.h index faf1ff278..d19ce4a44 100644 --- a/src/SB/Game/zSurface.h +++ b/src/SB/Game/zSurface.h @@ -6,12 +6,11 @@ #include "xMath3.h" #include "xSurface.h" +#define SURF_TEXANIM_ON (1 << 0) +#define SURF_TEXANIM_ON2 (1 << 1) -#define SURF_TEXANIM_ON (1<<0) -#define SURF_TEXANIM_ON2 (1<<1) - -#define UVANIM_FLAG_ON (1<<0) -#define UVANIM_FLAG_ON2 (1<<1) +#define UVANIM_FLAG_ON (1 << 0) +#define UVANIM_FLAG_ON2 (1 << 1) struct zSurfMatFX { @@ -130,6 +129,7 @@ void zSurfaceRegisterMapper(U32 assetId); void zSurfaceExit(); xSurface* zSurfaceGetSurface(U32 mat_id); xSurface* zSurfaceGetSurface(const xCollis* coll); +S32 zSurfaceGetStep(const xSurface* surf); U32 zSurfaceGetStandOn(const xSurface* surf); void zSurfaceSave(xSurface* ent, xSerial* s); void zSurfaceLoad(xSurface* ent, xSerial* s); From 68c8b2b30680714ea7b17d34c99e87a7ae637cb2 Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Sun, 9 Aug 2026 20:18:03 -0400 Subject: [PATCH 4/4] fix ci --- src/SB/Game/zSurface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SB/Game/zSurface.h b/src/SB/Game/zSurface.h index d19ce4a44..3f575a031 100644 --- a/src/SB/Game/zSurface.h +++ b/src/SB/Game/zSurface.h @@ -129,7 +129,7 @@ void zSurfaceRegisterMapper(U32 assetId); void zSurfaceExit(); xSurface* zSurfaceGetSurface(U32 mat_id); xSurface* zSurfaceGetSurface(const xCollis* coll); -S32 zSurfaceGetStep(const xSurface* surf); +U32 zSurfaceGetStep(const xSurface* surf); U32 zSurfaceGetStandOn(const xSurface* surf); void zSurfaceSave(xSurface* ent, xSerial* s); void zSurfaceLoad(xSurface* ent, xSerial* s);