Name remaining aibot properties

This commit is contained in:
Ryan Dwyer 2023-05-28 14:07:16 +10:00
parent 2e386f7a34
commit 953afe9925
18 changed files with 256 additions and 245 deletions

View File

@ -133,7 +133,7 @@ void botReset(struct chrdata *chr, u8 respawning)
aibot->burstsdone[0] = 0;
aibot->burstsdone[1] = 0;
aibot->skrocket = NULL;
aibot->unk0a0 = 0;
aibot->htbheldtimer60 = 0;
aibot->hasbriefcase = false;
aibot->hascase = false;
aibot->cloakdeviceenabled = false;
@ -141,8 +141,8 @@ void botReset(struct chrdata *chr, u8 respawning)
aibot->unk04c_04 = false;
aibot->unk04c_03 = false;
aibot->hasuplink = false;
aibot->unk064 = 0;
aibot->unk04c_00 = false;
aibot->flags = 0;
aibot->inhill = false;
aibot->hillpadnum = -1;
aibot->hillcovernum = -1;
aibot->lastknownhill = -1;
@ -163,8 +163,8 @@ void botReset(struct chrdata *chr, u8 respawning)
aibot->targetinsight = 0;
aibot->queryplayernum = 0;
aibot->unk040 = 0;
aibot->unk06c = 0;
aibot->unk070 = 0;
aibot->speedmultforwards = 0;
aibot->speedmultsideways = 0;
aibot->maulercharge[1] = 0;
aibot->maulercharge[0] = 0;
aibot->shotspeed.x = 0;
@ -180,22 +180,21 @@ void botReset(struct chrdata *chr, u8 respawning)
}
aibot->waypoints[0] = NULL;
aibot->unk208 = 0;
aibot->numwaystepstotarget = 0;
aibot->random1 = random();
aibot->random1ttl60 = 0;
aibot->targetcloaktimer60 = 0;
aibot->canseecloaked = 0;
aibot->rcpcloaktimer60 = 0;
aibot->random2ttl60 = 0;
aibot->unk2c4 = 0;
aibot->random2 = random();
aibot->randomfrac = RANDOMFRAC();
aibot->cheap = 0;
#if VERSION >= VERSION_NTSC_1_0
aibot->unk078 = 0;
aibot->unk050 = 0;
aibot->unk09d = 0;
aibot->forceslowupdates = 0;
aibot->distoverrideprop = NULL;
aibot->distoverridetimer60 = 0;
#endif
}
@ -204,15 +203,20 @@ void botReset(struct chrdata *chr, u8 respawning)
}
if (aibot->config->difficulty == BOTDIFF_DARK) {
aibot->unk064 &= ~1;
// @bug: This is unsetting the UNLIMITEDAMMO flag rather than setting it.
// It could have been intentional - they could have experimented with
// darksims having unlimited ammo during development before disabling
// the feature - but then it would make more sense to remove the flag
// rather than invert it.
aibot->flags &= ~BOTFLAG_UNLIMITEDAMMO;
if (mpHasShield()) {
chr->cshield = 8;
}
}
aibot->unk059 = 1;
aibot->unk058 = TICKS(120);
aibot->respawning = true;
aibot->fadeintimer60 = TICKS(120);
}
}
@ -245,12 +249,12 @@ void botSpawn(struct chrdata *chr, u8 respawning)
thing = scenarioChooseSpawnLocation(chr->radius, &pos, rooms, chr->prop);
chr->hidden |= CHRHFLAG_WARPONSCREEN;
chrMoveToPos(chr, &pos, rooms, thing, true);
chr->aibot->unk0a4 = modelGetChrRotY(chr->model);
chr->aibot->roty = modelGetChrRotY(chr->model);
chr->aibot->angleoffset = 0;
chr->aibot->speedtheta = 0;
chr->aibot->unk0b0 = modelGetChrRotY(chr->model);
chr->aibot->unk0b4 = 0;
chr->aibot->unk0b8 = 0;
chr->aibot->lookangle = modelGetChrRotY(chr->model);
chr->aibot->moveratex = 0;
chr->aibot->moveratey = 0;
func0f02e9a0(chr, 0);
}
}
@ -730,16 +734,16 @@ bool botApplyMovement(struct chrdata *chr)
aibot = chr->aibot;
angle = chrGetInverseTheta(chr) - func0f03e578(chr);
angle = chrGetInverseTheta(chr) - chrGetRotY(chr);
if (angle < 0) {
angle += M_BADTAU;
}
speedforwards = aibot->unk06c * cosf(angle) - sinf(angle) * aibot->unk070;
speedsideways = aibot->unk06c * sinf(angle) + cosf(angle) * aibot->unk070;
speedforwards = aibot->speedmultforwards * cosf(angle) - sinf(angle) * aibot->speedmultsideways;
speedsideways = aibot->speedmultforwards * sinf(angle) + cosf(angle) * aibot->speedmultsideways;
playerChooseThirdPersonAnimation(chr, botGuessCrouchPos(chr), speedsideways, speedforwards, aibot->speedtheta, &aibot->angleoffset, &aibot->unk068);
playerChooseThirdPersonAnimation(chr, botGuessCrouchPos(chr), speedsideways, speedforwards, aibot->speedtheta, &aibot->angleoffset, &aibot->attackanimconfig);
angle2 = chrGetInverseTheta(chr) - aibot->angleoffset;
@ -807,11 +811,12 @@ bool botIsAboutToAttack(struct chrdata *chr, bool arg1)
}
if (chr->aibot->config->difficulty == BOTDIFF_NORMAL) {
if (chr->aibot->unk208 > 0 && chr->aibot->unk208 < 4) {
if (chr->aibot->numwaystepstotarget > 0 && chr->aibot->numwaystepstotarget < 4) {
result = true;
}
} else {
if (chr->aibot->unk208 > 0 && chr->aibot->unk208 < 5) {
// Higher than BOTDIFF_NORMAL
if (chr->aibot->numwaystepstotarget > 0 && chr->aibot->numwaystepstotarget < 5) {
result = true;
}
}
@ -821,7 +826,7 @@ bool botIsAboutToAttack(struct chrdata *chr, bool arg1)
if (!arg1
&& (chr->aibot->config->difficulty == BOTDIFF_MEAT || chr->aibot->config->difficulty == BOTDIFF_EASY)
&& !chrGoPosIsWaiting(chr)) {
f32 tmp = func0f03e578(chr);
f32 tmp = chrGetRotY(chr);
f32 angle = atan2f(target->pos.x - chr->prop->pos.x, target->pos.z - chr->prop->pos.z) - tmp;
if (angle < 0) {
@ -900,22 +905,22 @@ s32 botTick(struct prop *prop)
} else if (botIsAboutToAttack(chr, false)) {
struct prop *target = chrGetTargetProp(chr);
targetangle = chrGetAngleToPos(chr, &target->pos);
targetangle = oldangle + targetangle + aibot->unk1c0;
targetangle = oldangle + targetangle + aibot->extraangle;
} else if (chr->myaction == MA_AIBOTDOWNLOAD && g_ScenarioData.htm.dlterminalnum != -1) {
targetangle = chrGetAngleToPos(chr, &g_ScenarioData.htm.terminals[g_ScenarioData.htm.dlterminalnum].prop->pos);
targetangle = oldangle + targetangle;
} else if (chr->myaction == MA_AIBOTFOLLOW
&& aibot->followingplayernum >= 0
&& aibot->chrdistances[aibot->followingplayernum] < 300
&& aibot->unk1e4 >= g_Vars.lvframe60 - TICKS(60)
&& aibot->realignangleframe >= g_Vars.lvframe60 - TICKS(60)
&& aibot->config->difficulty != BOTDIFF_MEAT) {
targetangle = chrGetInverseTheta(g_MpAllChrPtrs[aibot->followingplayernum]);
} else if (chr->myaction == MA_AIBOTDEFEND
&& aibot->unk1e4 >= g_Vars.lvframe60 - TICKS(60)
&& aibot->realignangleframe >= g_Vars.lvframe60 - TICKS(60)
&& aibot->config->difficulty != BOTDIFF_MEAT) {
targetangle = aibot->unk098;
targetangle = aibot->defendholdrot;
} else {
targetangle = func0f03e578(chr);
targetangle = chrGetRotY(chr);
}
while (targetangle >= M_BADTAU) {
@ -994,25 +999,25 @@ s32 botTick(struct prop *prop)
bool left = chr->weapons_held[HAND_LEFT] ? true : false;
bool right = (0, chr->weapons_held[HAND_RIGHT] ? true : false);
func0f03e9f4(chr, aibot->unk068, left, right, 0);
func0f03e9f4(chr, aibot->attackanimconfig, left, right, 0);
} else {
chrResetAimEndProperties(chr);
}
if (chr->actiontype == ACT_DIE || chr->actiontype == ACT_DEAD) {
aibot->unk06c = 0;
aibot->unk070 = 0;
aibot->speedmultforwards = 0;
aibot->speedmultsideways = 0;
} else if (aibot->skrocket) {
aibot->unk06c = 0;
aibot->unk070 = 0;
aibot->unk1e4 = g_Vars.lvframe60;
aibot->speedmultforwards = 0;
aibot->speedmultsideways = 0;
aibot->realignangleframe = g_Vars.lvframe60;
} else if (chr->actiontype == ACT_GOPOS && (chr->act_gopos.flags & GOPOSFLAG_WAITING) == 0) {
aibot->unk06c = 1;
aibot->unk070 = 0;
aibot->speedmultforwards = 1;
aibot->speedmultsideways = 0;
} else {
aibot->unk06c = 0;
aibot->unk070 = 0;
aibot->unk1e4 = g_Vars.lvframe60;
aibot->speedmultforwards = 0;
aibot->speedmultsideways = 0;
aibot->realignangleframe = g_Vars.lvframe60;
}
}
@ -1099,8 +1104,8 @@ void bot0f1921f8(struct chrdata *chr, f32 *move)
f32 sine;
u32 stack[4];
f32 sp30[2];
f32 fVar7;
f32 fVar8;
f32 speedsideways;
f32 speedforwards;
f32 speed;
f32 tmp;
@ -1114,45 +1119,44 @@ void bot0f1921f8(struct chrdata *chr, f32 *move)
return;
}
fVar7 = chr->aibot->unk070;
fVar8 = chr->aibot->unk06c;
speedsideways = chr->aibot->speedmultsideways;
speedforwards = chr->aibot->speedmultforwards;
speed = botCalculateMaxSpeed(chr);
fVar7 *= speed;
fVar8 *= speed;
speedsideways *= speed;
speedforwards *= speed;
sp50 = func0f03e578(chr);
sp50 = chrGetRotY(chr);
cosine = cosf(sp50);
sine = sinf(sp50);
sp30[0] = fVar7 * cosine + fVar8 * sine;
sp30[1] = -fVar7 * sine + fVar8 * cosine;
sp30[0] = speedsideways * cosine + speedforwards * sine;
sp30[1] = -speedsideways * sine + speedforwards * cosine;
move[0] = 0;
move[1] = 0;
#if VERSION >= VERSION_NTSC_1_0
tmp = (PAL ? 0.065f : 0.055000007152557f) * arg3 / numupdates;
for (i = 0; i < numupdates; i++) {
chr->aibot->unk0b4 = (PAL ? 0.935f : 0.945f) * chr->aibot->unk0b4 + sp30[0];
chr->aibot->unk0b8 = (PAL ? 0.935f : 0.945f) * chr->aibot->unk0b8 + sp30[1];
chr->aibot->moveratex = (PAL ? 0.935f : 0.945f) * chr->aibot->moveratex + sp30[0];
chr->aibot->moveratey = (PAL ? 0.935f : 0.945f) * chr->aibot->moveratey + sp30[1];
move[0] += chr->aibot->unk0b4 * tmp;
move[1] += chr->aibot->unk0b8 * tmp;
move[0] += chr->aibot->moveratex * tmp;
move[1] += chr->aibot->moveratey * tmp;
}
#else
tmp = (PAL ? 0.065f : 0.055000007152557f) * g_Vars.lvupdate60freal / g_Vars.lvupdate240;
for (i = 0; i < g_Vars.lvupdate240; i++) {
chr->aibot->unk0b4 = (PAL ? 0.935f : 0.945f) * chr->aibot->unk0b4 + sp30[0];
chr->aibot->unk0b8 = (PAL ? 0.935f : 0.945f) * chr->aibot->unk0b8 + sp30[1];
chr->aibot->moveratex = (PAL ? 0.935f : 0.945f) * chr->aibot->moveratex + sp30[0];
chr->aibot->moveratey = (PAL ? 0.935f : 0.945f) * chr->aibot->moveratey + sp30[1];
move[0] += chr->aibot->unk0b4 * tmp;
move[1] += chr->aibot->unk0b8 * tmp;
move[0] += chr->aibot->moveratex * tmp;
move[1] += chr->aibot->moveratey * tmp;
}
#endif
}
@ -1204,25 +1208,25 @@ void botApplyProtect(struct chrdata *chr, struct prop *prop)
chr->aibot->forcemainloop = true;
}
void botApplyDefend(struct chrdata *chr, struct coord *pos, s16 *room, f32 arg3)
void botApplyDefend(struct chrdata *chr, struct coord *pos, s16 *room, f32 angle)
{
chr->aibot->command = AIBOTCMD_DEFEND;
chr->aibot->defendholdpos.x = pos->x;
chr->aibot->defendholdpos.y = pos->y;
chr->aibot->defendholdpos.z = pos->z;
roomsCopy(room, chr->aibot->defendholdrooms);
chr->aibot->unk098 = arg3;
chr->aibot->defendholdrot = angle;
chr->aibot->forcemainloop = true;
}
void botApplyHold(struct chrdata *chr, struct coord *pos, s16 *room, f32 arg3)
void botApplyHold(struct chrdata *chr, struct coord *pos, s16 *room, f32 angle)
{
chr->aibot->command = AIBOTCMD_HOLD;
chr->aibot->defendholdpos.x = pos->x;
chr->aibot->defendholdpos.y = pos->y;
chr->aibot->defendholdpos.z = pos->z;
roomsCopy(room, chr->aibot->defendholdrooms);
chr->aibot->unk098 = arg3;
chr->aibot->defendholdrot = angle;
chr->aibot->forcemainloop = true;
}
@ -1308,7 +1312,7 @@ void botSetTarget(struct chrdata *botchr, s32 propnum)
botchr->target = propnum;
botchr->aibot->shootdelaytimer60 = 0;
botchr->aibot->waypoints[0] = NULL;
botchr->aibot->unk208 = 0;
botchr->aibot->numwaystepstotarget = 0;
if (botchr->aibot->targetinsight && otherchr) {
botchr->aibot->targetcloaktimer60 = TICKS(120);
@ -1387,18 +1391,18 @@ void bot0f192a74(struct chrdata *chr)
f32 fVar11;
f32 tmp;
aibot->unk1cc -= g_Vars.lvupdate60;
aibot->random3ttl60 -= g_Vars.lvupdate60;
if (aibot->unk1cc <= 0) {
aibot->unk1d0 = random();
aibot->unk1cc = TICKS(20) + random() % TICKS(20);
if (aibot->random3ttl60 <= 0) {
aibot->random3 = random();
aibot->random3ttl60 = TICKS(20) + random() % TICKS(20);
}
if (g_Vars.lvupdate240 > 0) {
if (aibot->targetinsight) {
aibot->unk1d4 += g_Vars.diffframe60;
aibot->targetinsighttemperature += g_Vars.diffframe60;
} else {
aibot->unk1d4 -= g_Vars.diffframe60;
aibot->targetinsighttemperature -= g_Vars.diffframe60;
}
tmp = g_BotDifficulties[diff].unk10 * (aibot->speedtheta * g_Vars.lvupdate60f);
@ -1407,23 +1411,23 @@ void bot0f192a74(struct chrdata *chr)
tmp = -tmp;
}
aibot->unk1d4 -= tmp;
aibot->targetinsighttemperature -= tmp;
}
if (aibot->unk1d4 > aibot->shootdelaytimer60) {
aibot->unk1d4 = aibot->shootdelaytimer60;
if (aibot->targetinsighttemperature > aibot->shootdelaytimer60) {
aibot->targetinsighttemperature = aibot->shootdelaytimer60;
}
if (aibot->unk1d4 < 0) {
aibot->unk1d4 = 0;
if (aibot->targetinsighttemperature < 0) {
aibot->targetinsighttemperature = 0;
}
if (aibot->unk1d4 >= g_BotDifficulties[diff].unk0c) {
aibot->unk1d4 = g_BotDifficulties[diff].unk0c;
if (aibot->targetinsighttemperature >= g_BotDifficulties[diff].unk0c) {
aibot->targetinsighttemperature = g_BotDifficulties[diff].unk0c;
fVar12 = 0;
fVar11 = 0;
} else {
tmp = (g_BotDifficulties[diff].unk0c - aibot->unk1d4) / g_BotDifficulties[diff].unk0c;
tmp = (g_BotDifficulties[diff].unk0c - aibot->targetinsighttemperature) / g_BotDifficulties[diff].unk0c;
fVar12 = g_BotDifficulties[diff].unk04 * tmp;
fVar11 = g_BotDifficulties[diff].unk08 * tmp;
}
@ -1442,17 +1446,17 @@ void bot0f192a74(struct chrdata *chr)
fVar11 = g_BotDifficulties[diff].unk18;
}
aibot->unk1c8 = (fVar11 - fVar12) * (aibot->unk1d0 & 0xffff) * 0.000015259021893144f + fVar12;
aibot->extraanglebase = (fVar11 - fVar12) * (aibot->random3 & 0xffff) * 0.000015259021893144f + fVar12;
if (aibot->unk1d0 & 0x10000) {
aibot->unk1c8 = -aibot->unk1c8;
if (aibot->random3 & 0x10000) {
aibot->extraanglebase = -aibot->extraanglebase;
}
for (i = 0; i < g_Vars.lvupdate240; i++) {
aibot->unk1c4 = aibot->unk1c4 * (PAL ? 0.97f : 0.97500002384186f) + aibot->unk1c8;
aibot->extraanglerate = aibot->extraanglerate * (PAL ? 0.97f : 0.97500002384186f) + aibot->extraanglebase;
}
aibot->unk1c0 = aibot->unk1c4 * (PAL ? 0.029999971389771f : 0.024999976158142f);
aibot->extraangle = aibot->extraanglerate * (PAL ? 0.029999971389771f : 0.024999976158142f);
}
/**
@ -2763,7 +2767,7 @@ void botTickUnpaused(struct chrdata *chr)
aibot->gotopos.y = token->pos.y;
aibot->gotopos.z = token->pos.z;
roomsCopy(token->rooms, aibot->gotorooms);
aibot->unk04c_00 = false;
aibot->inhill = false;
}
}
} else if (aibot->command == AIBOTCMD_DEFHILL) {
@ -2791,7 +2795,7 @@ void botTickUnpaused(struct chrdata *chr)
aibot->gotopos.y = posinhill.y;
aibot->gotopos.z = posinhill.z;
roomsCopy(g_ScenarioData.koh.hillrooms, aibot->gotorooms);
aibot->unk04c_00 = (chr->prop->rooms[0] == g_ScenarioData.koh.hillrooms[0]) != 0;
aibot->inhill = (chr->prop->rooms[0] == g_ScenarioData.koh.hillrooms[0]) != 0;
aibot->hillpadnum = padnuminhill;
aibot->hillcovernum = covernuminhill;
aibot->lastknownhill = g_ScenarioData.koh.hillrooms[0];
@ -2813,7 +2817,7 @@ void botTickUnpaused(struct chrdata *chr)
aibot->gotopos.y = posinhill.y;
aibot->gotopos.z = posinhill.z;
roomsCopy(g_ScenarioData.koh.hillrooms, aibot->gotorooms);
aibot->unk04c_00 = (chr->prop->rooms[0] == g_ScenarioData.koh.hillrooms[0]) != 0;
aibot->inhill = (chr->prop->rooms[0] == g_ScenarioData.koh.hillrooms[0]) != 0;
aibot->hillpadnum = padnuminhill;
aibot->hillcovernum = covernuminhill;
aibot->lastknownhill = g_ScenarioData.koh.hillrooms[0];
@ -2958,7 +2962,7 @@ void botTickUnpaused(struct chrdata *chr)
aibot->gotopos.z = pad.pos.z;
aibot->gotorooms[0] = pad.room;
aibot->gotorooms[1] = -1;
aibot->unk04c_00 = false;
aibot->inhill = false;
}
} else if (g_MpSetup.scenario == MPSCENARIO_HACKERCENTRAL) {
// If the bot has the uplink, go to the terminal
@ -3253,10 +3257,10 @@ void botTickUnpaused(struct chrdata *chr)
chr->myaction = MA_AIBOTMAINLOOP;
}
} else if (chr->myaction == MA_AIBOTGOTOPOS) {
if (g_MpSetup.scenario == MPSCENARIO_KINGOFTHEHILL && aibot->unk04c_00) {
if (g_MpSetup.scenario == MPSCENARIO_KINGOFTHEHILL && aibot->inhill) {
if (aibot->lastknownhill != g_ScenarioData.koh.hillrooms[0]) {
// Someone scored the hill
aibot->unk04c_00 = false;
aibot->inhill = false;
} else if (chr->prop->rooms[0] == g_ScenarioData.koh.hillrooms[0]) {
// empty
} else if (aibot->hillpadnum >= 0) {
@ -3303,7 +3307,7 @@ void botTickUnpaused(struct chrdata *chr)
if (first && last) {
s32 hash = (g_Vars.lvframe60 >> 9) * 128 + chr->chrnum * 8;
waypointSetHashThing(hash, hash);
aibot->unk208 = waypointFindRoute(last, first, aibot->waypoints, ARRAYCOUNT(aibot->waypoints));
aibot->numwaystepstotarget = waypointFindRoute(last, first, aibot->waypoints, ARRAYCOUNT(aibot->waypoints));
waypointSetHashThing(0, 0);
}
}
@ -3475,7 +3479,7 @@ void botTickUnpaused(struct chrdata *chr)
chrUncloakTemporarily(chr);
botactTryRemoveAmmoFromReserve(aibot, aibot->weaponnum, aibot->gunfunc, 1);
botact0f19a37c(chr);
botactThrow(chr);
func = weaponGetFunctionById(aibot->weaponnum, aibot->gunfunc);

View File

@ -83,7 +83,7 @@ s32 botactGetAmmoQuantityByWeapon(struct aibot *aibot, s32 weaponnum, s32 funcnu
s32 equippedammotype;
if (aibot) {
if (aibot->unk064 & 1) {
if (aibot->flags & BOTFLAG_UNLIMITEDAMMO) {
ammotype = botactGetAmmoTypeByFunction(weaponnum, funcnum);
qty = bgunGetCapacityByAmmotype(ammotype);
} else {
@ -109,7 +109,7 @@ s32 botactGetAmmoQuantityByType(struct aibot *aibot, s32 ammotype, bool include_
s32 qty = 0;
if (aibot) {
if (aibot->unk064 & 1) {
if (aibot->flags & BOTFLAG_UNLIMITEDAMMO) {
qty = bgunGetCapacityByAmmotype(ammotype);
} else {
qty = aibot->ammoheld[ammotype];
@ -140,7 +140,7 @@ s32 botactTryRemoveAmmoFromReserve(struct aibot *aibot, s32 weaponnum, s32 funcn
return 0;
}
if (aibot->unk064 & 1) {
if (aibot->flags & BOTFLAG_UNLIMITEDAMMO) {
return tryqty;
}
@ -167,7 +167,7 @@ void botactGiveAmmoByWeapon(struct aibot *aibot, s32 weaponnum, s32 funcnum, s32
s32 max;
s32 *heldquantity = &aibot->ammoheld[botactGetAmmoTypeByFunction(weaponnum, funcnum)];
if (aibot && (aibot->unk064 & 1) == 0 && qty > 0) {
if (aibot && (aibot->flags & BOTFLAG_UNLIMITEDAMMO) == 0 && qty > 0) {
dprint();
*heldquantity += qty;
@ -188,7 +188,7 @@ void botactGiveAmmoByType(struct aibot *aibot, u32 ammotype, s32 quantity)
s32 max;
s32 *heldquantity = &aibot->ammoheld[ammotype];
if (!aibot || (aibot->unk064 & 1) || quantity <= 0) {
if (!aibot || (aibot->flags & BOTFLAG_UNLIMITEDAMMO) || quantity <= 0) {
return;
}
@ -336,7 +336,7 @@ s32 botactGetWeaponByAmmoType(s32 ammotype)
return 0;
}
void botact0f19a37c(struct chrdata *chr)
void botactThrow(struct chrdata *chr)
{
struct coord sp228 = {0, 0, 0};
Mtxf sp164;
@ -399,7 +399,7 @@ void botact0f19a37c(struct chrdata *chr)
bgunCreateThrownProjectile2(chr, &gset, &prop->pos, prop->rooms, &sp164, &sp228);
if (gset.weaponnum == WEAPON_REMOTEMINE) {
chr->aibot->unk064 |= 0x1000;
chr->aibot->flags |= BOTFLAG_THREWREMOTEMINE;
}
}

View File

@ -127,9 +127,11 @@ void botcmdTickDistMode(struct chrdata *chr)
}
#if VERSION >= VERSION_NTSC_1_0
if (newmode != BOTDISTMODE_BACKUP || !insight || aibot->unk050 != targetprop) {
aibot->unk050 = NULL;
aibot->unk09d = 0;
if (newmode == BOTDISTMODE_BACKUP && insight && aibot->distoverrideprop == targetprop) {
// don't unset
} else {
aibot->distoverrideprop = NULL;
aibot->distoverridetimer60 = 0;
}
if (newmode == BOTDISTMODE_OK) {
@ -137,17 +139,24 @@ void botcmdTickDistMode(struct chrdata *chr)
newmode = BOTDISTMODE_ADVANCE;
}
} else if (newmode == BOTDISTMODE_BACKUP) {
// If the bot is too close to the target, it'll try to back up. But if
// the target goes out of sight during the back up, the bot needs to
// advance again, regardless of the distance to the target.
// When the target returns to sight, force the distance mode to be okay
// for a random duration before returning to the normal distmode behaviour.
// This likely prevents them from going into a backup/advance loop as
// they go around a corner.
if (!insight) {
newmode = BOTDISTMODE_ADVANCE;
aibot->unk050 = targetprop;
aibot->unk09d = TICKS(20) + (random() % TICKS(120));
} else if (aibot->unk050) {
if (aibot->unk09d > g_Vars.lvupdate60) {
aibot->unk09d -= g_Vars.lvupdate60;
aibot->distoverrideprop = targetprop;
aibot->distoverridetimer60 = TICKS(20) + (random() % TICKS(120));
} else if (aibot->distoverrideprop) {
if (g_Vars.lvupdate60 < aibot->distoverridetimer60) {
aibot->distoverridetimer60 -= g_Vars.lvupdate60;
newmode = BOTDISTMODE_OK;
} else {
aibot->unk050 = NULL;
aibot->unk09d = 0;
aibot->distoverrideprop = NULL;
aibot->distoverridetimer60 = 0;
}
}
}

View File

@ -797,7 +797,7 @@ void botinvScoreWeapon(struct chrdata *chr, s32 weaponnum, s32 funcnum, s32 arg3
extra = 30;
}
extra += chr->aibot->unk2a8[weaponindex];
extra += chr->aibot->equipextrascores[weaponindex];
score1 += extra;
score2 += extra;
@ -901,19 +901,19 @@ void botinvTick(struct chrdata *chr)
}
}
// Every 10-60 seconds, generate new unk2a8 values
aibot->unk2a4 -= g_Vars.lvupdate60;
// Every 10-60 seconds, generate new equipextrascores
aibot->equipextrascorestimer60 -= g_Vars.lvupdate60;
if (aibot->unk2a4 < 0) {
aibot->unk2a4 = TICKS(600) + random() % TICKS(3000);
if (aibot->equipextrascorestimer60 < 0) {
aibot->equipextrascorestimer60 = TICKS(600) + random() % TICKS(3000);
for (i = 0; i < ARRAYCOUNT(aibot->unk2a8); i++) {
for (i = 0; i < ARRAYCOUNT(aibot->equipextrascores); i++) {
if (aibot->config->difficulty == BOTDIFF_MEAT) {
aibot->unk2a8[i] = random() % 200 - 100; // -100 to +100
aibot->equipextrascores[i] = random() % 200 - 100; // -100 to +100
} else if (aibot->config->difficulty == BOTDIFF_EASY) {
aibot->unk2a8[i] = random() % 100 - 50; // -50 to +50
aibot->equipextrascores[i] = random() % 100 - 50; // -50 to +50
} else {
aibot->unk2a8[i] = random() % 30 - 15; // -15 to +15
aibot->equipextrascores[i] = random() % 30 - 15; // -15 to +15
}
}
}

View File

@ -134,7 +134,7 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
}
aibot->aibotnum = aibotnum;
aibot->unk064 = 0;
aibot->flags = 0;
aibot->gotoprop = NULL;
aibot->timeuntilreload60[0] = 0;
aibot->timeuntilreload60[1] = 0;
@ -142,8 +142,8 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
aibot->unk040 = 0.0f;
aibot->loadedammo[0] = 0;
aibot->loadedammo[1] = 0;
aibot->unk058 = 0;
aibot->unk059 = 0;
aibot->fadeintimer60 = 0;
aibot->respawning = false;
aibot->nextbullettimer60[0] = 0;
aibot->nextbullettimer60[1] = 0;
#if VERSION < VERSION_PAL_BETA
@ -155,15 +155,15 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
aibot->attackingplayernum = -1;
aibot->followingplayernum = -1;
aibot->dangerouspropnum = -1;
aibot->unk068 = 0;
aibot->unk06c = 0.0f;
aibot->unk070 = 0.0f;
aibot->attackanimconfig = NULL;
aibot->speedmultforwards = 0.0f;
aibot->speedmultsideways = 0.0f;
aibot->distmode = -1;
aibot->lastkilledbyplayernum = -1;
aibot->feudplayernum = -1;
aibot->command = AIBOTCMD_NORMAL;
aibot->unk098 = 0.0f;
aibot->defendholdrot = 0.0f;
aibot->defendholdpos.x = pos.x;
aibot->defendholdpos.y = pos.y;
aibot->defendholdpos.z = pos.z;
@ -173,7 +173,7 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
aibot->burstsdone[0] = 0;
aibot->burstsdone[1] = 0;
aibot->skrocket = NULL;
aibot->unk0a0 = 0;
aibot->htbheldtimer60 = 0;
aibot->gunfunc = FUNC_PRIMARY;
aibot->ismeleeweapon = true;
@ -185,7 +185,7 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
aibot->unk04c_04 = false;
aibot->unk04c_03 = false;
aibot->hasuplink = false;
aibot->unk04c_00 = false;
aibot->inhill = false;
aibot->hillpadnum = -1;
aibot->hillcovernum = -1;
@ -201,13 +201,13 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
aibot->reaperspeed[HAND_RIGHT] = 0;
aibot->maulercharge[HAND_LEFT] = 0.0f;
aibot->maulercharge[HAND_RIGHT] = 0.0f;
aibot->unk0a4 = modelGetChrRotY(chr->model);
aibot->roty = modelGetChrRotY(chr->model);
aibot->angleoffset = 0.0f;
aibot->speedtheta = 0.0f;
aibot->unk0b0 = modelGetChrRotY(chr->model);
aibot->lookangle = modelGetChrRotY(chr->model);
aibot->unk0b4 = 0.0f;
aibot->unk0b8 = 0.0f;
aibot->moveratex = 0.0f;
aibot->moveratey = 0.0f;
aibot->shotspeed.x = 0.0f;
aibot->shotspeed.y = 0.0f;
aibot->shotspeed.z = 0.0f;
@ -226,15 +226,15 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
aibot->chrrooms[i] = -1;
}
aibot->unk1c0 = 0.0f;
aibot->unk1c4 = 0.0f;
aibot->unk1c8 = 0.0f;
aibot->unk1cc = -1;
aibot->unk1d0 = 0;
aibot->unk1d4 = 0.0f;
aibot->unk1e4 = -1;
aibot->extraangle = 0.0f;
aibot->extraanglerate = 0.0f;
aibot->extraanglebase = 0.0f;
aibot->random3ttl60 = -1;
aibot->random3 = 0;
aibot->targetinsighttemperature = 0.0f;
aibot->realignangleframe = -1;
aibot->waypoints[0] = NULL;
aibot->unk208 = 0;
aibot->numwaystepstotarget = 0;
aibot->random1 = random();
aibot->random1ttl60 = 0;
@ -248,12 +248,12 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
aibot->equipdurations60[i][0] = 0;
aibot->equipdurations60[i][1] = 0;
aibot->unk2a8[i] = 0;
aibot->equipextrascores[i] = 0;
}
aibot->unk2a4 = 0;
aibot->equipextrascorestimer60 = 0;
aibot->dampensuicidesttl60 = 0;
aibot->unk2c4 = 0.0f;
aibot->rcpcloaktimer60 = 0.0f;
aibot->targetcloaktimer60 = 0;
aibot->canseecloaked = false;
@ -262,9 +262,9 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
aibot->randomfrac = RANDOMFRAC();
aibot->cheap = false;
#if VERSION >= VERSION_NTSC_1_0
aibot->unk078 = 0;
aibot->unk050 = 0;
aibot->unk09d = 0;
aibot->forceslowupdates = 0;
aibot->distoverrideprop = NULL;
aibot->distoverridetimer60 = 0;
#endif
} else {
g_MpBotChrPtrs[--g_BotCount] = NULL;

View File

@ -576,11 +576,15 @@ bool chr0f01f378(struct model *model, struct coord *arg1, struct coord *arg2, f3
if (VAR(lvupdate240) > 0) {
#if VERSION >= VERSION_NTSC_1_0
if (chr->aibot->unk078 != 0) {
if (chr->aibot->forceslowupdates != 0) {
// forceslowupdates is set when the bot is being saved from
// falling out of bounds due to high lag. It forces them to
// update in smaller increments, which gives a higher chance
// of their collision detecting working correctly.
if (chr->prop->flags & PROPFLAG_ONANYSCREENPREVTICK) {
chr->aibot->unk078 = 0;
chr->aibot->forceslowupdates = 0;
} else {
chr->aibot->unk078--;
chr->aibot->forceslowupdates--;
if (lvupdate240 >= 25) {
lvupdate60f = 4.0f;
@ -824,11 +828,15 @@ bool chr0f01f378(struct model *model, struct coord *arg1, struct coord *arg2, f3
#if VERSION >= VERSION_NTSC_1_0
if (chr->aibot
&& chr->aibot->unk078 == 0
&& chr->aibot->forceslowupdates == 0
&& ground < -100000
&& g_Vars.lvupdate60 >= 5
&& (chr->prop->flags & PROPFLAG_ONANYSCREENPREVTICK) == 0) {
chr->aibot->unk078 = 10;
// The new position has no ground and is offscreen,
// So they're about to fall out of the geometry.
// Run the previous calculations but using their current
// position instead. This holds them in place.
chr->aibot->forceslowupdates = 10;
arg2->x = prop->pos.x;
arg2->y = prop->pos.y;
@ -838,7 +846,8 @@ bool chr0f01f378(struct model *model, struct coord *arg1, struct coord *arg2, f3
lvupdate60freal = 0.0f;
ground = cdFindGroundInfoAtCyl(arg2, chr->radius, spfc, &chr->floorcol, &chr->floortype, &floorflags, &chr->floorroom, &inlift, &lift);
ground = cdFindGroundInfoAtCyl(arg2, chr->radius, spfc,
&chr->floorcol, &chr->floortype, &floorflags, &chr->floorroom, &inlift, &lift);
}
#endif
@ -2094,11 +2103,11 @@ void chrUpdateCloak(struct chrdata *chr)
&& !chrIsDead(chr)
&& botactGetAmmoQuantityByWeapon(chr->aibot, WEAPON_RCP120, 0, 1) > 0) {
if (chr->hidden & CHRHFLAG_CLOAKED) {
chr->aibot->unk2c4 += LVUPDATE60FREAL() * 0.4f;
chr->aibot->rcpcloaktimer60 += LVUPDATE60FREAL() * 0.4f;
if (chr->aibot->unk2c4 >= 1) {
qty = chr->aibot->unk2c4;
chr->aibot->unk2c4 -= qty;
if (chr->aibot->rcpcloaktimer60 >= 1) {
qty = chr->aibot->rcpcloaktimer60;
chr->aibot->rcpcloaktimer60 -= qty;
if (chr->aibot->loadedammo[0] > 0) {
chr->aibot->loadedammo[0] -= qty;
@ -2322,11 +2331,11 @@ bool chrTickBeams(struct prop *prop)
beamTick(&g_Fireslots[chr->fireslots[1]].beam);
}
if (chr->aibot && chr->aibot->unk058 > 0) {
if (chr->aibot->unk058 > g_Vars.lvupdate60) {
chr->aibot->unk058 -= g_Vars.lvupdate60;
if (chr->aibot && chr->aibot->fadeintimer60 > 0) {
if (chr->aibot->fadeintimer60 > g_Vars.lvupdate60) {
chr->aibot->fadeintimer60 -= g_Vars.lvupdate60;
} else {
chr->aibot->unk058 = 0;
chr->aibot->fadeintimer60 = 0;
}
}
@ -3360,8 +3369,8 @@ Gfx *chrRender(struct prop *prop, Gfx *gdl, bool xlupass)
alpha = chr->fadealpha;
}
if (chr->aibot && chr->aibot->unk058 > 0) {
alpha = (f32)alpha * (TICKS(120) - chr->aibot->unk058) * (PAL ? 0.01f : 0.0083333337679505f);
if (chr->aibot && chr->aibot->fadeintimer60 > 0) {
alpha = (f32)alpha * (TICKS(120) - chr->aibot->fadeintimer60) * (1.0f / TICKS(120));
}
chrGetBloodColour(chr->bodynum, spec, NULL);

View File

@ -8832,7 +8832,7 @@ void chrUpdateFireslot(struct chrdata *chr, s32 handnum, bool withsound, bool wi
f32 chrGetInverseTheta(struct chrdata *chr)
{
if (chr->aibot) {
return chr->aibot->unk0b0;
return chr->aibot->lookangle;
}
if (chr->model == NULL && chr->prop && chr->prop->type == PROPTYPE_PLAYER) {
@ -8854,27 +8854,27 @@ f32 chrGetInverseTheta(struct chrdata *chr)
void chrSetLookAngle(struct chrdata *chr, f32 angle)
{
if (chr->aibot) {
chr->aibot->unk0b0 = angle;
chr->aibot->lookangle = angle;
} else {
modelSetChrRotY(chr->model, angle);
}
}
f32 func0f03e578(struct chrdata *chr)
f32 chrGetRotY(struct chrdata *chr)
{
if (chr->aibot) {
return chr->aibot->unk0a4;
return chr->aibot->roty;
} else {
return modelGetChrRotY(chr->model);
}
return modelGetChrRotY(chr->model);
}
void func0f03e5b0(struct chrdata *chr, f32 arg1)
void chrSetRotY(struct chrdata *chr, f32 roty)
{
if (chr->aibot) {
chr->aibot->unk0a4 = arg1;
chr->aibot->roty = roty;
} else {
modelSetChrRotY(chr->model, arg1);
modelSetChrRotY(chr->model, roty);
}
}
@ -8890,7 +8890,7 @@ f32 chrGetAimAngle(struct chrdata *chr)
}
if (chr->aibot) {
if (chr->aibot->unk068) {
if (chr->aibot->attackanimconfig) {
// empty
}
} else if (chr->actiontype == ACT_ATTACK
@ -11364,7 +11364,7 @@ bool chrDetectDangerousObject(struct chrdata *chr, u8 flags)
chr->runfrompos.z = g_DangerousProps[i]->pos.z;
if (chr->aibot) {
chr->aibot->unk064 |= 0x0004;
chr->aibot->flags |= BOTFLAG_AVOIDINGDANGEROUSPROP;
chr->aibot->dangerouspropnum = i;
}
@ -11374,7 +11374,7 @@ bool chrDetectDangerousObject(struct chrdata *chr, u8 flags)
}
if (chr->aibot) {
chr->aibot->unk064 &= ~0x0004;
chr->aibot->flags &= ~BOTFLAG_AVOIDINGDANGEROUSPROP;
chr->aibot->dangerouspropnum = -1;
}
@ -11402,7 +11402,7 @@ bool func0f043f2c(struct chrdata *chr, struct coord *runpos, u32 arg2, f32 *turn
result = false;
angle1 = atan2f(xdiff, zdiff);
finalangle = func0f03e578(chr);
finalangle = chrGetRotY(chr);
angle2 = angle1 - finalangle;
if (finalangle > angle1) {
@ -11466,7 +11466,7 @@ bool func0f043f2c(struct chrdata *chr, struct coord *runpos, u32 arg2, f32 *turn
}
}
func0f03e5b0(chr, finalangle);
chrSetRotY(chr, finalangle);
return result;
}

View File

@ -385,7 +385,7 @@ bool (*g_CommandPointers[])(void) = {
/*0x0173*/ aiChrCopyProperties,
/*0x0174*/ aiIfCutsceneButtonPressed,
/*0x0175*/ ai0175,
/*0x0176*/ ai0176,
/*0x0176*/ aiIfBotRespawning,
/*0x0177*/ aiPlayerAutoWalk,
/*0x0178*/ aiIfPlayerAutoWalkFinished,
/*0x0179*/ ai0179,

View File

@ -6076,7 +6076,7 @@ u8 func0028_aibot_dead[] = {
dprint 'l','i','s','t',':',' ','a','i','d','e','a','d',0,
beginloop(0x0d)
cmd0176_if_something(/*goto*/ 0x16)
if_bot_respawning(/*goto*/ 0x16)
endloop(0x0d)
label(0x16)

View File

@ -19,7 +19,7 @@ bool aiMpInitSimulants(void)
/**
* @cmd 0176
*/
bool ai0176(void)
bool aiIfBotRespawning(void)
{
u8 *cmd = g_Vars.ailist + g_Vars.aioffset;
struct aibot *aibot;
@ -35,9 +35,9 @@ bool ai0176(void)
aibot = g_Vars.chrdata->aibot;
if (aibot->unk059 == 1) {
if (aibot->respawning == true) {
g_Vars.aioffset = chraiGoToLabel(g_Vars.ailist, g_Vars.aioffset, cmd[2]);
aibot->unk059 = 0;
aibot->respawning = false;
} else {
g_Vars.aioffset += 3;
}

View File

@ -352,15 +352,15 @@ void htbTickChr(struct chrdata *chr)
{
if (chr) {
if (chr->aibot->hasbriefcase) {
chr->aibot->unk0a0 += g_Vars.lvupdate240;
chr->aibot->htbheldtimer60 += g_Vars.lvupdate240;
if (chr->aibot->unk0a0 >= TICKS(7200)) {
if (chr->aibot->htbheldtimer60 >= TICKS(7200)) {
sndStart(var80095200, SFX_MP_SCOREPOINT, NULL, -1, -1, -1, -1, -1);
g_MpAllChrConfigPtrs[mpPlayerGetIndex(chr)]->numpoints++;
chr->aibot->unk0a0 = 0;
chr->aibot->htbheldtimer60 = 0;
}
} else {
chr->aibot->unk0a0 = 0;
chr->aibot->htbheldtimer60 = 0;
}
} else {
if (invHasBriefcase()) {

View File

@ -3408,7 +3408,7 @@
/**
*
*/
#define cmd0176_if_something(label) \
#define if_bot_respawning(label) \
mkshort(0x0176), \
label,

View File

@ -384,6 +384,10 @@
#define BOTDISTMODE_ADVANCE 3
#define BOTDISTMODE_GOTO 4
#define BOTFLAG_UNLIMITEDAMMO 0x0001
#define BOTFLAG_AVOIDINGDANGEROUSPROP 0x0004
#define BOTFLAG_THREWREMOTEMINE 0x1000
#define BOTTYPE_GENERAL 0
#define BOTTYPE_PEACE 1 // Collects weapons but doesn't engage in combat
#define BOTTYPE_SHIELD 2 // Prioritises full shield before combat

View File

@ -45,8 +45,8 @@ char *botGetCommandName(s32 command);
void botApplyAttack(struct chrdata *chr, struct prop *prop);
void botApplyFollow(struct chrdata *chr, struct prop *prop);
void botApplyProtect(struct chrdata *chr, struct prop *prop);
void botApplyDefend(struct chrdata *chr, struct coord *pos, s16 *room, f32 arg3);
void botApplyHold(struct chrdata *chr, struct coord *pos, s16 *room, f32 arg3);
void botApplyDefend(struct chrdata *chr, struct coord *pos, s16 *room, f32 angle);
void botApplyHold(struct chrdata *chr, struct coord *pos, s16 *room, f32 angle);
void botApplyScenarioCommand(struct chrdata *chr, u32 arg1);
bool botCanFollow(struct chrdata *leader, struct chrdata *follower);
s32 botFindTeammateToFollow(struct chrdata *chr, f32 range);

View File

@ -16,7 +16,7 @@ bool botactShootFarsight(struct chrdata *chr, s32 arg1, struct coord *arg2, stru
bool botactIsWeaponThrowable(s32 weaponnum, bool is_secondary);
u32 botactGetProjectileThrowInterval(u32 weapon);
s32 botactGetWeaponByAmmoType(s32 ammotype);
void botact0f19a37c(struct chrdata *chr);
void botactThrow(struct chrdata *chr);
s32 botactGetShootInterval60(s32 weaponnum, s32 funcnum);
bool botactFindRocketRoute(struct chrdata *chr, struct coord *frompos, struct coord *topos, s16 *fromrooms, s16 *torooms, struct projectile *projectile);
void botactGetRocketNextStepPos(u16 padnum, struct coord *pos);

View File

@ -272,8 +272,8 @@ void chrFadeCorpse(struct chrdata *chr);
void chrFadeCorpseWhenOffScreen(struct chrdata *chr);
void chrTickTest(struct chrdata *chr);
void chrSetLookAngle(struct chrdata *chr, f32 angle);
f32 func0f03e578(struct chrdata *chr);
void func0f03e5b0(struct chrdata *chr, f32 arg1);
f32 chrGetRotY(struct chrdata *chr);
void chrSetRotY(struct chrdata *chr, f32 arg1);
void chrResetAimEndProperties(struct chrdata *chr);
void chrSetFiring(struct chrdata *chr, s32 hand, bool firing);
void chrStopFiring(struct chrdata *chr);

View File

@ -352,7 +352,7 @@
/*0x0173*/ bool aiChrCopyProperties(void);
/*0x0174*/ bool aiIfCutsceneButtonPressed(void);
/*0x0175*/ bool ai0175(void);
/*0x0176*/ bool ai0176(void);
/*0x0176*/ bool aiIfBotRespawning(void);
/*0x0177*/ bool aiPlayerAutoWalk(void);
/*0x0178*/ bool aiIfPlayerAutoWalkFinished(void);
/*0x0179*/ bool ai0179(void);

View File

@ -708,67 +708,57 @@ struct aibot {
/*0x020*/ s32 weaponnum;
/*0x024*/ s32 loadedammo[2]; // amount of ammo in current clip
/*0x02c*/ s16 timeuntilreload60[2];
/*0x030*/ u32 unk030; // timer of some sort
/*0x030*/ u32 unk030; // unused
/*0x034*/ s32 throwtimer60;
/*0x038*/ u32 unk038;
/*0x038*/ u32 unk038; // unused
/*0x03c*/ s16 punchtimer60[2];
/*0x040*/ f32 unk040;
/*0x040*/ f32 unk040; // unused
/*0x044*/ struct prop *skrocket;
/*0x048*/ s16 hillpadnum;
/*0x04a*/ s16 hillcovernum;
/*0x04c*/ u8 unk04c_00 : 1;
/*0x04c*/ u8 inhill : 1;
/*0x04c*/ u8 ismeleeweapon : 1;
/*0x04c*/ u8 gunfunc : 1;
/*0x04c*/ u8 unk04c_03 : 1;
/*0x04c*/ u8 unk04c_04 : 1;
/*0x04c*/ u8 unk04c_03 : 1; // unused
/*0x04c*/ u8 unk04c_04 : 1; // unused
/*0x04c*/ u8 hasuplink : 1;
/*0x04c*/ u8 cloakdeviceenabled : 1;
/*0x04d*/ u8 burstsdone[2];
/*0x04f*/ u8 teamisonlyai : 1;
/*0x050*/ struct prop *unk050;
/*0x054*/ u32 unk054;
/*0x058*/ u8 unk058; // related to fireslots
/*0x059*/ u8 unk059;
/*0x050*/ struct prop *distoverrideprop;
/*0x054*/ u32 unk054; // unused
/*0x058*/ u8 fadeintimer60;
/*0x059*/ u8 respawning;
/*0x05c*/ s32 nextbullettimer60[2];
/**
* 0x0001 = has unlimited ammo (darksim?)
* 0x0004 = detected dangerous prop
* 0x1000 = using remote mines
*/
/*0x064*/ u16 unk064;
/*0x068*/ struct attackanimconfig *unk068;
/*0x06c*/ f32 unk06c;
/*0x070*/ f32 unk070;
/*0x064*/ u16 flags;
/*0x068*/ struct attackanimconfig *attackanimconfig;
/*0x06c*/ f32 speedmultforwards;
/*0x070*/ f32 speedmultsideways;
/*0x074*/ s8 distmode;
/*0x075*/ s8 unk075;
/*0x076*/ s16 lastkilledbyplayernum;
/*0x078*/ u8 unk078;
/*0x078*/ u8 forceslowupdates;
/*0x079*/ u8 command;
/*0x07a*/ s16 defendholdrooms[1];
/*0x07c*/ u32 unk07c;
/*0x080*/ u32 unk080;
/*0x084*/ u32 unk084;
/*0x088*/ u32 unk088;
/*0x07c*/ u32 unk07c; // unused
/*0x080*/ u32 unk080; // unused
/*0x084*/ u32 unk084; // unused
/*0x088*/ u32 unk088; // unused
/*0x08c*/ struct coord defendholdpos;
/*0x098*/ f32 unk098;
/*0x098*/ f32 defendholdrot;
/*0x09c*/ u8 hasbriefcase : 1; // htb
/*0x09c*/ u8 hascase : 1; // ctc
/*0x09c*/ u8 rcp120cloakenabled : 1;
/*0x09c*/ u8 canseecloaked : 1;
/*0x09c*/ u8 unk09c_04 : 1;
/*0x09c*/ u8 unk09c_05 : 1;
/*0x09c*/ u8 unk09c_06 : 1;
/*0x09c*/ u8 unk09c_04 : 3; // unused
/*0x09c*/ u8 cheap : 1; // True if aibot is not in any visible room
/*0x09d*/ u8 unk09d;
/*0x0a0*/ s32 unk0a0;
/*0x0a4*/ f32 unk0a4;
/*0x09d*/ u8 distoverridetimer60;
/*0x0a0*/ s32 htbheldtimer60;
/*0x0a4*/ f32 roty;
/*0x0a8*/ f32 angleoffset;
/*0x0ac*/ f32 speedtheta;
/*0x0b0*/ f32 unk0b0; // likely to be the turn angle to 360 degrees, in radians
/*0x0b4*/ f32 unk0b4;
/*0x0b8*/ f32 unk0b8;
/*0x0b0*/ f32 lookangle; // likely to be the turn angle to 360 degrees, in radians
/*0x0b4*/ f32 moveratex;
/*0x0b8*/ f32 moveratey;
/*0x0bc*/ s32 lastknownhill;
/*0x0c0*/ s32 attackpropnum;
/*0x0c4*/ bool cyclonedischarging[2];
@ -794,32 +784,27 @@ struct aibot {
/*0x16c*/ u8 chrsinsight[MAX_MPCHRS];
/*0x178*/ s32 chrslastseen60[MAX_MPCHRS];
/*0x1a8*/ s16 chrrooms[MAX_MPCHRS];
/*0x1c0*/ f32 unk1c0;
/*0x1c4*/ f32 unk1c4;
/*0x1c8*/ f32 unk1c8;
/*0x1cc*/ s32 unk1cc;
/*0x1d0*/ u32 unk1d0;
/*0x1d4*/ f32 unk1d4;
/*0x1c0*/ f32 extraangle;
/*0x1c4*/ f32 extraanglerate;
/*0x1c8*/ f32 extraanglebase;
/*0x1cc*/ s32 random3ttl60;
/*0x1d0*/ u32 random3;
/*0x1d4*/ f32 targetinsighttemperature;
/*0x1d8*/ s32 abortattacktimer60;
/*0x1dc*/ bool canbreakdefend;
/*0x1e0*/ bool canbreakfollow;
/*0x1e4*/ s32 unk1e4;
/*0x1e4*/ s32 realignangleframe;
/*0x1e8*/ struct waypoint *waypoints[8];
/*0x208*/ s32 unk208;
/*0x208*/ s32 numwaystepstotarget;
/*0x20c*/ s32 random1ttl60;
/*0x210*/ u32 random1;
/*0x214*/ f32 killsbygunfunc[NUM_MPWEAPONSLOTS][2];
/*0x244*/ f32 suicidesbygunfunc[NUM_MPWEAPONSLOTS][2];
/*0x274*/ s32 equipdurations60[NUM_MPWEAPONSLOTS][2];
/*0x2a4*/ s32 unk2a4;
/*0x2a8*/ s32 unk2a8[NUM_MPWEAPONSLOTS];
/*0x2a4*/ s32 equipextrascorestimer60;
/*0x2a8*/ s32 equipextrascores[NUM_MPWEAPONSLOTS];
/*0x2c0*/ s32 dampensuicidesttl60;
/**
* Some kind of cloak counter? Ticks up while cloaked. Over 1 causes RCP120
* ammo to be removed, and when this happens this value is decreased.
*/
/*0x2c4*/ f32 unk2c4;
/*0x2c4*/ f32 rcpcloaktimer60;
/**
* 120 when target is in sight
@ -833,8 +818,8 @@ struct aibot {
/*0x2cc*/ s32 random2ttl60;
/*0x2d0*/ u32 random2;
/*0x2d4*/ f32 randomfrac;
/*0x2d8*/ u32 unk2d8;
/*0x2dc*/ u32 unk2dc;
/*0x2d8*/ u32 unk2d8; // unused
/*0x2dc*/ u32 unk2dc; // unused
};
struct geo {