Project

General

Profile

Bug #207 » 0004-AI-Stop-attempts-to-recover-Helicopter-HP-in-the-ope.patch

Marko Lindqvist, 02/04/2024 08:19 PM

View differences:

ai/default/daiunit.c
CHECK_UNIT(punit);
if (pcity) {
/* rest in city until the hitpoints are recovered, but attempt
to protect city from attack (and be opportunistic too)*/
if (pcity != NULL) {
/* Rest in the city until the hitpoints are recovered, but attempt
* to protect city from attack (and be opportunistic too)*/
if (dai_military_rampage(punit, RAMPAGE_ANYTHING,
RAMPAGE_FREE_CITY_OR_BETTER)) {
UNIT_LOG(LOGLEVEL_RECOVERY, punit, "recovering hit points.");
} else {
return; /* we died heroically defending our city */
return; /* We died heroically defending our city */
}
} else {
/* goto to nearest city to recover hit points */
/* just before, check to see if we can occupy an undefended enemy city */
/* Goto to nearest city to recover hit points */
/* Just before, check to see if we can occupy an undefended enemy city */
if (!dai_military_rampage(punit, RAMPAGE_FREE_CITY_OR_BETTER,
RAMPAGE_FREE_CITY_OR_BETTER)) {
return; /* oops, we died */
return; /* Oops, we died */
}
/* find city to stay and go there */
/* Find a city to stay and go there */
safe = find_nearest_safe_city(punit);
if (safe) {
UNIT_LOG(LOGLEVEL_RECOVERY, punit, "going to %s to recover",
......
return;
}
} else {
/* oops */
/* Oops */
UNIT_LOG(LOGLEVEL_RECOVERY, punit, "didn't find a city to recover in!");
dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
dai_military_attack(ait, pplayer, punit);
......
}
}
/* is the unit still damaged? if true recover hit points, if not idle */
if (punit->hp == punittype->hp) {
/* we are ready to go out and kick ass again */
/* Is the unit still damaged? If true, and could recover hit points, do so.
* Don't wait if would be losing hitpoints that way! */
if (punit->hp == punittype->hp || unit_gain_hitpoints(punit) <= 0) {
/* We are ready to go out and kick ass again */
UNIT_LOG(LOGLEVEL_RECOVERY, punit, "ready to kick ass again!");
dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
return;
} else {
def_ai_unit_data(punit, ait)->done = TRUE; /* sit tight */
def_ai_unit_data(punit, ait)->done = TRUE; /* Sit tight */
}
}
common/unit.c
}
/**********************************************************************//**
returns how many hp's a unit will gain standing still on current tile
depends on whether or not it's inside city or fortress.
barracks will regen landunits completely
airports will regen airunits completely
ports will regen navalunits completely
fortify will add a little extra.
Returns how many hp's a unit will gain standing still on current tile.
**************************************************************************/
int hp_gain_coord(struct unit *punit)
int hp_gain_coord(const struct unit *punit)
{
int hp = 0;
const int base = unit_type_get(punit)->hp;
......
return MAX(hp, 0);
}
/**********************************************************************//**
How many hitpoints does unit recover?
**************************************************************************/
int unit_gain_hitpoints(const struct unit *punit)
{
const struct unit_type *utype = unit_type_get(punit);
struct unit_class *pclass = unit_class_get(punit);
struct city *pcity = tile_city(unit_tile(punit));
int gain;
if (!punit->moved) {
gain = hp_gain_coord(punit);
} else {
gain = 0;
}
gain += get_unit_bonus(punit, EFT_UNIT_RECOVER);
if (!punit->homecity && 0 < game.server.killunhomed
&& !unit_has_type_flag(punit, UTYF_GAMELOSS)) {
/* Hit point loss of units without homecity; at least 1 hp! */
/* Gameloss units are immune to this effect. */
int hp_loss = MAX(utype->hp * game.server.killunhomed / 100, 1);
if (gain > hp_loss) {
gain = -1;
} else {
gain -= hp_loss;
}
}
if (pcity == NULL && !tile_has_native_base(unit_tile(punit), utype)
&& !unit_transported(punit)) {
gain -= utype->hp * pclass->hp_loss_pct / 100;
}
if (punit->hp + gain > utype->hp) {
gain = utype->hp - punit->hp;
} else if (punit->hp + gain < 0) {
gain = -punit->hp;
}
return gain;
}
/**********************************************************************//**
Does unit lose hitpoints each turn?
**************************************************************************/
common/unit.h
int unit_pays_mp_for_action(const struct action *paction,
const struct unit *punit);
int hp_gain_coord(struct unit *punit);
int hp_gain_coord(const struct unit *punit);
int unit_gain_hitpoints(const struct unit *punit);
bool is_losing_hp(const struct unit *punit);
bool unit_type_is_losing_hp(const struct player *pplayer,
const struct unit_type *punittype);
server/unittools.c
}
/**********************************************************************//**
add hitpoints to the unit, hp_gain_coord returns the amount to add
Add hitpoints to the unit, hp_gain_coord returns the amount to add
united nations will speed up the process by 2 hp's / turn, means helicopters
will actually not lose hp's every turn if player have that wonder.
Units which have moved don't gain hp, except the United Nations and
......
static void unit_restore_hitpoints(struct unit *punit)
{
bool was_lower;
int save_hp;
struct unit_class *pclass = unit_class_get(punit);
struct city *pcity = tile_city(unit_tile(punit));
was_lower = (punit->hp < unit_type_get(punit)->hp);
save_hp = punit->hp;
if (!punit->moved) {
punit->hp += hp_gain_coord(punit);
}
const struct unit_type *utype = unit_type_get(punit);
/* Bonus recovery HP (traditionally from the United Nations) */
punit->hp += get_unit_bonus(punit, EFT_UNIT_RECOVER);
was_lower = (punit->hp < utype->hp);
if (!punit->homecity && 0 < game.server.killunhomed
&& !unit_has_type_flag(punit, UTYF_GAMELOSS)) {
/* Hit point loss of units without homecity; at least 1 hp! */
/* Gameloss units are immune to this effect. */
int hp_loss = MAX(unit_type_get(punit)->hp * game.server.killunhomed / 100,
1);
punit->hp = MIN(punit->hp - hp_loss, save_hp - 1);
}
punit->hp += unit_gain_hitpoints(punit);
if (!pcity && !tile_has_native_base(unit_tile(punit), unit_type_get(punit))
&& !unit_transported(punit)) {
punit->hp -= unit_type_get(punit)->hp * pclass->hp_loss_pct / 100;
}
fc_assert(punit->hp >= 0);
fc_assert(punit->hp <= utype->hp);
if (punit->hp >= unit_type_get(punit)->hp) {
punit->hp = unit_type_get(punit)->hp;
if (punit->hp == utype->hp) {
if (was_lower && punit->activity == ACTIVITY_SENTRY) {
set_unit_activity(punit, ACTIVITY_IDLE);
}
}
if (punit->hp < 0) {
punit->hp = 0;
}
punit->moved = FALSE;
punit->paradropped = FALSE;
}
(3-3/4)