Improve "Whomever is attacking me" targeting

Fixes #197
This commit is contained in:
Alexander Batalov 2022-12-29 09:37:51 +03:00
parent 11217974c6
commit 34259269a4
1 changed files with 85 additions and 27 deletions

View File

@ -1508,7 +1508,7 @@ static Object* _ai_danger_source(Object* a1)
return NULL; return NULL;
} }
bool v2 = false; bool ignoreFleeingCritters = false;
int attackWho; int attackWho;
Object* targets[4]; Object* targets[4];
@ -1518,42 +1518,100 @@ static Object* _ai_danger_source(Object* a1)
int disposition = aiGetDisposition(a1); int disposition = aiGetDisposition(a1);
switch (disposition + 1) { switch (disposition + 1) {
case 1: case DISPOSITION_CUSTOM:
case 2: case DISPOSITION_COWARD:
case 3: case DISPOSITION_DEFENSIVE:
case 4: case DISPOSITION_AGGRESSIVE:
v2 = true; ignoreFleeingCritters = true;
break; break;
case 0: case DISPOSITION_NONE:
case 5: case DISPOSITION_BERKSERK:
v2 = false; ignoreFleeingCritters = false;
break; break;
} }
if (v2 && aiGetDistance(a1) == DISTANCE_CHARGE) { if (ignoreFleeingCritters && aiGetDistance(a1) == DISTANCE_CHARGE) {
v2 = false; ignoreFleeingCritters = false;
} }
attackWho = aiGetAttackWho(a1); attackWho = aiGetAttackWho(a1);
switch (attackWho) { switch (attackWho) {
case ATTACK_WHO_WHOMEVER_ATTACKING_ME: { case ATTACK_WHO_WHOMEVER_ATTACKING_ME:
Object* candidate = aiInfoGetLastTarget(gDude); if (1) {
if (candidate == NULL || a1->data.critter.combat.team == candidate->data.critter.combat.team) { // CE: Slightly improve "Whomever is attacking me" targeting.
break; //
// First attempt to continue attack our previous target. This
// prevents jumping from target to target thus spending precious
// action points on meaningless movements.
Object* candidate = aiInfoGetLastTarget(a1);
if (candidate != NULL) {
// Check if candidate is still a valid target:
// - not dead and not knocked out
// - not on the same team
// - still attacking dude
Object* critter = candidate;
if ((critter->data.critter.combat.results & (DAM_DEAD | DAM_KNOCKED_OUT)) != 0
|| a1->data.critter.combat.team == critter->data.critter.combat.team
|| aiInfoGetLastTarget(critter) != gDude) {
candidate = NULL;
} }
if (pathfinderFindPath(a1, a1->tile, gDude->data.critter.combat.whoHitMe->tile, NULL, 0, _obj_blocking_at) == 0 // NOTE: I'm not sure if we need to revalidate candidate's
&& _combat_check_bad_shot(a1, candidate, HIT_MODE_RIGHT_WEAPON_PRIMARY, false) != COMBAT_BAD_SHOT_OK) { // reachability and shot conditions.
debugPrint("\nai_danger_source: %s couldn't attack at target! Picking alternate!", critterGetName(a1));
break; // Do not chase fleeing critter.
if (ignoreFleeingCritters && critterIsFleeing(critter)) {
candidate = NULL;
}
} }
if (v2 && critterIsFleeing(a1)) { if (candidate == NULL) {
break; // Previous target is invalid. Pick nearest candidate who's
// attacking dude.
_ai_sort_list_distance(_curr_crit_list, _curr_crit_num, a1);
for (int index = 0; index < _curr_crit_num; index++) {
Object* critter = _curr_crit_list[index];
if (critter != a1) {
// Check if it's valid target (same conditions as
// above).
if ((critter->data.critter.combat.results & (DAM_DEAD | DAM_KNOCKED_OUT)) != 0
|| a1->data.critter.combat.team == critter->data.critter.combat.team
|| aiInfoGetLastTarget(critter) != gDude) {
continue;
} }
// Make sure critter is reachable.
if (pathfinderFindPath(a1, a1->tile, critter->tile, NULL, 0, _obj_blocking_at) == 0) {
continue;
}
// Check if we can attack it. No ammo and out of
// range are ok results, since we can reload weapon
// move closer if necessary.
int badShot = _combat_check_bad_shot(a1, critter, HIT_MODE_RIGHT_WEAPON_PRIMARY, false);
if (badShot != COMBAT_BAD_SHOT_OK
&& badShot != COMBAT_BAD_SHOT_NO_AMMO
&& badShot != COMBAT_BAD_SHOT_OUT_OF_RANGE) {
continue;
}
// Do not chase fleeing critter.
if (ignoreFleeingCritters && critterIsFleeing(critter)) {
continue;
}
candidate = critter;
break;
}
}
}
if (candidate != NULL) {
return candidate; return candidate;
} }
}
break;
case ATTACK_WHO_STRONGEST: case ATTACK_WHO_STRONGEST:
case ATTACK_WHO_WEAKEST: case ATTACK_WHO_WEAKEST:
case ATTACK_WHO_CLOSEST: case ATTACK_WHO_CLOSEST:
@ -1585,7 +1643,7 @@ static Object* _ai_danger_source(Object* a1)
aiFindAttackers(a1, &(targets[1]), &(targets[2]), &(targets[3])); aiFindAttackers(a1, &(targets[1]), &(targets[2]), &(targets[3]));
if (v2) { if (ignoreFleeingCritters) {
for (int index = 0; index < 4; index++) { for (int index = 0; index < 4; index++) {
if (targets[index] != NULL && critterIsFleeing(targets[index])) { if (targets[index] != NULL && critterIsFleeing(targets[index])) {
targets[index] = NULL; targets[index] = NULL;