Separate "cures" from "heals" cleanly:

...remove global assumptions about cure/heal amounts, too.

I also added an explicit number to how much terrain heals (it's still
assumed to cure).

I also separated "cures" and "heals" from the user's perspective,
which unfortunately means the description of "heals" does not include
the number of HP any more.  It would be nice if the tooltip could use
variables...
This commit is contained in:
Rusty Russell 2006-03-29 12:09:39 +00:00
parent dbd341e8dd
commit f2a9f6455c
24 changed files with 171 additions and 177 deletions

24
MANUAL
View file

@ -224,22 +224,24 @@ points of damage regardless of the time of day.
HEALING
Injured units in villages will recover 8 hitpoints every turn. Injured
units that are adjacent to units with the 'heal' or 'cure' abilities
units that are adjacent to units with the 'heal' abilities
will also heal. A unit that does not move or fight during a turn is
'resting' and will recover an additional 2 hitpoints.
A unit with the 'heals' ability will heal adjacent allied units by up
to 4 hitpoints each, at the beginning of the healer's turn. Poisoned
units will have their poison damage stopped by the healer, instead.
A unit with the 'heals' ability will heal adjacent allied units at the
beginning of the healer's turn. Poisoned units will have their poison
damage stopped by the healer, instead of being healed.
A unit with the 'cures' ability will heal adjacent allied units by up
to 8 hitpoints each, at the beginning of the curer's turn. Poisoned
units will have their poison cured by healer, instead.
A unit with the 'cures' ability will remove poison from a unit.
Usually a unit with 'cures' ability has 'heals' as well, but a unit
will be cured of poison instead of healed.
No unit can be healed or cured by more than one thing at a time: the
effects are not cumulative. For example, a unit standing in a village
gains no additional benefit from a curer standing next to it. A unit
standing next to two healers and a curer will not use the two healers.
No unit can be healed by more than one thing at a time: the effects
are not cumulative. The most powerful healing method is always
selected. For example, a unit standing in a village gains no
additional benefit from a healer standing next to it if the healer
does less than 8 hitpoints healing. A unit standing next to three
healers will only use the most powerful healer.
For more information see the in-game help.

View file

@ -3,16 +3,17 @@
[heals]
description=heals
amount=4
max=8
[/heals]
#enddef
# For backward compat reasons, this heals & cures.
#define ABILITY_CURES
[heals]
description=cures
description=heals
amount=8
max=18
[/heals]
[cures]
[/cures]
#enddef
#define ABILITY_REGENERATES

View file

@ -23,11 +23,7 @@ Enemy units cannot see or attack this unit when it is in forest, except for any
ability_ambush= _ "ambush"
cures_description= _ "Cures:
This unit combines herbal remedies with magic to heal units more quickly than is normally possible on the battlefield.
This unit will care for all adjacent friendly units that are injured at the beginning of its turn.
Each non-poisoned unit cared for by a curer will heal by up to 8 HP per turn.
A curer can cure a unit of poison, although that unit will receive no additional healing on the turn it is cured of the poison."
This unit combines herbal remedies with magic to cure a unit of poison. Most units with this ability also are extremely effective healers, but will cure poisoned units rather than healing them."
ability_cures= _ "cures"
@ -35,7 +31,7 @@ heals_description= _ "Heals:
Allows the unit to heal adjacent friendly units at the beginning of each turn.
This unit will care for all adjacent friendly units that are injured at the beginning of its turn.
Each non-poisoned unit cared for by a healer will heal up to 4 HP per turn.
Each non-poisoned unit cared for by a healer will heal by 4 HP or 8 HP per turn, depending on the healer's ability.
A healer will stop the damage done by poison on the current turn, but cannot cure it: the poisoned unit must seek the care of a village or a unit that can cure."
ability_heals= _ "heals"

View file

@ -43,8 +43,7 @@ default=yes
[game_config]
base_income=2
village_income=1
heal_amount=4
cure_amount=8
poison_amount=8
rest_heal_amount=2
recall_cost=20
kill_experience=8

View file

@ -216,8 +216,8 @@ text= _ "In combat, your units will inevitably take damage. When a unit <ref>dst
Resting: A unit which neither moves, attacks, nor is attacked will heal 2HP in its next turn." + _"
Villages: A unit which starts a turn in a village will heal 8HP." + _"
<ref>dst=ability_regenerates text=Regeneration</ref>: Certain units (such as trolls) will automatically heal 8HP every turn." + _"
Healing units: Units with the <ref>dst=ability_heals text=Heals</ref> ability will heal up to 4HP of damage from each allied adjacent unit, per turn, or prevent Poison from causing that unit damage." + _"
Curing units: Units with the <ref>dst=ability_cures text=Cures</ref> ability will heal up to 8HP of damage from each allied adjacent unit, per turn, or cure Poison in that unit." + _"
Healing units: Units with the <ref>dst=ability_heals text=Heals</ref> ability will heal each allied adjacent unit, usually 4 or 8HP per turn, or prevent Poison from causing that unit damage." + _"
Curing units: Units with the <ref>dst=ability_cures text=Cures</ref> ability will heal cure Poison in all allied adjacent units (in preference to healing, if it has that ability as well)." + _"
Resting can be combined with other forms of healing, but villages, regeneration, healing and curing cannot combine with each other: the best option will be used. Finally, units heal fully between scenarios."
[/topic]

View file

@ -147,7 +147,7 @@ symbol_image=village-human-tile
id=village
name= _ "Village"
char=v
heals=true
heals=8
gives_income=true
[/terrain]
@ -159,7 +159,7 @@ char=Z
aliasof=c
submerge=0.4
unit_height_adjust=-4
heals=true
heals=8
gives_income=true
[/terrain]
@ -169,7 +169,7 @@ id=swamp_village
name= _ "Village"
char=Y
aliasof=vw
heals=true
heals=8
gives_income=true
[/terrain]
@ -179,7 +179,7 @@ id=village
name= _ "Village"
char=t
aliasof=v
heals=true
heals=8
gives_income=true
[/terrain]
@ -190,7 +190,7 @@ id=desert_village
name= _ "Village"
char=B
aliasof=vI
heals=true
heals=8
gives_income=true
[/terrain]
@ -200,7 +200,7 @@ id=desert_village
name= _ "Village"
char=U
aliasof=vI
heals=true
heals=8
gives_income=true
[/terrain]
@ -210,7 +210,7 @@ id=oasis
name= _ "Oasis"
char=P
aliasof=I
heals=true
heals=8
#gives_income=true
[/terrain]
@ -220,7 +220,7 @@ id=tropical_forest_village
name= _ "Village"
char=L
aliasof=v
heals=true
heals=8
gives_income=true
[/terrain]
@ -230,7 +230,7 @@ id=hill_village
name= _ "Village"
char=a
aliasof=vh
heals=true
heals=8
gives_income=true
[/terrain]
@ -240,7 +240,7 @@ id=snow-hill_village
name= _ "Village"
char=A
aliasof=vh
heals=true
heals=8
gives_income=true
[/terrain]
@ -250,7 +250,7 @@ id=mountain_village
name= _ "Village"
char=b
aliasof=vm
heals=true
heals=8
gives_income=true
[/terrain]
@ -260,7 +260,7 @@ id=snow_village
name= _ "Village"
char=V
aliasof=v
heals=true
heals=8
gives_income=true
[/terrain]
@ -270,7 +270,7 @@ id=elven_snow_village
name= _ "Village"
char=e
aliasof=v
heals=true
heals=8
gives_income=true
[/terrain]
@ -280,7 +280,7 @@ id=underground_village
name= _ "Village"
char=D
aliasof=vu
heals=true
heals=8
gives_income=true
[/terrain]
@ -290,7 +290,7 @@ id=dwarven_village
name= _ "Village"
char=p
aliasof=vu
heals=true
heals=8
gives_income=true
[/terrain]

View file

@ -2,7 +2,7 @@ tip_of_day1= _ "Lawful units fight better at day, and chaotic units fight better
tip_of_day2= _ "In a campaign, you can use veteran units from previous scenarios by using the 'recall' option."
tip_of_day3= _ "There are six types of attacks: pierce, blade, impact, fire, cold, and holy. Different units have weaknesses against different types of attacks. Right-click on a unit, and then select 'Unit Description', and then click 'Resistance' to see how much resistance a unit has against different attack types."
tip_of_day4= _ "The terrain your units are occupying determines the chance your opponents have of hitting them in battle. The defensive rating for the currently selected unit in the currently selected terrain is displayed in the top right corner of the screen."
tip_of_day5= _ "Poisoned units lose 8 hitpoints every turn, but they will not die from poison: poison will never reduce them below 1 hitpoint. Poisoned units can be cured by moving them to a village, or placing them next to a unit with the 'cure' ability."
tip_of_day5= _ "Poisoned units lose 8 hitpoints every turn, but they will not die from poison: poison will never reduce them below 1 hitpoint. Poisoned units can be cured by moving them to a village, or placing them next to a unit with the 'cures' ability."
tip_of_day6= _ "You can use units from a previous scenario by selecting 'Recall' in the game menu. By recalling the same units over and over, you can build up a powerful and experienced army."
tip_of_day7= _ "Units have a Zone of Control in each of the hexes next to them. If a unit moves into an enemy's Zone of Control, it may not move any further that turn. Level 0 units are too frail to control a zone; and skirmisher units are skilled enough to ignore these zones."
tip_of_day8= _ "The chance to hit a unit usually depends on how well that unit can defend itself in the terrain it is standing in, however magical attacks have a 70% chance to hit both when attacking and defending. Marksman attacks have at least 60% chance to hit when attacking."

View file

@ -18,7 +18,7 @@
The claws of a wolf are not generally regarded as being the more dangerous parts, but on a beast this large, they are thicker and longer than iron nails. Their riders smear a poison on the front set, not unlike that used by the orcish assassins, making a swipe from these beasts' paws into a most deadly stroke.
Special Notes: anyone struck by a direwolf's claws will be poisoned, and victims of this poison will continually take damage until they can be cured in town or by a healer."
Special Notes: anyone struck by a direwolf's claws will be poisoned, and victims of this poison will continually take damage until they can be cured in town or by a unit which cures."
get_hit_sound=wolf-hit.wav
die_sound=wolf-die.wav
[defend]

View file

@ -16,7 +16,7 @@
usage=fighter
unit_description= _ "The larger, and often more skilled orcish assassins are called 'Slayers' by their enemies, though this distinction is somewhat unclear. Slayers are fast on their feet, and quite nimble in combat, although they achieve that end by forgoing armor. Their weapon of choice, poison, is a vicious tool, and its common use on the battlefield is often the real cause of orcish supremacy.
Special Notes: Orcish Slayers use poison on their throwing knives, and victims of this poison will continually take damage until they can be cured in town or by a healer."
Special Notes: Orcish Slayers use poison on their throwing knives, and victims of this poison will continually take damage until they can be cured in town or by a unit which cures."
get_hit_sound=orc-hit.wav
die_sound=orc-die.wav
[defend]

View file

@ -17,7 +17,7 @@
It is because of such things that necromancy is condemned with an almost primal hatred.
Special Notes: A ghoul's claws are covered in poison, and victims of this poison will continually take damage until they can be cured in town or by a healer."
Special Notes: A ghoul's claws are covered in poison, and victims of this poison will continually take damage until they can be cured in town or by a unit which cures."
get_hit_sound=ghoul-hit.wav
[defend]
[frame]

View file

@ -17,7 +17,7 @@
usage=fighter
unit_description= _ "Driven ravenous by an unholy hunger for dead flesh, Necrophages attack their hoped-for food with beast-like ferocity. When they are sated with the flesh of their victims, they simply shrug off all damage sustained as if they had been freshly summoned, to begin their search for flesh again.
Special Notes: A Necrophage's claws are covered in poison, and victims of this poison will continually take damage until they can be cured in town or by a healer."
Special Notes: A Necrophage's claws are covered in poison, and victims of this poison will continually take damage until they can be cured in town or by a unit which cures."
get_hit_sound=ghoul-hit.wav
[defend]
[frame]

View file

@ -1384,62 +1384,9 @@ unit_map::const_iterator find_leader(const unit_map& units, int side)
}
namespace {
struct patient
{
patient(unit &un, bool allied)
: u(un), healing(0), poison_stopped(false), ally(allied) { }
unit &u;
// How much have we been healed?
int healing;
// Was our poison stopped / cured?
bool poison_stopped;
// Are we an ally? In which case we only get healed.
bool ally;
void heal(int amount, bool allies_too);
void harm(int amount);
void rest();
};
void patient::heal(int amount, bool allies_too)
{
if (ally && !allies_too)
return;
if (u.poisoned()) {
if (amount >= game_config::cure_amount)
u.remove_flag("poisoned");
poison_stopped = true;
} else {
healing = minimum(u.max_hitpoints() - u.hitpoints(), amount);
std::cerr << "healing by " << lexical_cast<std::string>(healing) << " of potential "
<< lexical_cast<std::string>(u.max_hitpoints() - u.hitpoints()) << "\n";
}
}
void patient::harm(int amount)
{
if (ally)
return;
wassert(!healing && !poison_stopped);
healing = -minimum(u.hitpoints() - 1, amount);
}
void patient::rest()
{
if (ally)
return;
healing += minimum(u.max_hitpoints() - (u.hitpoints() + healing), game_config::rest_heal_amount);
std::cerr << "resting by " << lexical_cast<std::string>(minimum(u.max_hitpoints() - (u.hitpoints() + healing), game_config::rest_heal_amount)) << "\n";
}
// Find the best adjacent healer.
unit_map::iterator find_healer(const gamemap::location &loc, std::map<gamemap::location,unit>& units,
unsigned int side)
unsigned int side, bool wants_curing)
{
gamemap::location adjacent[6];
unit_map::iterator healer = units.end();
@ -1452,9 +1399,9 @@ unit_map::iterator find_healer(const gamemap::location &loc, std::map<gamemap::l
continue;
if (i->second.side() != side)
continue;
if (!i->second.type().heals())
continue;
if (healer == units.end() || i->second.type().heals() > healer->second.type().heals())
if (healer == units.end()
|| i->second.type().heals() > healer->second.type().heals()
|| (wants_curing && i->second.type().cures()))
healer = i;
}
}
@ -1483,37 +1430,75 @@ void calculate_healing(display& disp, const gamestatus& status, const gamemap& m
if (!i->second.healable())
continue;
patient p(i->second, i->second.side() != side);
unit_map::iterator healer = units.end();
int heal = 0;
bool cure = false;
if (p.u.type().regenerates())
p.heal(p.u.type().regenerate_amount(), false);
else if (map.gives_healing(i->first))
p.heal(game_config::cure_amount, false);
else {
healer = find_healer(i->first, units, side);
if (healer != units.end())
p.heal(healer->second.type().heals(), true);
// First look for the best healer. Even if unit is allied, it can use this.
healer = find_healer(i->first, units, side, i->second.poisoned());
if (healer != units.end()) {
heal = healer->second.type().heals();
cure = healer->second.type().cures();
}
if (p.u.poisoned() && !p.poison_stopped)
p.harm(game_config::cure_amount);
if (p.u.is_resting())
p.rest();
if (!p.healing && !p.poison_stopped)
// All other healing/harming effect happen only to this side.
if (i->second.side() == side) {
// Can we regenerate as well or better than the healer?
if (i->second.type().regenerates()) {
if (i->second.poisoned() || i->second.type().regenerate_amount() >= heal) {
healer = units.end();
heal = i->second.type().regenerate_amount();
cure = true;
}
}
// Can village do as well or better than healer/regeneration?
if (map.gives_healing(i->first)) {
if (i->second.poisoned() || map.gives_healing(i->first) >= heal) {
healer = units.end();
heal = map.gives_healing(i->first);
cure = true;
}
}
// FIXME: Make poison damage configurable by attack?
if (i->second.poisoned() && !cure) {
if (!heal)
heal -= game_config::poison_amount;
else
heal = 0;
}
if (i->second.is_resting())
heal += game_config::rest_heal_amount;
}
// Poison curing is chosen over healing.
if (i->second.poisoned() && cure) {
i->second.remove_flag("poisoned");
heal = 0;
}
// Make sure we don't overheal, overpoison.
if (heal < -(i->second.hitpoints() - 1))
heal = -(i->second.hitpoints() - 1);
else if (heal > i->second.max_hitpoints() - i->second.hitpoints())
heal = i->second.max_hitpoints() - i->second.hitpoints();
if (heal == 0)
continue;
if (disp.turbo() || recorder.is_skipping()
|| disp.fogged(i->first.x, i->first.y)
|| !update_display
|| (p.u.invisible(map.underlying_union_terrain(map[i->first.x][i->first.y]),
|| (i->second.invisible(map.underlying_union_terrain(map[i->first.x][i->first.y]),
status.get_time_of_day().lawful_bonus,i->first,units,teams) &&
teams[disp.viewing_team()].is_enemy(side))) {
// Simple path.
if (p.healing > 0)
p.u.heal(p.healing);
else if (p.healing < 0)
p.u.gets_hit(-p.healing);
if (heal > 0)
i->second.heal(heal);
else if (heal < 0)
i->second.gets_hit(-heal);
continue;
}
@ -1526,45 +1511,45 @@ void calculate_healing(display& disp, const gamestatus& status, const gamemap& m
healer->second.set_healing(disp);
start_time = healer->second.get_animation()->get_first_frame_time();
}
if (p.healing < 0) {
p.u.set_poisoned(disp, -p.healing);
start_time = minimum<int>(start_time, p.u.get_animation()->get_first_frame_time());
if (heal < 0) {
i->second.set_poisoned(disp, -heal);
start_time = minimum<int>(start_time, i->second.get_animation()->get_first_frame_time());
sound::play_sound("groan.wav");
disp.float_label(i->first, lexical_cast<std::string>(-p.healing), 255,0,0);
disp.float_label(i->first, lexical_cast<std::string>(-heal), 255,0,0);
} else {
p.u.set_healed(disp, p.healing);
start_time = minimum<int>(start_time, p.u.get_animation()->get_first_frame_time());
i->second.set_healed(disp, heal);
start_time = minimum<int>(start_time, i->second.get_animation()->get_first_frame_time());
sound::play_sound("heal.wav");
disp.float_label(i->first, lexical_cast<std::string>(p.healing), 0,255,0);
disp.float_label(i->first, lexical_cast<std::string>(heal), 0,255,0);
}
// restart both anims in a synchronized way
p.u.restart_animation(disp, start_time);
i->second.restart_animation(disp, start_time);
if (healer != units.end())
healer->second.restart_animation(disp, start_time);
bool finished;
do {
finished = (p.u.get_animation()->animation_finished());
finished = (i->second.get_animation()->animation_finished());
disp.draw_tile(i->first.x, i->first.y);
if (healer != units.end()) {
finished &= healer->second.get_animation()->animation_finished();
disp.draw_tile(healer->first.x, healer->first.y);
}
if (p.healing > 0) {
p.u.heal(1);
--p.healing;
} else if (p.healing < 0) {
p.u.gets_hit(1);
++p.healing;
if (heal > 0) {
i->second.heal(1);
--heal;
} else if (heal < 0) {
i->second.gets_hit(1);
++heal;
}
finished &= (!p.healing);
finished &= (heal == 0);
disp.update_display();
events::pump();
SDL_Delay(10);
} while (!finished);
p.u.set_standing(disp);
i->second.set_standing(disp);
if (healer != units.end())
healer->second.set_standing(disp);
disp.update_display();

View file

@ -1206,7 +1206,7 @@ bool ai::get_healing(std::map<gamemap::location,paths>& possible_moves, const mo
//worth of healing, and doesn't regenerate itself, then try to
//find a vacant village for it to rest in
if(u.side() == team_num_ &&
u.max_hitpoints() - u.hitpoints() >= game_config::cure_amount/2 &&
u.max_hitpoints() - u.hitpoints() >= game_config::poison_amount/2 &&
!u.type().regenerates()) {
//look for the village which is the least vulnerable to enemy attack

View file

@ -532,7 +532,7 @@ void ai::attack_analysis::analyze(const gamemap& map, unit_map& units, int num_s
//if the attacker moved onto a village, reward it for doing so
else if(on_village) {
atthp += game_config::cure_amount*2; //double reward to emphasize getting onto villages
atthp += game_config::poison_amount*2; //double reward to emphasize getting onto villages
}
defenderxp += (atthp == 0 ? game_config::kill_experience:1)*att->second.type().level();
@ -550,8 +550,8 @@ void ai::attack_analysis::analyze(const gamemap& map, unit_map& units, int num_s
defhp = defend_it->second.hitpoints();
} else if(defhp == 0) {
chance_to_kill += 1.0;
} else if(map.is_village(defend_it->first)) {
defhp += game_config::cure_amount;
} else if(map.gives_healing(defend_it->first)) {
defhp += map.gives_healing(defend_it->first);
if(defhp > target_hp)
defhp = target_hp;
}

View file

@ -24,8 +24,7 @@ namespace game_config
{
int base_income = 2;
int village_income = 1;
int heal_amount = 4;
int cure_amount = 8;
int poison_amount= 8;
int rest_heal_amount= 2;
int recall_cost = 20;
int kill_experience = 8;
@ -97,8 +96,7 @@ namespace game_config
base_income = atoi(v["base_income"].c_str());
village_income = atoi(v["village_income"].c_str());
heal_amount = atoi(v["heal_amount"].c_str());
cure_amount = atoi(v["cure_amount"].c_str());
poison_amount = atoi(v["poison_amount"].c_str());
rest_heal_amount = atoi(v["rest_heal_amount"].c_str());
recall_cost = atoi(v["recall_cost"].c_str());
kill_experience = atoi(v["kill_experience"].c_str());

View file

@ -26,8 +26,7 @@ namespace game_config
{
extern int base_income;
extern int village_income;
extern int heal_amount;
extern int cure_amount;
extern int poison_amount;
extern int rest_heal_amount;
extern int recall_cost;
extern int kill_experience;

View file

@ -86,7 +86,7 @@ bool gamemap::is_village(gamemap::TERRAIN terrain) const
return get_terrain_info(terrain).is_village();
}
bool gamemap::gives_healing(gamemap::TERRAIN terrain) const
int gamemap::gives_healing(gamemap::TERRAIN terrain) const
{
return get_terrain_info(terrain).gives_healing();
}
@ -106,7 +106,7 @@ bool gamemap::is_village(const gamemap::location& loc) const
return on_board(loc) && is_village(get_terrain(loc));
}
bool gamemap::gives_healing(const gamemap::location& loc) const
int gamemap::gives_healing(const gamemap::location& loc) const
{
return on_board(loc) && gives_healing(get_terrain(loc));
}

View file

@ -107,12 +107,12 @@ public:
{ return underlying_union_terrain(get_terrain(loc)); }
bool is_village(TERRAIN terrain) const;
bool gives_healing(TERRAIN terrain) const;
int gives_healing(TERRAIN terrain) const;
bool is_castle(TERRAIN terrain) const;
bool is_keep(TERRAIN terrain) const;
bool is_village(const location& loc) const;
bool gives_healing(const location& loc) const;
int gives_healing(const location& loc) const;
bool is_castle(const location& loc) const;
bool is_keep(const location& loc) const;

View file

@ -14,6 +14,8 @@
#include "global.hpp"
#include "tstring.hpp"
#include "config.hpp"
#include "log.hpp"
#include "util.hpp"
#include "terrain.hpp"
#include <algorithm>
@ -68,7 +70,12 @@ terrain_type::terrain_type(const config& cfg)
light_modification_ = atoi(cfg["light"].c_str());
heals_ = cfg["heals"] == "true";
if (cfg["heals"] == "true") {
LOG_STREAM(err, config) << "terrain " << id() << " uses heals=true which is deprecated (use number)\n";
heals_ = 8;
} else {
heals_ = lexical_cast_default<int>(cfg["heals"], 0);
}
village_ = cfg["gives_income"] == "true";
castle_ = cfg["recruit_onto"] == "true";
keep_ = cfg["recruit_from"] == "true";
@ -130,7 +137,7 @@ double terrain_type::unit_submerge() const
return submerge_;
}
bool terrain_type::gives_healing() const
int terrain_type::gives_healing() const
{
return heals_;
}

View file

@ -44,7 +44,7 @@ public:
int unit_height_adjust() const;
double unit_submerge() const;
bool gives_healing() const;
int gives_healing() const;
bool is_village() const;
bool is_castle() const;
bool is_keep() const;
@ -66,9 +66,9 @@ private:
double submerge_;
int light_modification_;
int light_modification_, heals_;
bool heals_, village_, castle_, keep_;
bool village_, castle_, keep_;
};
void create_terrain_maps(const std::vector<config*>& cfgs,

View file

@ -526,11 +526,6 @@ bool unit::gets_hit(int damage)
return hitpoints_ <= 0;
}
void unit::heal()
{
heal(game_config::heal_amount);
}
void unit::heal(int amount)
{
int max_hp = max_hitpoints();

View file

@ -91,7 +91,6 @@ public:
bool is_resting() const;
bool gets_hit(int damage);
void heal();
void heal(int amount);
void heal_all();

View file

@ -603,7 +603,7 @@ void ability_filter::add_filters(const config* cfg)
unit_type::unit_type(const unit_type& o)
: variations_(o.variations_), cfg_(o.cfg_), race_(o.race_),
alpha_(o.alpha_), abilities_(o.abilities_),ability_tooltips_(o.ability_tooltips_),
heals_filter_(o.heals_filter_), heals_(o.heals_),
heals_(o.heals_), cures_(o.cures_),
regenerates_filter_(o.regenerates_filter_),regenerates_(o.regenerates_),
regeneration_(o.regeneration_),
leadership_filter_(o.leadership_filter_), leadership_(o.leadership_),
@ -708,6 +708,7 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
possibleTraits_.insert(possibleTraits_.end(),unit_traits.begin(),unit_traits.end());
heals_ = 0;
cures_ = false;
regenerates_ = false;
regeneration_ = 0;
steadfast_ = false;
@ -732,20 +733,21 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
if(!deprecated_abilities.empty()) {
LOG_STREAM(err, config) << "unit " << id() << " uses the ability=list tag, which is deprecated\n";
if(std::find(deprecated_abilities.begin(),deprecated_abilities.end(),"heals") != deprecated_abilities.end()) {
heals_ = game_config::heal_amount;
heals_filter_.unfilter();
heals_ = 4;
abilities_.push_back("heals");
ability_tooltips_.push_back("heals");
}
if(std::find(deprecated_abilities.begin(),deprecated_abilities.end(),"cures") != deprecated_abilities.end()) {
heals_ = game_config::cure_amount;
heals_filter_.unfilter();
heals_ = 8;
cures_ = true;
abilities_.push_back("heals");
ability_tooltips_.push_back("heals");
abilities_.push_back("cures");
ability_tooltips_.push_back("cures");
}
if(std::find(deprecated_abilities.begin(),deprecated_abilities.end(),"regenerates") != deprecated_abilities.end()) {
regenerates_ = true;
regeneration_ = game_config::cure_amount;
regeneration_ = 8;
regenerates_filter_.unfilter();
abilities_.push_back("regenerates");
ability_tooltips_.push_back("regenerates");
@ -809,10 +811,18 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
} else {
ability_tooltips_.push_back("heals");
}
heals_ = maximum<int>(heals_, lexical_cast_default<int>((**ab)["amount"],game_config::heal_amount));
heals_filter_.add_filters((*ab)->child("filter"));
if ((**ab)["amount"] == "")
LOG_STREAM(err, config) << "unit " << id() << " uses the [heals] tag without amount=\n";
heals_ = maximum<int>(heals_, lexical_cast<int>((**ab)["amount"]));
}
}
const config::child_list& cure_abilities = abil_cfg->get_children("cures");
if (!cure_abilities.empty()) {
abilities_.push_back("cures");
ability_tooltips_.push_back("cures");
cures_ = true;
}
const config::child_list& regenerate_abilities = abil_cfg->get_children("regenerates");
if (!regenerate_abilities.empty()) {
abilities_.push_back("regenerates");
@ -823,7 +833,9 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
ability_tooltips_.push_back("regenerates");
}
regenerates_ = true;
regeneration_ = maximum<int>(regeneration_, lexical_cast_default<int>((**ab)["amount"],game_config::cure_amount));
if ((**ab)["amount"] == "")
LOG_STREAM(err, config) << "unit " << id() << " uses the [regenerates] tag without amount=\n";
regeneration_ = maximum<int>(regeneration_, lexical_cast<int>((**ab)["amount"]));
regenerates_filter_.add_filters((*ab)->child("filter"));
}
}
@ -1294,6 +1306,11 @@ int unit_type::heals() const
return heals_;
}
bool unit_type::cures() const
{
return cures_;
}
bool unit_type::regenerates() const
{
return regenerates_;
@ -1397,10 +1414,6 @@ const std::string& unit_type::race() const
return race_->name();
}
const ability_filter unit_type::heals_filter() const
{
return heals_filter_;
}
const ability_filter unit_type::regenerates_filter() const
{
return regenerates_filter_;

View file

@ -217,6 +217,7 @@ public:
const std::vector<std::string>& ability_tooltips() const;
int heals() const;
bool cures() const;
bool regenerates() const;
int regenerate_amount() const;
bool is_leader() const;
@ -247,7 +248,6 @@ public:
const death_animation& die_animation(const attack_type* attack) const;
const movement_animation& move_animation(const std::string terrain,gamemap::location::DIRECTION) const;
const ability_filter heals_filter() const;
const ability_filter regenerates_filter() const;
const ability_filter leadership_filter() const;
const ability_filter illuminates_filter() const;
@ -275,8 +275,8 @@ private:
mutable std::string id_;
ability_filter heals_filter_;
int heals_;
bool cures_;
ability_filter regenerates_filter_;
bool regenerates_;