spidey-decomp/thug.cpp
2024-07-26 17:46:50 +02:00

1276 lines
23 KiB
C++

#include "thug.h"
#include "validate.h"
#include "trig.h"
#include "m3dutils.h"
#include "message.h"
#include "ps2lowsfx.h"
#include "utils.h"
#include "ai.h"
#include "ps2redbook.h"
#include "spidey.h"
#include "exp.h"
#include <cmath>
extern CBaddy *BaddyList;
extern CPlayer* MechList;
EXPORT CThug* gGlobalThug;
EXPORT CThug* gThugList;
// @Ok
// @Test
void CThug::TakeHit(void)
{
switch (this->dumbAssPad)
{
case 0:
this->mCBodyFlags &= 0xFFEFu;
this->field_310 = 0;
this->ClearAttackFlags();
if (this->field_318 == 1)
{
this->field_DC = 0;
this->RunAnim(this->field_38 != 304 ? 19 : 14, 0, -1);
this->dumbAssPad = 2;
}
else
{
new CAIProc_LookAt(this, MechList, 0, 0, 80, 200);
this->RunAppropriateHitAnim();
this->dumbAssPad = 3;
}
break;
case 1:
if ( this->field_142 )
{
this->field_318 = 0;
this->field_31C.bothFlags = 28;
this->dumbAssPad = 0;
}
break;
case 2:
if ( this->field_142 )
{
this->field_DC = this->field_38 == 304 ? 96 : 150;
this->RunAnim(this->field_38 == 304 ? 15 : 20, 0, -1);
this->dumbAssPad = 1;
}
break;
case 3:
if ( this->field_142 )
{
this->field_31C.bothFlags = 28;
this->dumbAssPad = 0;
}
break;
default:
print_if_false(0, "Unknown substate!");
break;
}
}
// @Ok
void CThug::BackpedalPlease(void)
{
CVector v10;
v10.vx = 0;
v10.vy = 0;
v10.vz = 0;
switch (this->dumbAssPad)
{
case 0:
this->Neutralize();
this->field_1F8 = 0;
v10 = this->mPos;
v10.vx += 6 * ((this->mPos.vx - MechList->mPos.vx) >> 2);
v10.vx += 6 * ((this->mPos.vz - MechList->mPos.vz) >> 2);
if (this->AddPointToPath(&this->mPos, 0) && this->AddPointToPath(&v10, 0))
{
this->mAccellorVel = (this->mPos - MechList->mPos) >> 2;
this->mAccellorVel.vy = 0;
}
this->RunAppropriateHitAnim();
this->dumbAssPad++;
break;
case 1:
this->DoPhysics(1);
if (this->field_1F8 <= 0)
this->Neutralize();
if (this->field_142)
{
this->Neutralize();
this->field_31C.bothFlags = 28;
this->dumbAssPad = 0;
}
break;
default:
print_if_false(0, "Unknown substate!");
break;
}
}
// @Ok
void CThug::LookForPlayer(void)
{
CVector v5;
v5.vx = 0;
v5.vy = 0;
v5.vz = 0;
switch (this->dumbAssPad)
{
case 0:
this->Neutralize();
this->CycleAnim(this->field_298.Bytes[0], 1);
this->dumbAssPad++;
this->field_21D = Rnd(64);
this->field_1F8 = 0;
break;
case 1:
CVector *mPos;
if (this->field_1F8 < 64)
mPos = &MechList->mPos;
else
mPos = &this->mPos;
this->GetWaypointNearTarget(mPos, 409600, this->field_21D, &v5);
this->field_21D++;
if ( !this->PathCheck(&this->mPos, &v5, 0, 55)
&& (this->AddPointToPath(&v5, 0)
|| this->AddPointToPath(&this->mPos, 0)
&& this->AddPointToPath(&v5, 0)) )
{
this->field_31C.bothFlags = 24;
this->dumbAssPad = 0;
}
else
{
if ( this->field_1F8++ > 128 )
{
this->field_330 = 0;
this->field_31C.bothFlags = 2;
this->dumbAssPad = 0;
}
}
break;
default:
print_if_false(0, "Unknown substate!");
break;
}
}
// @BIGTODO
i32 CThug::DetermineFightState(void)
{
printf("i32 CThug::DetermineFightState(void)");
return 0x26042024;
}
// @Ok
void CThug::Caution(void)
{
switch (this->dumbAssPad)
{
case 0:
this->field_310 = 0;
this->Neutralize();
SFX_PlayPos( (Rnd(3) + 14) | 0x8000, &this->mPos, 0);
if ((abs(MechList->mPos.vy - this->field_29C - 0x4000) < 409600)
&& this->PlayerIsVisible())
{
if (!this->ShouldIShootPlayer())
{
this->field_31C.bothFlags = MechList->field_57C != 0 ? 1 : 4;
this->dumbAssPad = 0;
}
}
else if (!this->DetermineFightState())
{
this->field_31C.bothFlags = 2;
this->dumbAssPad = 0;
}
break;
default:
print_if_false(0, "Unknown substate!");
break;
}
}
// @Ok
void CThug::CreateCombatImpactEffect(CVector* a2, i32 a3)
{
if ( this->field_38 == 304 )
{
new CCombatImpactRing(a2, 0x12u, 18, 108, 384, 1792, 144);
new CCombatImpactRing(a2, 0x48u, 72, 144, 192, 896, 72);
}
else
{
new CCombatImpactRing(a2, 0x6Cu, 108, 18, 384, 1792, 144);
new CCombatImpactRing(a2, 0x90u, 144, 72, 192, 896, 72);
}
}
// @Ok
// @Test
// two's complement a lil diff
INLINE i32 CThug::ShouldIShootPlayer(void)
{
if ( MechList->field_57C
|| gThugList
|| this->DistanceToPlayer(2) >= 2000
|| MechList->field_E48
|| this->DistanceToPlayer(2) <= 650
&& (abs(MechList->mPos.vy - this->field_29C - 0x4000) <= 409600) )
{
return 0;
}
this->Neutralize();
gThugList = this;
this->field_31C.bothFlags = 9;
this->dumbAssPad = 0;
return 1;
}
// @Ok
CThug::~CThug(void)
{
if (this->field_3A0)
delete this->field_3A0;
this->field_3A0 = 0;
if (this->field_3A4)
Mem_Delete(this->field_3A4);
this->field_3A4 = 0;
if (gThugList == this)
gThugList = 0;
this->ClearAttackFlags();
this->DeleteFrom(reinterpret_cast<CBody**>(&BaddyList));
}
// @SMALLTODO
i32 CThug::SetUpLaser(CGPolyLine**, CVector*, CVector*)
{
printf("i32 CThug::SetUpLaser(CGPolyLine**, CVector*, CVector*)");
return 0x26042024;
}
// @Ok
INLINE i32 CThug::DrawBarrelFlash(
CVector *a2,
CVector *a3,
SLineInfo *a4,
u8 a5,
u8 a6,
u8 a7)
{
new CGlowFlash(a2, 5, a5, a6, a7, 32, 0, 0, 0, 0, 50, 20, 1, 20, 10, 40, 20, 10, 1);
return this->SetUpLaser(&this->field_3A0, a2, a3);
}
// @NotOk
// Validate when used
INLINE void CThug::CheckToShoot(i32 a2, i32 a3)
{
if ( MechList->field_57C && !gThugList && !MechList->field_E48)
{
if ( ((this->field_218 & 0x800) && a2 < this->field_37C)
||
(this->field_330 && a2 < 1500 && (a3 != -1 || this->PathCheck(&this->mPos, &MechList->mPos, 0, 55))))
{
this->Neutralize();
gThugList = this;
this->ClearAttackFlags();
this->field_31C.bothFlags = 9;
this->dumbAssPad = 0;
}
}
}
// @NotOk
// Better type
void CThug::WarnOtherThugs(void)
{
CThug *nearest = reinterpret_cast<CThug*>(this->GetClosest(304, 0));
if ( (nearest || ((nearest = reinterpret_cast<CThug*>(this->GetClosest(312, 0))) != 0))
&& !nearest->field_330)
{
new CMessage(this, nearest, 7, 0);
}
}
// @NotOk
// validate when used
INLINE i32 CThug::AdjustPosPlaySound(i32 a2)
{
CVector v4;
v4.vx = 0;
v4.vy = 0;
v4.vz = 0;
v4.vx = ((2400 * MechList->mPos.vx) >> 12) + ((1600 * this->mPos.vx) >> 12);
v4.vy = ((2400 * MechList->mPos.vy) >> 12) + ((1600 * this->mPos.vy) >> 12);
v4.vz = ((2400 * MechList->mPos.vz) >> 12) + ((1600 * this->mPos.vz) >> 12);
return SFX_PlayPos(a2, &v4, 0);
}
// @NotOk
// globals flags :(
u8 CThug::Grab(CVector* a2)
{
if ( (this->CheckStateFlags(reinterpret_cast<SStateFlags*>(0x557CA0), 17) & 2)
|| !this->AddPointToPath(a2, 0) )
{
return 0;
}
this->field_31C.bothFlags = 20;
this->dumbAssPad = 0;
this->field_2A8 |= 0x40;
return 1;
}
// @Ok
INLINE void CThug::SetAttacker(void)
{
if (gGlobalThug != this)
{
this->ClearAttackFlags();
if (gGlobalThug)
{
gGlobalThug->ClearAttackFlags();
}
gGlobalThug = this;
this->field_3BC = 1;
}
}
// @Ok
INLINE i32 CThug::SpideyAnimUppercut(void)
{
return MechList->field_12A == 106
|| MechList->field_12A == 113
|| MechList->field_12A == 284;
}
// @NotOk
// validate
void CThug::PlaySounds(void)
{
CVector v11;
if (this->field_38 == 304)
{
switch ( this->field_12A )
{
case 1u:
if ( this->field_128 == 27 || this->field_128 == 13 )
SFX_PlayPos((Rnd(4) + 32) | 0x80, &this->mPos, 300);
return;
break;
case 8u:
if ( this->field_128 == 5 )
SFX_PlayPos(0x801D, &this->mPos, 500);
break;
case 0xEu:
if ( this->field_128 == 15 )
{
v11.vz = 409600;
v11.vx = 0;
v11.vy = 0;
this->MakeSpriteRing(&v11);
}
break;
case 0x1Au:
if ( this->field_128 == 23 )
{
v11.vx = 0;
v11.vy = 0;
v11.vz = -122880;
this->MakeSpriteRing(&v11);
}
break;
case 0x1Cu:
if ( this->field_128 == 4 || this->field_128 == 14)
SFX_PlayPos((Rnd(4) + 32) | 0x80, &this->mPos, 50);
break;
}
}
else
{
switch ( this->field_12A )
{
case 5u:
if ( this->field_128 == 1 || this->field_128 == 21 )
{
SFX_PlayPos((Rnd(4) + 32) | 0x80, &this->mPos, 300);
}
break;
case 7u:
if ( this->field_128 == 3 )
SFX_PlayPos(0x801D, &this->mPos, 500);
break;
case 0x13u:
if ( this->field_128 == 15 )
{
v11.vx = 0;
v11.vy = 0;
v11.vz = 204800;
this->MakeSpriteRing(&v11);
}
break;
case 0x18u:
if ( this->field_128 == 1 || this->field_128 == 12)
SFX_PlayPos((Rnd(4) + 32) | 0x80, &this->mPos, 50);
break;
case 0x1Au:
if ( this->field_128 == 28 )
{
v11.vz = -204800;
v11.vx = 0;
v11.vy = 0;
this->MakeSpriteRing(&v11);
}
break;
}
}
}
// @MEDIUMTODO
i32 CThug::MonitorSpitPlease(void)
{
return 0x11062024;
}
// @Ok
void CThug::CycleOrContinueAnim(
i32 a2,
i32 a3,
i32 a4,
i32 a5)
{
if ( this->field_12A != a2
&& this->field_12A != a3
&& this->field_12A != a4
&& this->field_12A != a5 )
this->CycleAnim(a2, 1);
}
// @Ok
void CThug::Guard(void)
{
switch (this->dumbAssPad)
{
case 0:
this->Neutralize();
this->mCBodyFlags |= 0x10;
if (this->field_38 != 304)
{
this->RunAnim(this->field_298.Bytes[0], 0, -1);
this->field_1F8 = Rnd(5) + 8;
this->dumbAssPad = 5;
break;
}
this->dumbAssPad++;
if (this->field_12A == 11)
{
this->field_142 = 1;
break;
}
else if (this->field_12A != 10)
{
this->RunAnim(0xAu, 0, -1);
break;
}
this->RunAnim(0xA, this->field_128, -1);
case 1:
if ( this->field_142 )
{
this->CycleOrContinueAnim(11, -1, -1, -1);
this->field_230 = Rnd(30) + 20;
this->dumbAssPad++;
}
break;
case 2:
if ( this->field_230-- <= 0 )
{
this->RunAnim(0xCu, 0, -1);
this->dumbAssPad++;
}
break;
case 3:
if ( this->field_142 )
{
this->CycleAnim(3, 1);
this->field_230 = Rnd(30) + 20;
this->dumbAssPad++;
}
break;
case 4:
if ( this->field_230-- <= 0 )
this->dumbAssPad = 0;
break;
case 5:
if ( this->field_142 )
{
if ( --this->field_1F8 == 0 )
{
this->field_1F8 = Rnd(5) + 8;
this->RunAnim(0x15, 0, -1);
this->dumbAssPad++;
}
else
{
this->RunAnim(this->field_298.Bytes[0], 0, -1);
}
}
break;
case 6:
if ( this->MonitorSpitPlease() )
this->dumbAssPad = 5;
break;
default:
print_if_false(0, "Unknown substate!");
break;
}
}
// @NotOk
// stateflags
INLINE i32 CThug::CanAck(
i32 a2,
i32 a3,
i32 a4,
CThug* pThug)
{
if (!this->field_330
&& !this->field_33C
&& (this->CheckStateFlags(reinterpret_cast<SStateFlags*>(0x557CA0), 17) & 0x20))
{
this->mHandleTwo = Mem_MakeHandle(pThug);
this->field_398 = a3;
this->field_39C = a4;
this->field_33C = a2;
this->field_31C.bothFlags = 21;
this->dumbAssPad = 0;
return 1;
}
return 0;
}
// @Ok
void CThug::StrikeUpConversation(void)
{
if (this->DistanceToPlayer(2) <= 1792)
{
CThug *pThug = reinterpret_cast<CThug*>(this->GetClosest(304, 1));
if ((pThug || (pThug = reinterpret_cast<CThug*>(this->GetClosest(312, 1))))
&& Utils_CrapDist(this->mPos, pThug->mPos) < 0x800)
{
i32 v5;
i32 v4 = 4;
this->field_398 = Rnd(7);
this->field_39C = 4;
i32 v6 = 4;
switch ( this->field_398 )
{
case 0:
this->field_398 = -3;
v5 = 160;
break;
case 1:
this->field_398 = -5;
v4 = 6;
v5 = 160;
break;
case 2:
this->field_398 = -7;
v4 = 8;
v5 = 160;
break;
case 3:
this->field_398 = -9;
v4 = 10;
v5 = 160;
this->field_39C = 3;
v6 = 3;
break;
case 4:
this->field_398 = -11;
v4 = 12;
v5 = 160;
this->field_39C = 3;
v6 = 3;
break;
case 5:
this->field_398 = -13;
v4 = 14;
v5 = 160;
this->field_39C = 3;
v6 = 3;
break;
case 6:
this->field_398 = -15;
v4 = 14;
v5 = 160;
this->field_39C = 3;
break;
default:
print_if_false(0, "Too many ack response types.");
v4 = 4;
v5 = 4;
break;
}
if (pThug->CanAck(v5, v4, v6, this))
{
this->field_33C = v5;
this->mHandleTwo = Mem_MakeHandle(pThug);
this->field_31C.bothFlags = 21;
this->dumbAssPad = 0;
}
}
}
}
// @Ok
void CThug::Acknowledge(void)
{
switch (this->dumbAssPad)
{
case 0:
this->mCBodyFlags |= 0x10;
this->Neutralize();
if (this->field_398 < 0)
{
this->RunAnim(this->field_38 != 304 ? 39 : 32, 0, -1);
Redbook_XAPlayPos(this->field_39C, -this->field_398, &this->mPos, 20);
}
if (Mem_RecoverPointer(&this->mHandleTwo))
{
new CAIProc_LookAt(
this,
reinterpret_cast<CBody*>(this->mHandleTwo.field_0),
0,
2,
70,
200);
}
this->dumbAssPad++;
break;
case 1:
if (this->field_142)
this->CycleAnim(this->field_298.Bytes[0], 1);
if (!this->field_33C)
{
if (this->field_398 > 0)
{
Redbook_XAPlayPos(this->field_39C, this->field_398, &this->mPos, 20);
this->RunAnim(this->field_38 != 304 ? 40 : 32, 0, -1);
this->dumbAssPad++;
return;
}
this->field_33C = 2000;
this->field_31C.bothFlags = 2;
this->dumbAssPad = 0;
}
break;
case 2:
if (this->field_142)
{
this->field_33C = 2000;
this->field_31C.bothFlags = 2;
this->dumbAssPad = 0;
}
break;
default:
print_if_false(0, "Unknown substate!");
break;
}
}
// @Ok
void CThug::LookConfused(void)
{
i32 v3;
switch ( this->dumbAssPad )
{
case 0:
this->field_1F8 = Rnd(3) + 2;
this->dumbAssPad++;
case 1:
this->Neutralize();
if ( !this->field_1F8 )
{
this->field_330 = 0;
this->field_31C.bothFlags = 28;
this->dumbAssPad = 0;
}
else
{
this->dumbAssPad = 5;
this->field_1F8 = this->field_1F8 - 1;
}
break;
case 5:
v3 = Rnd(1000) + 1000;
if ( Rnd(2) )
v3 = -v3;
v3 += this->mAngles.vy;
new CAIProc_LookAt(this, v3, 2, 80, 200);
this->dumbAssPad++;
break;
case 6:
this->RunAppropriateAnim();
if ( (this->field_288 & 2) != 0 )
{
this->dumbAssPad = 1;
this->field_288 &= 0xFFFFFFFD;
}
break;
default:
print_if_false(0, "Unknown substate!");
break;
}
}
// @MEDIUMTODO
i32 CThug::WallHitCheck(CVector*, CVector*, i32)
{
return 0x13072024;
}
// @Ok
i32 CThug::GetLaunched(
CVector* a2,
i32 a3,
i32 a4,
i32 a5)
{
i32 v10; // ebx
CVector v13; // [esp+10h] [ebp-18h] BYREF
v13.vy = this->mPos.vy;
v13.vx = (a4 + 1) * a2->vx + this->mPos.vx;
v13.vz = (a4 + 1) * a2->vz + this->mPos.vz;
v10 = this->WallHitCheck(&v13, a2, a4);
if ( v10 == 3 )
return 0;
this->Neutralize();
this->mAccellorVel = *a2;
this->mAccellorVel.vy = 0;
if ( !a3 || v10 == 2 )
{
new CAIProc_LookAt(this, 0, &v13, 0, 80, 200);
}
return v10;
}
// @Ok
u8 CThug::TugImpulse(CVector* a2, CVector* a3, CVector* a4)
{
this->field_2A8 &= 0xFFFFFFF7;
if (a4)
{
this->field_31C.bothFlags = 16;
this->dumbAssPad = 0;
if (this->field_3A4)
Mem_Delete(reinterpret_cast<void*>(this->field_3A4));
this->field_3A4 = a4;
return 1;
}
i32 Launched = this->GetLaunched(a3, 0, 80, 0);
if (!Launched)
{
return 0;
}
if (this->field_E2 <= 50)
{
if (Launched == 1)
{
this->field_2A8 |= 0x10;
}
else
{
this->field_2A8 &= ~0x10;
}
}
this->field_218 |= 0x80000;
SFX_PlayPos(0x800F, &this->mPos, 0);
this->field_31C.bothFlags = 14;
this->dumbAssPad = 0;
return 1;
}
// @Ok
void CThug::CheckFallBack(void)
{
CVector v6;
CVector a3;
a3.vx = 0;
a3.vy = 0;
a3.vz = 0;
v6.vz = ((this->field_2A8 & 0x10) ? -75 : 75) << 12;
v6.vy = 0;
v6.vx = 0;
Utils_RotateY(&a3, &v6, this->mAngles.vy);
if ( this->PathCheck(&this->mPos, &(this->mPos + a3), 0, 55) == 2 )
{
new CAIProc_RotY(this, 2047, 4, 0);
}
}
// @Ok
void CThug::GetReadyToShootHostage(CMessage *pMessage)
{
CItem *pItem = reinterpret_cast<CItem*>(Mem_RecoverPointer(&pMessage->mHandle));
if ( pItem )
{
if ( Utils_LineOfSight(&this->mPos, &pItem->mPos, 0, 0) )
{
this->mHandle = pMessage->mHandle;
this->field_31C.bothFlags = 8;
this->dumbAssPad = 0;
this->Neutralize();
new CAIProc_StateSwitchSendMessage(this, 16);
}
else
{
new CMessage(this, reinterpret_cast<CBaddy*>(pMessage->mHandle.field_0), 1, 0);
}
pMessage->field_10 |= 1;
}
}
// @Ok
// @Test
void CThug::SetParamByIndex(i32 Index, i32 Param)
{
switch ( Index )
{
case 1:
this->field_374 = Param;
break;
case 2:
this->field_370 = Param;
break;
case 3:
this->field_378 = Param;
break;
case 4:
this->field_37C = Param;
break;
case 5:
this->field_380 = Param;
break;
case 6:
this->field_384 = Param;
break;
case 7:
this->field_388 = Param;
break;
case 8:
this->field_38C = Param;
break;
case 9:
this->field_1FC = Param;
break;
case 10:
this->field_394 = Param;
break;
case 11:
if (Param)
this->field_218 |= 0x800;
else
this->field_218 &= 0xFFFFF7FF;
break;
case 12:
this->field_218 |= 0x8000;
break;
default:
print_if_false(0, "Unknown index in C_SET_PARAMETER_BY_INDEX");
break;
}
}
// @Ok
void CThug::SetHitDirectionFlag(CVector* pVector)
{
CSVector v4;
v4.vx = 0;
v4.vy = 0;
v4.vz = 0;
Utils_CalcAim(&v4, &(this->mPos + (*pVector * 300)), &this->mPos);
i32 v3 = v4.vy - this->mAngles.vy;
if (v3 < -2048)
{
v3 += 4096;
}
else
{
if (v3 > 2048)
v3 -= 4096;
}
if (v3 < -455)
{
this->field_218 |= 0x20000;
}
else
{
if (v3 > 455)
this->field_218 |= 0x10000;
}
}
// @NotOk
// Globals
// also a little out of order with the v6 | 1 thing :(
CThug::CThug(int *a2, int a3)
{
__int16 *v5 = this->SquirtAngles(reinterpret_cast<i16*>(this->SquirtPos(a2)));
this->field_3B8 = Trig_GetLevelId();
this->ShadowOn();
this->field_D0 = 50;
this->field_3B0 = *dword_5FCCF4;
this->AttachTo(reinterpret_cast<CBody**>(&BaddyList));
int v6 = this->field_2A8;
this->field_1F4 = a3;
this->field_DE = a3;
__int16 v7 = this->field_38;
this->field_230 = 0;
this->field_216 = 32;
this->field_2A8 = v6 | 1;
this->field_DC = v7 != 304 ? 150 : 96;
this->field_D8 = 64;
this->field_380 = v7 != 304 ? 400 : 300;
this->field_31C.bothFlags = 0;
this->field_370 = 3500;
this->field_374 = 400;
this->field_378 = 2047;
this->field_37C = 100;
this->field_384 = 1500;
this->field_388 = 10;
this->field_38C = 10;
this->field_1FC = 10;
this->field_394 = 2000;
this->ParseScript(reinterpret_cast<unsigned __int16*>(v5));
this->field_212 = 60;
}
// @Ok
void Thug_CreateTHug(const unsigned int *stack, unsigned int *result)
{
int* v2 = reinterpret_cast<int*>(*stack);
int v3 = static_cast<int>(stack[1]);
*result = reinterpret_cast<unsigned int>(new CThug(v2, v3));
}
// @Ok
void __inline CThugPing::SetPosition(void)
{
CSuper* v2 = reinterpret_cast<CSuper*>(Mem_RecoverPointer(&this->field_70));
if (!v2)
this->Die();
else
M3dUtils_GetDynamicHookPosition(
reinterpret_cast<VECTOR*>(&this->mPos),
v2,
&this->field_78);
}
// @Ok
void CThugPing::Move(void)
{
this->SetPosition();
Bit_ReduceRGB(&this->mCodeBGR, 7);
if ((this->mCodeBGR & 0xFFFFFF) == 0)
this->Die();
}
static unsigned char gAttackFlagRelated;
// @Ok
void CThug::ClearAttackFlags(void)
{
if ( gGlobalThug == this )
{
gGlobalThug = 0;
}
else if (this->field_3BC & 2)
{
gAttackFlagRelated &= ~this->field_3BD;
}
this->field_3BC = 0;
this->field_3BD = 0;
}
static i32 gThugTypeRelatedFirstFirst;
static i32 gThugTypeRelatedFirstSecond;
static u8 gThugTypeRelatedFirstThird;
static i32 gThugTypeRelatedSecondFirst;
static i32 gThugTypeRelatedSecondSecond;
static u8 gThugTypeRelatedSecondThird;
// @NotOk
// globals
void CThug::SetThugType(int type)
{
this->field_38 = type;
switch (type)
{
case 304:
this->InitItem("thug");
this->field_21E = 100;
this->field_294.Int = gThugTypeRelatedFirstFirst;
this->field_298.Int = gThugTypeRelatedFirstSecond;
M3dUtils_ReadHooksPacket(this, &gThugTypeRelatedFirstThird);
break;
case 312:
if (Trig_GetLevelId() == 513)
this->InitItem("henchngt");
else
this->InitItem("henchman");
this->field_294.Int = gThugTypeRelatedSecondFirst;
this->field_298.Int = gThugTypeRelatedSecondSecond;
M3dUtils_ReadHooksPacket(this, &gThugTypeRelatedSecondThird);
break;
default:
print_if_false(0, "Unknown thug type!");
}
}
// @BIGTODO
void CThug::RunToWhereTheActionIs(CVector*)
{}
// @Ok
void CThug::HelpOutBuddy(CMessage *pMessage)
{
if (this->field_31C.bothFlags == 2 || this->field_31C.bothFlags == 1)
{
CItem *pItem = reinterpret_cast<CItem*>(Mem_RecoverPointer(&pMessage->mHandle));
if (pItem)
this->RunToWhereTheActionIs(&pItem->mPos);
}
}
// @Ok
INLINE void CThug::PlayHitWallSound(void)
{
if (!this->field_1F8)
{
if (this->field_218 & 0x400)
{
SFX_PlayPos(0x802F, &this->mPos, 0);
}
else
{
SFX_PlayPos(0x802E, &this->mPos, 0);
}
}
}
// @Ok
INLINE void CThug::StandStill(void)
{
switch (this->dumbAssPad)
{
case 0:
this->Neutralize();
this->CycleAnim(this->field_38 != 304 ? 15 : 17, 1);
this->dumbAssPad++;
break;
default:
print_if_false(0, "Unknown substate.");
break;
}
}
// @Ok
void CThug::DieAfterFlyingAcrossRoom(void)
{
if (this->ShouldFall(200, 0x5F000))
{
this->field_218 &= 0xFFFFFFFD;
this->field_31C.bothFlags = 22;
}
else
{
this->SetHeight(1, 100, 600);
this->PlayHitWallSound();
this->field_31C.bothFlags = 26;
}
this->dumbAssPad = 0;
}
// @Ok
INLINE void CThug::RunAppropriateHitAnim(void)
{
i32 anim;
if (this->field_218 & 0x10000)
{
anim = this->field_38 != 304 ? 38 : 43;
}
else if (this->field_218 & 0x20000)
{
anim = this->field_38 != 304 ? 37 : 42;
}
else
{
anim = this->field_38 != 304 ? 18 : 25;
}
this->RunAnim(anim, 0, -1);
}
// @Ok
INLINE void CThug::StopShooting(void)
{
switch (this->dumbAssPad)
{
case 0:
this->RunAnim(9, 0, -1);
this->dumbAssPad++;
break;
case 1:
if (this->field_142)
{
this->field_31C.bothFlags = 28;
this->dumbAssPad = 0;
}
break;
default:
print_if_false(0, "Unknown substate!");
break;
}
}
// @Ok
i32 CThug::TryAddingCollidePointToPath(CVector* pVector)
{
if (Utils_CrapDist(*pVector, this->mPos) < 0x64)
return 0;
CVector v5 = *pVector - this->mPos;
v5 >>= 0xC;
v5 *= 0xE74;
v5 += this->mPos;
return this->AddPointToPath(&v5, 0);
}
void validate_CThug(void){
VALIDATE_SIZE(CThug, 0x3C0);
VALIDATE(CThug, field_330, 0x330);
VALIDATE(CThug, field_33C, 0x33C);
VALIDATE(CThug, mHandle, 0x354);
VALIDATE(CThug, mHandleTwo, 0x35C);
VALIDATE(CThug, field_370, 0x370);
VALIDATE(CThug, field_374, 0x374);
VALIDATE(CThug, field_378, 0x378);
VALIDATE(CThug, field_37C, 0x37C);
VALIDATE(CThug, field_380, 0x380);
VALIDATE(CThug, field_384, 0x384);
VALIDATE(CThug, field_388, 0x388);
VALIDATE(CThug, field_38C, 0x38C);
VALIDATE(CThug, field_394, 0x394);
VALIDATE(CThug, field_398, 0x398);
VALIDATE(CThug, field_39C, 0x39C);
VALIDATE(CThug, field_3A0, 0x3A0);
VALIDATE(CThug, field_3A4, 0x3A4);
VALIDATE(CThug, field_3B0, 0x3B0);
VALIDATE(CThug, field_3B8, 0x3B8);
VALIDATE_SIZE(IntToBytes, 0x4);
}
void validate_CThugPing(void)
{
VALIDATE_SIZE(CThugPing, 0x80);
VALIDATE(CThugPing, field_70, 0x70);
VALIDATE(CThugPing, field_78, 0x78);
}