Document botdifficulty struct
This commit is contained in:
parent
4ee193e9e2
commit
31bc17b39d
138
src/game/bot.c
138
src/game/bot.c
|
|
@ -42,16 +42,51 @@ struct chrdata *g_MpBotChrPtrs[MAX_BOTS];
|
|||
|
||||
u8 g_BotCount = 0;
|
||||
|
||||
struct botdifficulty {
|
||||
u8 shootdelay60;
|
||||
f32 minzerospeed;
|
||||
f32 maxzerospeed;
|
||||
u16 zerotime60;
|
||||
f32 turnunzeromult;
|
||||
f32 zerocloakspeed;
|
||||
f32 forcezerominspeed;
|
||||
s32 dizzyamount;
|
||||
};
|
||||
|
||||
/**
|
||||
* shootdelay60:
|
||||
* How long the bot waits between seeing their target and shooting.
|
||||
* It has a cooldown, so a brief break in sight will have little effect.
|
||||
*
|
||||
* minzerospeed and maxzerospeed:
|
||||
* Controls the speed at which the bot zeroes their target.
|
||||
* These values are scaled linearly based on the bot's current zerotimer60.
|
||||
* A random speed between the scaled min and max is chosen.
|
||||
*
|
||||
* zerotime60:
|
||||
* How long it takes for the bot to zero their target. A cooldown is used.
|
||||
*
|
||||
* turnunzeromult:
|
||||
* When a bot is zeroing or has zeroed its target and has to turn naturally,
|
||||
* this controls the rate at which the target is "unzeroed".
|
||||
* The value is a multiplier for the zerotime60 cooldown.
|
||||
*
|
||||
* zerocloakspeed:
|
||||
* A minimum value for maxzerospeed which is used when the target is cloaked.
|
||||
* It allows the bot to zero faster when they're just starting to zero.
|
||||
*
|
||||
* forcezerominspeed:
|
||||
* A minimum value for maxzerospeed.
|
||||
* It allows the bot to zero faster when they're just starting to zero.
|
||||
*
|
||||
* dizzyamount:
|
||||
* How much tranq the bot needs to receive before they start being affected.
|
||||
* (ie. punching/shooting as soon as target is in sight, even if not zeroed)
|
||||
*/
|
||||
|
||||
struct botdifficulty g_BotDifficulties[] = {
|
||||
// shootdelay
|
||||
// | unk04
|
||||
// | | unk08
|
||||
// | | | unk0c
|
||||
// | | | | unk10
|
||||
// | | | | | unk14
|
||||
// | | | | | | unk18
|
||||
// | | | | | | | dizzyamount
|
||||
// | | | | | | | |
|
||||
// shootdelay60 turnunzeromult
|
||||
// | minzerospeed maxzerospeed zerotime60 | zerocloakspeed forcezerominspeed dizzyamount
|
||||
/* meat */ { TICKS(90), RAD(15, 0.26175770163536), RAD(30, 0.52351540327072), TICKS(600), 10, RAD(40, 0.69802051782608), RAD(20, 0.34901025891304), TICKS(1000) },
|
||||
/* easy */ { TICKS(60), RAD(7, 0.12215359508991), RAD(14, 0.24430719017982), TICKS(360), 10, RAD(28.5f, 0.49733963608742), RAD(8, 0.13960410654545), TICKS(1000) },
|
||||
/* norm */ { TICKS(30), RAD(4, 0.069802053272724), RAD(8, 0.13960410654545), TICKS(180), 4, RAD(20, 0.34901025891304), RAD(5, 0.08725256472826), TICKS(1500) },
|
||||
|
|
@ -905,7 +940,7 @@ s32 botTick(struct prop *prop)
|
|||
} else if (botIsAboutToAttack(chr, false)) {
|
||||
struct prop *target = chrGetTargetProp(chr);
|
||||
targetangle = chrGetAngleToPos(chr, &target->pos);
|
||||
targetangle = oldangle + targetangle + aibot->extraangle;
|
||||
targetangle = oldangle + targetangle + aibot->zeroangle;
|
||||
} 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;
|
||||
|
|
@ -1382,15 +1417,21 @@ bool botHasGround(struct chrdata *chr)
|
|||
return chr->ground >= -20000;
|
||||
}
|
||||
|
||||
void bot0f192a74(struct chrdata *chr)
|
||||
/**
|
||||
* The zero angle is the additional angle that's needed for the bot to zero in
|
||||
* on its target from its natural facing angle.
|
||||
*/
|
||||
void botUpdateZeroAngle(struct chrdata *chr)
|
||||
{
|
||||
struct aibot *aibot = chr->aibot;
|
||||
s32 diff = aibot->config->difficulty;
|
||||
s32 i;
|
||||
f32 fVar12;
|
||||
f32 fVar11;
|
||||
f32 minspeed;
|
||||
f32 maxspeed;
|
||||
f32 tmp;
|
||||
f32 frac;
|
||||
|
||||
// Consider recalculating random values
|
||||
aibot->random3ttl60 -= g_Vars.lvupdate60;
|
||||
|
||||
if (aibot->random3ttl60 <= 0) {
|
||||
|
|
@ -1398,65 +1439,76 @@ void bot0f192a74(struct chrdata *chr)
|
|||
aibot->random3ttl60 = TICKS(20) + random() % TICKS(20);
|
||||
}
|
||||
|
||||
// Increase or decrease curzerotimer60 depending on whether the target is in sight or not
|
||||
if (g_Vars.lvupdate240 > 0) {
|
||||
if (aibot->targetinsight) {
|
||||
aibot->targetinsighttemperature += g_Vars.diffframe60;
|
||||
aibot->curzerotimer60 += g_Vars.diffframe60;
|
||||
} else {
|
||||
aibot->targetinsighttemperature -= g_Vars.diffframe60;
|
||||
aibot->curzerotimer60 -= g_Vars.diffframe60;
|
||||
}
|
||||
|
||||
tmp = g_BotDifficulties[diff].unk10 * (aibot->speedtheta * g_Vars.lvupdate60f);
|
||||
// If the bot is naturally turning, decrease the zero timer
|
||||
tmp = g_BotDifficulties[diff].turnunzeromult * (aibot->speedtheta * g_Vars.lvupdate60f);
|
||||
|
||||
if (tmp < 0) {
|
||||
tmp = -tmp;
|
||||
}
|
||||
|
||||
aibot->targetinsighttemperature -= tmp;
|
||||
aibot->curzerotimer60 -= tmp;
|
||||
}
|
||||
|
||||
if (aibot->targetinsighttemperature > aibot->shootdelaytimer60) {
|
||||
aibot->targetinsighttemperature = aibot->shootdelaytimer60;
|
||||
// Don't allow the bot to zero faster than its shoot delay timer.
|
||||
// ie. The bot should not zero its target then have to wait before it can shoot.
|
||||
if (aibot->curzerotimer60 > aibot->shootdelaytimer60) {
|
||||
aibot->curzerotimer60 = aibot->shootdelaytimer60;
|
||||
}
|
||||
|
||||
if (aibot->targetinsighttemperature < 0) {
|
||||
aibot->targetinsighttemperature = 0;
|
||||
if (aibot->curzerotimer60 < 0) {
|
||||
aibot->curzerotimer60 = 0;
|
||||
}
|
||||
|
||||
if (aibot->targetinsighttemperature >= g_BotDifficulties[diff].unk0c) {
|
||||
aibot->targetinsighttemperature = g_BotDifficulties[diff].unk0c;
|
||||
fVar12 = 0;
|
||||
fVar11 = 0;
|
||||
// Figure out the turn speed that will be used.
|
||||
// The actual speed will be somewhere between minspeed and maxspeed using randomness.
|
||||
if (aibot->curzerotimer60 >= g_BotDifficulties[diff].zerotime60) {
|
||||
aibot->curzerotimer60 = g_BotDifficulties[diff].zerotime60;
|
||||
minspeed = 0;
|
||||
maxspeed = 0;
|
||||
} else {
|
||||
tmp = (g_BotDifficulties[diff].unk0c - aibot->targetinsighttemperature) / g_BotDifficulties[diff].unk0c;
|
||||
fVar12 = g_BotDifficulties[diff].unk04 * tmp;
|
||||
fVar11 = g_BotDifficulties[diff].unk08 * tmp;
|
||||
frac = (g_BotDifficulties[diff].zerotime60 - aibot->curzerotimer60) / g_BotDifficulties[diff].zerotime60;
|
||||
minspeed = g_BotDifficulties[diff].minzerospeed * frac;
|
||||
maxspeed = g_BotDifficulties[diff].maxzerospeed * frac;
|
||||
}
|
||||
|
||||
// If the bot's target is cloaked, make sure the max speed is at least a
|
||||
// certain value. So the bot can zero faster when their target is cloaked?
|
||||
// Rare might have intended for this to apply to zeroinc instead.
|
||||
if (chr->target != -1) {
|
||||
struct prop *target = chrGetTargetProp(chr);
|
||||
|
||||
if (target->chr->hidden & CHRHFLAG_CLOAKED) {
|
||||
if (fVar11 < g_BotDifficulties[diff].unk14) {
|
||||
fVar11 = g_BotDifficulties[diff].unk14;
|
||||
if (chrGetTargetProp(chr)->chr->hidden & CHRHFLAG_CLOAKED) {
|
||||
if (maxspeed < g_BotDifficulties[diff].zerocloakspeed) {
|
||||
maxspeed = g_BotDifficulties[diff].zerocloakspeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fVar11 < g_BotDifficulties[diff].unk18) {
|
||||
fVar11 = g_BotDifficulties[diff].unk18;
|
||||
// Force a minimum max speed (applies if the bot is just starting to zero).
|
||||
// As above, Rare might have intended for this to apply to zeroinc instead.
|
||||
if (maxspeed < g_BotDifficulties[diff].forcezerominspeed) {
|
||||
maxspeed = g_BotDifficulties[diff].forcezerominspeed;
|
||||
}
|
||||
|
||||
aibot->extraanglebase = (fVar11 - fVar12) * (aibot->random3 & 0xffff) * 0.000015259021893144f + fVar12;
|
||||
// Calculate the actual speed increment to use
|
||||
aibot->zeroinc = (maxspeed - minspeed) * (aibot->random3 % 0x10000) * (1.0f / 65535.0f) + minspeed;
|
||||
|
||||
// Negating this seems like a weird choice... unsure what effect this has
|
||||
if (aibot->random3 & 0x10000) {
|
||||
aibot->extraanglebase = -aibot->extraanglebase;
|
||||
aibot->zeroinc = -aibot->zeroinc;
|
||||
}
|
||||
|
||||
for (i = 0; i < g_Vars.lvupdate240; i++) {
|
||||
aibot->extraanglerate = aibot->extraanglerate * (PAL ? 0.97f : 0.97500002384186f) + aibot->extraanglebase;
|
||||
aibot->zerospeed = aibot->zerospeed * (PAL ? 0.97f : 0.97500002384186f) + aibot->zeroinc;
|
||||
}
|
||||
|
||||
aibot->extraangle = aibot->extraanglerate * (PAL ? 0.029999971389771f : 0.024999976158142f);
|
||||
aibot->zeroangle = aibot->zerospeed * (PAL ? 0.029999971389771f : 0.024999976158142f);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1576,7 +1628,7 @@ void botChooseGeneralTarget(struct chrdata *botchr)
|
|||
}
|
||||
}
|
||||
|
||||
bot0f192a74(botchr);
|
||||
botUpdateZeroAngle(botchr);
|
||||
|
||||
// If the bot is data uplinking, clear the target
|
||||
if (botchr->myaction == MA_AIBOTDOWNLOAD) {
|
||||
|
|
@ -3359,7 +3411,7 @@ void botTickUnpaused(struct chrdata *chr)
|
|||
|
||||
if (chr->target != -1
|
||||
&& aibot->targetinsight
|
||||
&& aibot->shootdelaytimer60 >= g_BotDifficulties[aibot->config->difficulty].shootdelay) {
|
||||
&& aibot->shootdelaytimer60 >= g_BotDifficulties[aibot->config->difficulty].shootdelay60) {
|
||||
if (!botIsDizzy(chr)) {
|
||||
if (aibot->weaponnum == WEAPON_TRANQUILIZER) {
|
||||
if (!chrIsTargetInFov(chr, 30, 0) || chrGetDistanceToTarget(chr) > range) {
|
||||
|
|
@ -3469,7 +3521,7 @@ void botTickUnpaused(struct chrdata *chr)
|
|||
|
||||
if (chr->target != -1
|
||||
&& aibot->targetinsight
|
||||
&& aibot->shootdelaytimer60 >= g_BotDifficulties[aibot->config->difficulty].shootdelay
|
||||
&& aibot->shootdelaytimer60 >= g_BotDifficulties[aibot->config->difficulty].shootdelay60
|
||||
&& (botIsDizzy(chr) || chrIsTargetInFov(chr, 45, false))) {
|
||||
throw = true;
|
||||
}
|
||||
|
|
@ -3532,7 +3584,7 @@ void botTickUnpaused(struct chrdata *chr)
|
|||
firing = true;
|
||||
} else if (chr->target != -1
|
||||
&& aibot->targetinsight
|
||||
&& aibot->shootdelaytimer60 >= g_BotDifficulties[aibot->config->difficulty].shootdelay
|
||||
&& aibot->shootdelaytimer60 >= g_BotDifficulties[aibot->config->difficulty].shootdelay60
|
||||
&& (botIsDizzy(chr) || chrIsTargetInFov(chr, 45, false))
|
||||
&& !chrIsDead(chrGetTargetProp(chr)->chr)) {
|
||||
firing = true;
|
||||
|
|
|
|||
|
|
@ -226,12 +226,12 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
|
|||
aibot->chrrooms[i] = -1;
|
||||
}
|
||||
|
||||
aibot->extraangle = 0.0f;
|
||||
aibot->extraanglerate = 0.0f;
|
||||
aibot->extraanglebase = 0.0f;
|
||||
aibot->zeroangle = 0.0f;
|
||||
aibot->zerospeed = 0.0f;
|
||||
aibot->zeroinc = 0.0f;
|
||||
aibot->random3ttl60 = -1;
|
||||
aibot->random3 = 0;
|
||||
aibot->targetinsighttemperature = 0.0f;
|
||||
aibot->curzerotimer60 = 0.0f;
|
||||
aibot->realignangleframe = -1;
|
||||
aibot->waypoints[0] = NULL;
|
||||
aibot->numwaystepstotarget = 0;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ void botDisarm(struct chrdata *chr, struct prop *attacker);
|
|||
void botSetTarget(struct chrdata *chr, s32 propnum);
|
||||
bool botIsTargetInvisible(struct chrdata *botchr, struct chrdata *otherchr);
|
||||
bool botHasGround(struct chrdata *chr);
|
||||
void bot0f192a74(struct chrdata *chr);
|
||||
void botUpdateZeroAngle(struct chrdata *chr);
|
||||
bool botPassesPeaceCheck(struct chrdata *botchr, struct chrdata *otherchr);
|
||||
bool botPassesCowardCheck(struct chrdata *botchr, struct chrdata *otherchr);
|
||||
void botChooseGeneralTarget(struct chrdata *chr);
|
||||
|
|
|
|||
|
|
@ -785,12 +785,12 @@ struct aibot {
|
|||
/*0x16c*/ u8 chrsinsight[MAX_MPCHRS];
|
||||
/*0x178*/ s32 chrslastseen60[MAX_MPCHRS];
|
||||
/*0x1a8*/ RoomNum chrrooms[MAX_MPCHRS];
|
||||
/*0x1c0*/ f32 extraangle;
|
||||
/*0x1c4*/ f32 extraanglerate;
|
||||
/*0x1c8*/ f32 extraanglebase;
|
||||
/*0x1c0*/ f32 zeroangle;
|
||||
/*0x1c4*/ f32 zerospeed;
|
||||
/*0x1c8*/ f32 zeroinc;
|
||||
/*0x1cc*/ s32 random3ttl60;
|
||||
/*0x1d0*/ u32 random3;
|
||||
/*0x1d4*/ f32 targetinsighttemperature;
|
||||
/*0x1d4*/ f32 curzerotimer60;
|
||||
/*0x1d8*/ s32 abortattacktimer60;
|
||||
/*0x1dc*/ bool canbreakdefend;
|
||||
/*0x1e0*/ bool canbreakfollow;
|
||||
|
|
@ -4519,17 +4519,6 @@ struct modelstate {
|
|||
u16 scale;
|
||||
};
|
||||
|
||||
struct botdifficulty {
|
||||
u8 shootdelay;
|
||||
f32 unk04;
|
||||
f32 unk08;
|
||||
u16 unk0c;
|
||||
f32 unk10;
|
||||
f32 unk14;
|
||||
f32 unk18;
|
||||
s32 dizzyamount;
|
||||
};
|
||||
|
||||
struct animtablerow {
|
||||
s16 animnum;
|
||||
bool flip;
|
||||
|
|
|
|||
Loading…
Reference in New Issue