Skip to content

Commit 2eee043

Browse files
committed
zNPCHazard: Matches on Chuck and TarTar functions
1 parent 70a444f commit 2eee043

File tree

2 files changed

+335
-0
lines changed

2 files changed

+335
-0
lines changed

src/SB/Game/zNPCHazard.cpp

Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "zNPCSupplement.h"
1010
#include "zNPCSupport.h"
1111
#include "xMath.h"
12+
#include "xMathInlines.h"
1213
#include "zGameExtras.h"
1314

1415
extern U32 g_hash_hazanim[3];
@@ -492,6 +493,331 @@ void NPCHazard::TarTarLinger()
492493
NPAR_EmitTarTarSpoil(&pos_emit, &vel_emit);
493494
}
494495

496+
void NPCHazard::Upd_ChuckBomb(F32 dt)
497+
{
498+
HAZTarTar* tartar = &this->custdata.tartar;
499+
const xParabola* parab = &tartar->parabinfo;
500+
501+
if (this->tmr_remain < dt)
502+
{
503+
if (this->flg_hazard & 0x20000)
504+
{
505+
xParabolaEvalPos(parab, &this->pos_hazard, parab->maxTime);
506+
ReconChuck();
507+
return;
508+
}
509+
else
510+
{
511+
ReconChuck();
512+
return;
513+
}
514+
}
515+
516+
if (this->flg_hazard & 0x8)
517+
{
518+
xVec3Sub(&tartar->vel, &tartar->pos_tgt, &this->pos_hazard);
519+
xVec3SMulBy(&tartar->vel, 1.0f / this->tmr_remain);
520+
521+
tartar->vel.y = 5.0f * (0.5f * this->tmr_remain) + tartar->vel.y;
522+
}
523+
524+
if (this->flg_hazard & 0x8)
525+
{
526+
PreCollide();
527+
}
528+
529+
F32 tym = this->tym_lifespan - this->tmr_remain;
530+
xParabolaEvalPos(parab, &this->pos_hazard, tym);
531+
xParabolaEvalVel(parab, &tartar->vel, tym);
532+
533+
F32 vel_mag = xVec3Length(&tartar->vel);
534+
if (vel_mag > 0.0001f)
535+
{
536+
xMat3x3 mat_rot;
537+
xVec3 dir;
538+
xVec3SMul(&dir, &tartar->vel, -1.0f / vel_mag);
539+
xMat3x3LookVec(&mat_rot, &dir);
540+
541+
xMat3x3 mat_spiral;
542+
xMat3x3Rot(&mat_spiral, &mat_rot.at, 2.0f * PI * (parab->minTime - parab->maxTime));
543+
xMat3x3Mul(&mat_rot, &mat_rot, &mat_spiral);
544+
545+
TypData_RotMatSet(&mat_rot);
546+
TypData_RotMatSet(&mat_rot);
547+
}
548+
549+
static S32 moreorless = 0;
550+
551+
if (--moreorless < 0)
552+
{
553+
moreorless = 3;
554+
DisperseBubWake(tartar->rad_cur, &tartar->vel);
555+
}
556+
557+
if (this->flg_hazard & 0x2000)
558+
{
559+
if (!(globals.player.DamageTimer > 0.0f) && ColPlyrSphere(tartar->rad_cur))
560+
{
561+
HurtThePlayer();
562+
ReconChuck();
563+
return;
564+
}
565+
}
566+
567+
StaggeredCollide();
568+
}
569+
570+
void NPCHazard::DisperseBubWake(F32 radius, const xVec3* velocity)
571+
{
572+
F32 dst_disperse = 0.5f * radius;
573+
574+
xVec3 pos_disperse;
575+
pos_disperse = *(xVec3*)Up() * (dst_disperse * (2.0f * (xurand() - 0.5f)));
576+
pos_disperse += *(xVec3*)Right() * (dst_disperse * (2.0f * (xurand() - 0.5f)));
577+
578+
xVec3 vel_disperse;
579+
vel_disperse = *(xVec3*)Up() * (8.0f * (2.0f * (xurand() - 0.5f)));
580+
vel_disperse += *(xVec3*)Right() * (8.0f * (2.0f * (xurand() - 0.5f)));
581+
582+
xVec3 dir_backward = *velocity;
583+
dir_backward.inverse();
584+
dir_backward.normalize();
585+
586+
xVec3 pos_emit = this->pos_hazard;
587+
pos_emit -= dir_backward * (1.5f * radius);
588+
589+
zFX_SpawnBubbleTrail(&pos_emit, 0x10, &pos_disperse, &vel_disperse);
590+
}
591+
592+
void NPCHazard::ReconChuck()
593+
{
594+
HAZBall* ball = &this->custdata.ball;
595+
596+
xVec3 dir_norm = this->custdata.collide.dir_normal;
597+
xVec3 vel_flight = this->custdata.tartar.vel;
598+
599+
Reconfigure(NPC_HAZ_CHUCKBLAST);
600+
601+
if (xVec3Length2(&dir_norm) > 0.0f)
602+
{
603+
xVec3Copy((xVec3*)&this->mdl_hazard->Mat->up, &dir_norm);
604+
NPCC_MakePerp((xVec3*)&this->mdl_hazard->Mat->at, &dir_norm);
605+
xVec3Cross((xVec3*)&this->mdl_hazard->Mat->right, (xVec3*)&this->mdl_hazard->Mat->up, (xVec3*)&this->mdl_hazard->Mat->at);
606+
607+
xMat3x3 mat;
608+
xMat3x3Rot(&mat, &dir_norm, 2 * PI * xurand());
609+
xMat3x3Mul(xModelGetFrame(this->mdl_hazard), xModelGetFrame(this->mdl_hazard), &mat);
610+
611+
F32 dot = xVec3Dot(&dir_norm, &g_Y3);
612+
613+
if (FABS(dot) < 0.86f)
614+
{
615+
ball->rad_max *= 0.5f;
616+
ball->rad_min *= 0.5f;
617+
ball->rad_cur *= 0.5f;
618+
}
619+
}
620+
621+
Start(NULL, -1.0f);
622+
623+
if (this->flg_hazard & 0x8 && HAZ_AvailablePool() > 5)
624+
{
625+
for (S32 i = 0; i < 7; i++)
626+
{
627+
if (KickBlooshBlob(&vel_flight))
628+
{
629+
this->flg_hazard |= 0x40;
630+
}
631+
}
632+
}
633+
}
634+
635+
void NPCHazard::Upd_ChuckBlast(F32 dt)
636+
{
637+
HAZBall* ball = &this->custdata.ball;
638+
639+
ball->rad_cur = LERP(this->pam_interp, ball->rad_min, ball->rad_max);
640+
641+
if (this->flg_hazard & 0x2000 && !(globals.player.DamageTimer > 0.75f) && this->pam_interp < 0.25f)
642+
{
643+
if (ColPlyrCyl(ball->rad_cur, 0.5f * ball->rad_cur))
644+
{
645+
HurtThePlayer();
646+
}
647+
}
648+
649+
if (this->flg_hazard & 0x8)
650+
{
651+
xSndPlay3D(xStrHash("Chu_splash"), 0.77f, 0.0f, 0x80, 0x0, &this->pos_hazard, 5.0f, 15.0f, SND_CAT_GAME, 0.0f);
652+
}
653+
654+
if (this->flg_hazard & 0x8)
655+
{
656+
WaterSplash(NULL);
657+
}
658+
659+
WavesOfEvil();
660+
}
661+
662+
void NPCHazard::WaterSplash(const xVec3* dir_norm)
663+
{
664+
xVec3 pos_emit = this->pos_hazard;
665+
666+
xVec3 up, at, rt;
667+
if (dir_norm)
668+
{
669+
up = *dir_norm;
670+
NPCC_MakePerp(&at, dir_norm);
671+
xVec3Cross(&rt, &up, &at);
672+
}
673+
else
674+
{
675+
up = *(xVec3*)Up();
676+
at = *(xVec3*)At();
677+
rt = *(xVec3*)Right();
678+
}
679+
680+
for (S32 i = 0; i < 8; i++)
681+
{
682+
xVec3 vel_emit;
683+
vel_emit = up * (0.5f * xurand() + 1.5f);
684+
685+
F32 direction;
686+
if (xrand() & 0x800000)
687+
{
688+
direction = 1.0f;
689+
}
690+
else
691+
{
692+
direction = -1.0f;
693+
}
694+
695+
vel_emit += at * direction * (0.5f * (2.0f * (xurand() - 0.5f)) + 1.0f);
696+
697+
if (xrand() & 0x800000)
698+
{
699+
direction = 1.0f;
700+
}
701+
else
702+
{
703+
direction = -1.0f;
704+
}
705+
706+
vel_emit += rt * direction * (0.5f * (2.0f * (xurand() - 0.5f)) + 1.0f);
707+
vel_emit.normalize();
708+
vel_emit *= 10.0f;
709+
710+
NPAR_EmitH2ODrips(&pos_emit, &vel_emit);
711+
}
712+
713+
for (S32 i = 0; i < 8; i++)
714+
{
715+
xVec3 vel_emit;
716+
xurand();
717+
vel_emit = up * 1.0f;
718+
719+
F32 direction;
720+
if (xrand() & 0x800000)
721+
{
722+
direction = 1.0f;
723+
}
724+
else
725+
{
726+
direction = -1.0f;
727+
}
728+
729+
vel_emit += at * direction * (0.75f * (2.0f * (xurand() - 0.5f)) + 0.75f);
730+
731+
if (xrand() & 0x800000)
732+
{
733+
direction = 1.0f;
734+
}
735+
else
736+
{
737+
direction = -1.0f;
738+
}
739+
740+
vel_emit += rt * direction * (0.75f * (2.0f * (xurand() - 0.5f)) + 0.75f);
741+
vel_emit.normalize();
742+
vel_emit *= 7.0f;
743+
744+
NPAR_EmitH2ODrops(&pos_emit, &vel_emit);
745+
}
746+
}
747+
748+
void NPCHazard::WavesOfEvil()
749+
{
750+
F32 rad = this->custdata.collide.rad_cur;
751+
752+
for (S32 i = 0; i < 8; i++)
753+
{
754+
xVec3 pos_emit;
755+
xVec3 vel_emit;
756+
757+
pos_emit = *(xVec3*)At() * (2.0f * (xurand() - 0.5f));
758+
pos_emit += *(xVec3*)Right() * (2.0f * (xurand() - 0.5f));
759+
pos_emit.normalize();
760+
pos_emit *= rad;
761+
762+
pos_emit += *(xVec3*)Up() * 0.2f;
763+
pos_emit += this->pos_hazard;
764+
765+
vel_emit = *(xVec3*)Up();
766+
vel_emit *= 5.5f;
767+
768+
NPAR_EmitH2OSpray(&pos_emit, &vel_emit);
769+
}
770+
}
771+
772+
S32 NPCHazard::KickBlooshBlob(const xVec3* vel_flight)
773+
{
774+
NPCHazard* haz = HAZ_Acquire();
775+
if (!haz)
776+
{
777+
return 0;
778+
}
779+
780+
if (!haz->ConfigHelper(NPC_HAZ_CHUCKBLOOSH))
781+
{
782+
haz->Discard();
783+
return 1;
784+
}
785+
786+
haz->SetNPCOwner(this->npc_owner);
787+
788+
HAZTarTar* tartar = &haz->custdata.tartar;
789+
tartar->vel = *(xVec3*)this->Up() * (5.0f * xurand() + 5.0f);
790+
791+
F32 spd_factor = 3.5f * xurand() + 2.5f;
792+
tartar->vel += *(xVec3*)this->At() * ((2.0f * (xurand() - 0.5f)) * spd_factor);
793+
794+
spd_factor = 3.5f * xurand() + 2.5f;
795+
tartar->vel += *(xVec3*)this->Right() * ((2.0f * (xurand() - 0.5f)) * spd_factor);
796+
797+
if (xVec3Dot(&g_Y3, (xVec3*)this->Up()) > 0.86f)
798+
{
799+
xVec3 vel_drift = { 0.0f, 0.0f, 0.0f };
800+
vel_drift.x = vel_flight->x;
801+
vel_drift.z = vel_flight->z;
802+
803+
F32 drift_mag = xVec3Length(&vel_drift);
804+
if (drift_mag > 0.5f)
805+
{
806+
F32 mag_factor = (2.5f < 0.25f * drift_mag ? 2.5f : 0.25f * drift_mag) / drift_mag;
807+
xVec3 vel_push = vel_drift * mag_factor;
808+
tartar->vel += vel_push;
809+
}
810+
811+
}
812+
813+
xVec3 pos_emit = this->pos_hazard;
814+
pos_emit += *(xVec3*)this->Up() * 0.35f;
815+
816+
haz->Start(&pos_emit, -1.0f);
817+
818+
return 2;
819+
}
820+
495821
void NPCHazard::ReconArfBone()
496822
{
497823
Reconfigure(NPC_HAZ_ARFBONEBLAST);

src/SB/Game/zNPCHazard.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,12 +262,21 @@ struct NPCHazard
262262
void TarTarGunkTrail();
263263
void TarTarSplash(const xVec3* dir_norm);
264264
void TarTarLinger();
265+
void Upd_ChuckBomb(F32 dt);
266+
void DisperseBubWake(F32 radius, const xVec3* velocity);
267+
void ReconChuck();
268+
void Upd_ChuckBlast(F32 dt);
269+
void WavesOfEvil();
270+
void WaterSplash(const xVec3* dir_norm);
271+
S32 KickBlooshBlob(const xVec3* vel_flight);
265272
S32 KickSteamyStinky();
266273
void ReconArfBone();
267274
void HurtThePlayer();
268275
void TypData_RotMatSet(xMat3x3* mat);
269276
void TypData_RotMatApply(xMat3x3* mat);
270277
en_hazmodel PickFunFrag();
278+
void PreCollide();
279+
void StaggeredCollide();
271280
void StagColGeneral(S32 who);
272281
void StagColStat();
273282
void StagColNPC();

0 commit comments

Comments
 (0)