Bug #207 » 0004-AI-Stop-attempts-to-recover-Helicopter-HP-in-the-ope.patch
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;
|
||
}
|