One (
min/max) is direct random chance and the other (
aggression) is timing between chances. They are used in conjunction with a third value called
attackthrottle to limit when the AI attacks, providing an in game effect of more human-like reflexes. Otherwise, you'd have 0 chance of beating the AI.
When an entity is in position to attack, it first rolls a random chance (more on that below). Assuming the random chance passes,
aggression modifies the amount of time added to
stall_time, which is an entity variable the engine uses to control action delays for the entity.
C:
if(!check_attack_chance(target, 1.0f - min_noatk_chance, 1.0f - min_noatk_chance))
{
self->nextattack = _time + randf(self->modeldata.attackthrottletime);
return 0;
}
else
{
self->stalltime = _time + (int)randf((float)MAX(1, GAME_SPEED * 3 / 4 - self->modeldata.aggression));
}
The
min_noatk_chance and
max_noatk_chance are used as part of the random attack chance roll. Before the entity can attack, it rolls a random chance that has to fall between two values (a min and max). The min and max are calculated using a variety of in-game factors. What min_noatk_chance and max_no_chance do is act as caps on the min/max formula. The default is 0.0 and 0.6 respectively.
Also note the value
attackthrottle. This modifies the chance roll, increasing or decreasing the chance of an attack.
C:
int check_attack_chance(entity *target, float min, float max)
{
float chance, chance1, chance2;//, aggfix;
if(self->modeldata.aiattack & AIATTACK1_ALWAYS)
{
return 1;
}
chance1 = MIN(1.0f, (diff(self->position.x, self->destx) + diff(self->position.z, self->destz)) / (videomodes.hRes + videomodes.vRes) * move_noatk_factor);
chance2 = MIN(1.0f, (count_ents(self->modeldata.type) - 1) * group_noatk_factor);
chance = (1.0f - chance1) * (1.0f - chance2);
if(chance > max)
{
chance = max;
}
else if(chance < min)
{
chance = min;
}
chance *= (1.0 - self->modeldata.attackthrottle);
if(self->position.x < screenx - 10 || self->position.x > screenx + videomodes.hRes + 10)
{
if (self->modeldata.offscreen_noatk_factor != 0) chance *= (1.0 - self->modeldata.offscreen_noatk_factor);
else chance *= (1.0 - offscreen_noatk_factor);
}
return (randf(1) <= chance);
}
In summary:
- min/max attack chance act as caps for the min/max rolls the engine's random chance must fall between. The engine can and will still make adjustments within those boundaries based on entity position.
- attackthrottle modifies the entity's chance to attack. It makes the entity more or less likely to try an attack.
- aggression modifies the time between chances to attack.
As an example, you could give a high attackthrottle and low aggression to make someone who is super quick with a first attack but doesn't wail endlessly on the target afterwards. Don't forget you have range, movement, AI flags, and a lot of other things that also come into play, so you'll need to experiment a bit to get behaviors you want.
HTH,
DC