spidey-decomp/baddy.cpp
2024-06-11 19:46:14 +02:00

903 lines
16 KiB
C++

#include "baddy.h"
#include "validate.h"
#include "utils.h"
#include "mem.h"
#include "message.h"
#include "web.h"
#include <cmath>
#include "trig.h"
// @TODO
void CBaddy::RunAppropriateAnim(void)
{}
// @TODO
int CBaddy::SmackSpidey(int, CVector*, int, int)
{
return 0x06062024;
}
// @NotOk
// Global
int CBaddy::DistanceToPlayer(int a2){
int v3; // eax
int result; // eax
v3 = this->field_208;
int dwordRead = *dword_5FCCF4;
if ( v3 && dwordRead - v3 <= a2 )
return this->field_204;
this->field_208 = dwordRead;
result = Utils_CrapXZDist(this->mPos, globalSuper->mPos);
this->field_204 = result;
return result;
}
// @Ok
int CBaddy::TrapWeb(void){
if((this->field_2A8 & 0x10000) || (this->field_E2 <= 0)){
return 0;
}
new CMessage(NULL, this, 5, 0);
return 1;
}
// @NotOk
// Replace fastcall with proper call
void CBaddy::CleanUpMessages(int a2, int a3)
{
int v3 = reinterpret_cast<int>(this->field_28C);
int v4;
while (v3)
{
v4 = v3;
v3 = *reinterpret_cast<int*>(v3 + 28);
if ((*reinterpret_cast<unsigned char*>(v4+16) & 1) || a2 || *reinterpret_cast<int*>(v4+20) == a3)
{
if (v4)
{
typedef void (FASTCALL *wtvHappeningPtr)(void*, void*, int);
wtvHappeningPtr wtvHappening = reinterpret_cast<wtvHappeningPtr>(**reinterpret_cast<int**>(v3));
wtvHappening(reinterpret_cast<void*>(v3), NULL, 1);
}
}
}
}
// @Ok
int CBaddy::CheckStateFlags(SStateFlags *sFlags, int a3){
if(this->field_314 < 0){
if (this->field_31C.bothFlags == -this->field_314)
return 0;
}
else if(this->field_31C.bothFlags == sFlags[this->field_314].flags[0]){
print_if_false(sFlags[this->field_314].flags[1] != 0, "This shouldn't be zero. Remove state from table.");
return sFlags[this->field_314].flags[1];
}
for (int i = 0; i< a3; i++){
if (this->field_31C.bothFlags != (unsigned __int16) sFlags[i].flags[0]){
continue;
}
this->field_314 = i;
print_if_false(sFlags[i].flags[1] != 0, "This shouldn't be zero. Remove state from table.");
return sFlags[i].flags[1];
}
this->field_314 = -this->field_31C.flags[0];
return 0;
}
// Revisit??
int CBaddy::YawTowards(int a2, int a3){
int vy; // edi
int v4; // eax
int v5; // edx
vy = this->mAngles.vy;
v4 = a2 - vy;
if ( a2 - vy < -2048 )
v4 += 4096;
if ( v4 > 2048 )
v4 -= 4096;
if ( !v4 )
{
this->field_8E.vy = 0;
this->csVector1.vy = 0;
return v4;
}
v5 = (a3 * v4) >> 8;
this->mAngles.vy += v5;
if ( v5 && ((int)this->mAngles.vy - a2 > 0) != (vy - a2> 0))
{
return v4;
}
this->mAngles.vy = a2;
this->field_8E.vy = 0;
this->csVector1.vy = 0;
return 0;
}
// @Ok
int CBaddy::RunTimer(int *a2)
{
*a2 -= this->field_80;
if ( *a2 < 0 )
*a2 = 0;
return *a2;
}
// @TODO
int CBaddy::PathCheckGuts(CVector*, CVector*, CVector*, int)
{
return 0x14141414;
}
static int * const dword_5FBEE0 = (int*)0x5FBEE0;;
// @NotOk
// Globals (rest is matching)
int CBaddy::PathCheck(CVector* a2, CVector* a3, CVector* a4, int a5)
{
int v5 = *dword_5FBEE0;
if ( (this->field_2A8 & 0x2000))
*dword_5FBEE0 = 1;
int result = this->PathCheckGuts(a2, a3, a4, a5);
*dword_5FBEE0 = v5;
return result;
}
static CBody** const dword_56E990 = (CBody**)0x56E990;
// @Ok
CBody* CBaddy::StruckGameObject(int a2, int a3)
{
CBody *result;
if ( !a2
|| (result = Utils_CheckObjectCollision(
&this->field_2FC,
&this->mPos,
globalSuper,
this)) == 0 )
{
if (a3 && (result = Utils_CheckObjectCollision(&this->field_2FC, &this->mPos, *dword_56E990, this)))
{
print_if_false(result != this, "smoething's wrong in the state of denmark");
return result;
}
return NULL;
}
return result;
}
// @Ok
void CBaddy::Neutralize(void)
{
this->MarkAIProcList(1, 0, 0);
this->gVec.vz = 0;
this->gVec.vy = 0;
this->gVec.vz = 0;
this->mAccellorVel.vz = 0;
this->mAccellorVel.vy = 0;
this->mAccellorVel.vx = 0;
this->gVec.vz = 0;
this->gVec.vy = 0;
this->gVec.vx = 0;
this->csVector1.vz = 0;
this->csVector1.vy = 0;
this->csVector1.vx = 0;
this->field_8E.vz = 0;
this->field_8E.vy = 0;
this->field_8E.vx = 0;
this->field_27C.vz = 0;
this->field_27C.vy = 0;
this->field_27C.vx = 0;
this->field_2A8 &= 0xB7FFFFFB;
}
// @Ok
int CBaddy::TugWeb(void)
{
if ( (this->field_2A8 & 0x200) || this->field_E2 <= 0)
{
CTrapWebEffect *trapWeb = reinterpret_cast<CTrapWebEffect*>(
Mem_RecoverPointer(reinterpret_cast<SHandle*>(&this->field_10C)));
if (trapWeb)
trapWeb->Burst();
return 0;
}
new CMessage(0, this, 6, 0);
return 1;
}
// @Ok
void __inline CBaddy::GetLocalPos(CVector *a2, CVector *a3, CSVector *a4)
{
MATRIX v7;
if (a4)
{
M3dMaths_RotMatrixYXZ(
reinterpret_cast<SVECTOR*>(a4),
&v7);
}
else
{
M3dMaths_RotMatrixYXZ(
reinterpret_cast<SVECTOR*>(&this->mAngles),
&v7);
}
gte_SetRotMatrix(&v7);
*a3 = *a2;
gte_ldlvl(reinterpret_cast<VECTOR*>(a3));
gte_rtir();
gte_stlvnl(reinterpret_cast<VECTOR*>(a3));
}
// @Ok
int CBaddy::MakeSpriteRing(CVector* arg0)
{
CVector mPos;
mPos.vx = 0;
mPos.vy = 0;
mPos.vz = 0;
if (!arg0)
{
mPos = this->mPos;
}
else
{
CVector tmp = *arg0;
tmp >>= 12;
this->GetLocalPos(&tmp, &mPos, 0);
mPos <<= 12;
mPos += this->mPos;
}
mPos.vy = Utils_GetGroundHeight(&this->mPos, 300, 600, 0) - 0xA000;
return Bit_MakeSpriteRing(&mPos, 24, 8, 1, 512, 32, 16, 0);
}
// @Ok
int CBaddy::SetHeight(int a2, int a3, int a4)
{
int v5 = this->field_2A8;
if (v5 & 0x8000)
{
return 1;
}
int *v7 = &this->field_2A4;
if (this->field_2A4
|| a2
|| (v5 & 0x40000) != 0
|| (v5 & 0x8000000) != 0 && ((v5 & 0x20000000) != 0 || (this->field_2F0 & 4) != 0) )
{
unsigned char v9;
if (a2 || (
v9 = this->field_80, v9 += this->field_213,
v9 >= this->field_212))
{
CVector v16;
v16.vx = this->mPos.vx;
v16.vy = (this->field_21E << 12) + this->mPos.vy;
v16.vz = this->mPos.vz;
int height = Utils_GetGroundHeight(&v16, a3, a4, reinterpret_cast<CBody**>(&this->field_2A4));
if (height == -1)
{
return 0;
}
int v7Value = *v7;
if (v7Value)
{
int v12 = *reinterpret_cast<int*>(v7Value + 0x64);
if (!v12)
{
*v7 = v12;
}
else
{
height += v12;
}
}
this->field_2A0 = height;
if (!this->field_212)
this->field_212 = 30;
this->field_213 = 0;
}
}
// label 21
int v13 = this->field_2A0 - (this->field_21E << 12);
int vy = this->mPos.vy;
if (v13 != vy)
{
int v15 = ((v13 - vy) >> 2) + vy;
this->mPos.vy = v15;
if ( abs(v15 - v13) <= (*v7 != 0 ? 122880 : 12888))
{
this->mPos.vy = v13;
}
else
{
return 1;
}
}
return 2;
}
// @Ok
void __inline CBaddy::SendDeathPulse(void)
{
if (!this->field_211 && this->field_DE != (__int16)0xFFFF)
{
this->field_211 = 1;
Trig_SendPulse(
reinterpret_cast<unsigned __int16*>(Trig_GetLinksPointer(this->field_DE & 0xFFFF)));
}
}
// @Ok
int CBaddy::Die(int a2)
{
if(!this->IsDead())
{
int v8;
int v9;
switch (a2)
{
case 0:
if (!(this->field_2A8 & 0x4000))
{
this->SendDeathPulse();
}
case 3:
this->mCBodyFlags |= 0x40;
this->mFlags |= 1;
break;
case 1:
if (!(this->field_2A8 & 0x4000))
{
this->SendDeathPulse();
}
this->mFlags |= 0x800;
this->field_30 = 128;
this->KillShadow();
this->mFlags |= 0x400;
this->field_24 = 0x404040;
this->field_1F8 = 0;
break;
case 2:
v8 = this->field_1F8;
v9 = v8 + 1;
this->field_1F8 = v9;
if ( v8 >= 40 )
return 1;
v9 = ((6553 * (40 - v9)) >> 12);
v8 = v9;
v8 <<= 8;
v8 |= v9;
v8 <<= 8;
v8 |= v9;
this->field_24 = v8;
break;
default:
print_if_false(0, "Unknown die state");
}
}
return 0;
}
// @NotOk
// Calling a vfunc with fastcall, basically matching but polluting edx
void CBaddy::CleanUpAIPRocList(int a2)
{
int v2 = reinterpret_cast<int>(this->field_28C);
int v3;
while (v2)
{
v3 = v2;
v2 = *reinterpret_cast<int*>(v2 + 28);
if (a2 || (*reinterpret_cast<unsigned char*>(v3 + 16) & 1))
{
if (v3)
{
typedef void (FASTCALL *wtvHappeningPtr)(void*, void*, int);
wtvHappeningPtr wtvHappening = reinterpret_cast<wtvHappeningPtr>(**reinterpret_cast<int**>(v3));
wtvHappening(reinterpret_cast<void*>(v3), NULL, 1);
}
}
}
}
// @NotOk
// Gloabsl
// and vz
int CBaddy::BumpedIntoSpidey(int a2)
{
int v3 = this->field_208;
int v4;
if (v3 && *dword_5FCCF4 <= 4)
{
v4 = this->field_204;
}
else
{
this->field_208 = *dword_5FCCF4;
v4 = Utils_CrapXZDist(this->mPos, globalSuper->mPos);
this->field_204 = v4;
}
if (v4 < a2)
{
__int16 vz = *reinterpret_cast<__int16*>(globalSuper + 0x754); // wrong
int twoOneE = this->field_21E;
int res = twoOneE - vz - (globalSuper->mPos.vy >> 12) + (this->mPos.vy >> 12);
int shifted = res >> 31;
if ( (((shifted) ^ res) - shifted) < 200)
return 1;
}
return 0;
}
// @Ok
int CBaddy::PlayerIsVisible(int a2)
{
if (!globalSuper->IsDead() &&
Utils_LineOfSight(&this->mPos, &globalSuper->mPos, 0, 0)
)
{
if (!this->PathCheck( &this->mPos, &globalSuper->mPos, 0, 55))
{
this->field_1A8 = globalSuper->mPos;
this->field_2A8 |= 0x800;
}
return 1;
}
return 0;
}
// @Ok
int CBaddy::ShouldFall(int a2, int a3)
{
int GroundHeight = Utils_GetGroundHeight(&this->mPos, a2, 4096, 0);
if (GroundHeight == -1)
{
this->field_308 = this->mPos.vy - 100;
this->KillShadow();
this->field_2A8 &= 0xFFFFFBFF;
return GroundHeight;
}
int v7 = GroundHeight - (this->field_21E << 12);
if (v7 - this->mPos.vy > a3)
{
this->KillShadow();
this->field_308 = v7;
this->field_2A8 |= 0x400;
return v7 - this->mPos.vy;
}
return 0;
}
// @NotOk
// Globals
int CBaddy::CheckSightCone(int a2, int a3, int a4, int a5, CBody *a6)
{
CSVector v16;
v16.vx = 0;
v16.vy = 0;
v16.vz = 0;
if (!a3)
return 0;
int v12 = a6->mPos.vy - this->mPos.vy;
if (abs(v12) > (a3 << 12))
return 0;
int v13;
if (a6 == globalSuper)
{
v13 = this->DistanceToPlayer(2);
}
else
{
v13 = Utils_CrapXZDist(this->mPos, a6->mPos);
}
if (v13 < a5)
return 1;
if (v13 > a4)
return 0;
Utils_CalcAim(&v16, &this->mPos, &a6->mPos);
int v14 = v16.vy - this->mAngles.vy;
if (v14 < -2048)
{
v14 += 4096;
}
else if (v14 >= -2048)
{
if (v14 > 2048)
{
v14 -= 4096;
}
}
return abs(v14) <= (a2 >> 1);
}
// @TODO
void CBaddy::ParseScript(unsigned __int16*)
{}
// @NotOk
// Globals
CBaddy::CBaddy(void)
{
this->field_1A8.vx = 0;
this->field_1A8.vy = 0;
this->field_1A8.vz = 0;
for(int i=0; i<5; i++)
{
this->field_1B4[i].vx = 0;
this->field_1B4[i].vy = 0;
this->field_1B4[i].vz = 0;
}
this->field_240 = 0;
this->field_244 = 0;
this->field_248 = 0;
this->field_27C.vx = 0;
this->field_27C.vy = 0;
this->field_27C.vz = 0;
this->field_2B8.vx = 0;
this->field_2B8.vy = 0;
this->field_2B8.vz = 0;
this->field_2C4 = 0;
this->field_2C8 = 0;
this->field_2CC = 0;
this->field_2D0.vx = 0;
this->field_2D0.vy = 0;
this->field_2D0.vz = 0;
this->field_2DC = 0;
this->field_2DE = 0;
this->field_2E0 = 0;
this->field_2E2 = 0;
this->field_2E4 = 0;
this->field_2E6 = 0;
this->field_2E8.vx = 0;
this->field_2E8.vy = 0;
this->field_2E8.vz = 0;
this->field_2FC.vx = 0;
this->field_2FC.vy = 0;
this->field_2FC.vz = 0;
int *dword_56E98C = reinterpret_cast<int*>(0x56E98C);
this->field_21D = *dword_56E98C;
*dword_56E98C = *dword_56E98C + 1;
this->field_DC = 128;
this->field_F4 = 128;
this->field_DE = -1;
this->field_216 = 32;
this->field_D8 = 64;
}
// @Ok
void CBaddy::CreateCombatImpactEffect(CVector*, int)
{
}
// @TODO
unsigned char CBaddy::TugImpulse(CVector*, CVector*, CVector*)
{
return (unsigned char)0x21052024;
}
// @NotOk
// Figure out name
void CBaddy::UnknownCBaddyFunctionTwo()
{
}
// @NotOk
// Figure out name
void CBaddy::UnknownCBaddyFunctionThree(int, int)
{
}
// @Ok
char CBaddy::UnknownCBaddyFunctionFour(int)
{
return 0;
}
// @Ok
void CBaddy::Shouldnt_DoPhysics_Be_Virtual(void)
{
this->DoPhysics(0);
}
// @NotOk
// Figure out name
void CBaddy::UnknownCBaddyFunctionFive(int)
{
}
// @TODO
int CBaddy::GetClosest(int, int)
{
return 0x888999;
}
// @TODO
int CBaddy::ExecuteCommand(unsigned __int16)
{
return 0x21052025;
}
// @TODO
void CBaddy::SetVariable(unsigned __int16)
{
printf("test");
}
// @TODO
unsigned __int16 CBaddy::GetVariable(unsigned __int16)
{
return 0x696940;
}
// @TODO
void CBaddy::DoPhysics(int)
{
}
// @Ok
void CBaddy::Baddy_SendSignal(void)
{
unsigned __int16 *ptr = reinterpret_cast<unsigned __int16*>(
Trig_GetLinksPointer((unsigned __int16)this->field_DE));
if (ptr)
Trig_SendSignalToLinks(ptr);
}
static CBaddy* gBaddylist;
// @Ok
CBaddy* FindBaddyOfType(int type)
{
CBaddy *current = gBaddylist;
if (current)
{
while (current)
{
if (current->field_38 == type)
{
return current;
}
current = reinterpret_cast<CBaddy*>(current->field_20);
}
}
return NULL;
}
// @Ok
void CBaddy::MarkAIProcList(int a2, int a3, int a4)
{
unsigned int *head = this->field_28C;
while (head)
{
unsigned int *v5 = head;
head = reinterpret_cast<unsigned int*>(head[7]);
unsigned int v6;
if (a2 && !(v5[2] & 0x20000) || a3 && (v5[2] & 0xFF00) == a3)
{
v6 = v5[4] | 1;
}
else
{
if (!a4 || (v5[2] & 0xFF00) != a4)
continue;
v6 = v5[4] | 4;
}
v5[4] = v6;
}
}
void validate_CBaddy(void){
VALIDATE_SIZE(CBaddy, 0x324);
VALIDATE(CBaddy, field_194, 0x194);
VALIDATE(CBaddy, field_198, 0x198);
VALIDATE(CBaddy, field_1A8, 0x1A8);
VALIDATE(CBaddy, field_1B4, 0x1B4);
VALIDATE(CBaddy, field_1F0, 0x1F0);
VALIDATE(CBaddy, field_1F4, 0x1F4);
VALIDATE(CBaddy, field_1F8, 0x1F8);
VALIDATE(CBaddy, field_1FC, 0x1FC);
VALIDATE(CBaddy, field_1FE, 0x1FE);
VALIDATE(CBaddy, field_204, 0x204);
VALIDATE(CBaddy, field_208, 0x208);
VALIDATE(CBaddy, field_20C, 0x20C);
VALIDATE(CBaddy, field_20F, 0x20F);
VALIDATE(CBaddy, field_210, 0x210);
VALIDATE(CBaddy, field_211, 0x211);
VALIDATE(CBaddy, field_212, 0x212);
VALIDATE(CBaddy, field_213, 0x213);
VALIDATE(CBaddy, field_216, 0x216);
VALIDATE(CBaddy, field_218, 0x218);
VALIDATE(CBaddy, field_21D, 0x21D);
VALIDATE(CBaddy, field_21E, 0x21E);
VALIDATE(CBaddy, registerArr, 0x220);
VALIDATE(CBaddy, field_230, 0x230);
VALIDATE(CBaddy, field_234, 0x234);
VALIDATE(CBaddy, field_23C, 0x23C);
VALIDATE(CBaddy, field_240, 0x240);
VALIDATE(CBaddy, field_244, 0x244);
VALIDATE(CBaddy, field_248, 0x248);
VALIDATE(CBaddy, field_24C, 0x24C);
VALIDATE(CBaddy, attributeArr, 0x270);
VALIDATE(CBaddy, field_27C, 0x27C);
VALIDATE(CBaddy, field_288, 0x288);
VALIDATE(CBaddy, field_28C, 0x28C);
VALIDATE(CBaddy, pMessage, 0x290);
VALIDATE(CBaddy, field_294, 0x294);
VALIDATE(CBaddy, field_298, 0x298);
VALIDATE(CBaddy, field_2A0, 0x2A0);
VALIDATE(CBaddy, field_2A4, 0x2A4);
VALIDATE(CBaddy, field_2A8, 0x2A8);
VALIDATE(CBaddy, field_2AC, 0x2AC);
VALIDATE(CBaddy, field_2B0, 0x2B0);
VALIDATE(CBaddy, field_2B4, 0x2B4);
VALIDATE(CBaddy, field_2B8, 0x2B8);
VALIDATE(CBaddy, field_2C4, 0x2C4);
VALIDATE(CBaddy, field_2C8, 0x2C8);
VALIDATE(CBaddy, field_2CC, 0x2CC);
VALIDATE(CBaddy, field_2D0, 0x2D0);
VALIDATE(CBaddy, field_2DC, 0x2DC);
VALIDATE(CBaddy, field_2DE, 0x2DE);
VALIDATE(CBaddy, field_2E0, 0x2E0);
VALIDATE(CBaddy, field_2E2, 0x2E2);
VALIDATE(CBaddy, field_2E4, 0x2E4);
VALIDATE(CBaddy, field_2E6, 0x2E6);
VALIDATE(CBaddy, field_2E8, 0x2E8);
VALIDATE(CBaddy, field_2F0, 0x2F0);
VALIDATE(CBaddy, field_2F4, 0x2F4);
VALIDATE(CBaddy, field_2F8, 0x2F8);
VALIDATE(CBaddy, field_2FC, 0x2FC);
VALIDATE(CBaddy, field_308, 0x308);
VALIDATE(CBaddy, field_310, 0x310);
VALIDATE(CBaddy, field_314, 0x314);
VALIDATE(CBaddy, field_318, 0x318);
VALIDATE(CBaddy, field_31C, 0x31C);
VALIDATE(CBaddy, dumbAssPad, 0x320);
VALIDATE_VTABLE(CBaddy, AI, 2);
VALIDATE_VTABLE(CBaddy, Hit, 3);
VALIDATE_VTABLE(CBaddy, PlayerIsVisible, 5);
VALIDATE_VTABLE(CBaddy, TugImpulse, 7);
VALIDATE_VTABLE(CBaddy, GetClosest, 13);
}
void validate_CScriptOnlyBaddy(void){
VALIDATE_SIZE(CScriptOnlyBaddy, 0x330);
VALIDATE(CScriptOnlyBaddy, field_328, 0x328);
VALIDATE(CScriptOnlyBaddy, field_32C, 0x32C);
VALIDATE(CScriptOnlyBaddy, field_32E, 0x32E);
}
void validate_SStateFlags(void){
VALIDATE_SIZE(SStateFlags, 0x4);
}