added turn-to-stone special weapon ability
attempt to fix STL-related compile error on Slackware
This commit is contained in:
parent
1ea1233dd7
commit
ae203d95cb
10 changed files with 65 additions and 39 deletions
|
@ -135,6 +135,7 @@ chaotic_description="Chaotic units fight better at night, and worse at day.
|
|||
Day: -25% Damage
|
||||
Night: +25% Damage"
|
||||
|
||||
stone_description="This unit has been turned to stone. It may not move or attack."
|
||||
invisible_description="This unit is invisible. It cannot be seen or attacked by enemy units."
|
||||
slowed_description="This unit has been slowed. It moves at half normal speed and receives one less attack than normal in combat."
|
||||
poisoned_description="This unit is poisoned. It will lose 8 HP every turn until it can seek a cure to the poison in a village or from a friendly unit with the 'cures' ability.
|
||||
|
@ -412,6 +413,7 @@ healthy="healthy"
|
|||
invisible="invisible"
|
||||
slowed="slowed"
|
||||
poisoned="poisoned"
|
||||
stone="stone"
|
||||
|
||||
short_range="melee"
|
||||
long_range="ranged"
|
||||
|
|
|
@ -169,16 +169,11 @@ battle_stats evaluate_battle_stats(
|
|||
attacker_terrain_override : map[attacker.x][attacker.y];
|
||||
const gamemap::TERRAIN defender_terrain = map[defender.x][defender.y];
|
||||
|
||||
res.chance_to_hit_attacker =
|
||||
a->second.defense_modifier(map,attacker_terrain);
|
||||
res.chance_to_hit_attacker = a->second.defense_modifier(map,attacker_terrain);
|
||||
res.chance_to_hit_defender = d->second.defense_modifier(map,defender_terrain);
|
||||
|
||||
res.chance_to_hit_defender =
|
||||
d->second.defense_modifier(map,defender_terrain);
|
||||
|
||||
const std::vector<attack_type>& attacker_attacks =
|
||||
a->second.attacks();
|
||||
const std::vector<attack_type>& defender_attacks =
|
||||
d->second.attacks();
|
||||
const std::vector<attack_type>& attacker_attacks = a->second.attacks();
|
||||
const std::vector<attack_type>& defender_attacks = d->second.attacks();
|
||||
|
||||
assert(attack_with >= 0 && attack_with < int(attacker_attacks.size()));
|
||||
const attack_type& attack = attacker_attacks[attack_with];
|
||||
|
@ -222,6 +217,11 @@ battle_stats evaluate_battle_stats(
|
|||
if(res.attack_special == "backstab" && !backstab)
|
||||
res.attack_special = "";
|
||||
|
||||
//the leader is immune to being turned to stone
|
||||
if(d->second.can_recruit() && res.attack_special == "stone") {
|
||||
res.attack_special = "";
|
||||
}
|
||||
|
||||
res.range = (attack.range() == attack_type::SHORT_RANGE ?
|
||||
"Melee" : "Ranged");
|
||||
}
|
||||
|
@ -269,6 +269,10 @@ battle_stats evaluate_battle_stats(
|
|||
if(include_strings) {
|
||||
res.defend_special = defender_attacks[defend].special();
|
||||
res.defend_icon = defender_attacks[defend].icon();
|
||||
|
||||
//leaders are immune to being turned to stone
|
||||
if(a->second.can_recruit() && res.defend_special == "stone")
|
||||
res.defend_special = "";
|
||||
}
|
||||
|
||||
//if the defender drains, and the attacker is a living creature, then
|
||||
|
@ -462,6 +466,15 @@ void attack(display& gui, const gamemap& map,
|
|||
if(stats.amount_attacker_drains > 0) {
|
||||
a->second.gets_hit(-stats.amount_attacker_drains);
|
||||
}
|
||||
|
||||
//if the defender is turned to stone, the fight stops immediately
|
||||
static const std::string stone_string("stone");
|
||||
if(stats.attack_special == stone_string) {
|
||||
d->second.set_flag("stone");
|
||||
stats.ndefends = 0;
|
||||
stats.nattacks = 0;
|
||||
game_events::fire("stone",d->first,a->first);
|
||||
}
|
||||
}
|
||||
|
||||
--stats.nattacks;
|
||||
|
@ -576,6 +589,15 @@ void attack(display& gui, const gamemap& map,
|
|||
if(stats.amount_defender_drains > 0) {
|
||||
d->second.gets_hit(-stats.amount_defender_drains);
|
||||
}
|
||||
|
||||
//if the attacker is turned to stone, the fight stops immediately
|
||||
static const std::string stone_string("stone");
|
||||
if(stats.defend_special == stone_string) {
|
||||
a->second.set_flag("stone");
|
||||
stats.ndefends = 0;
|
||||
stats.nattacks = 0;
|
||||
game_events::fire("stone",a->first,d->first);
|
||||
}
|
||||
}
|
||||
|
||||
--stats.ndefends;
|
||||
|
|
19
src/ai.cpp
19
src/ai.cpp
|
@ -165,6 +165,10 @@ void ai::calculate_possible_moves(std::map<location,paths>& res, move_map& srcds
|
|||
continue;
|
||||
}
|
||||
|
||||
if(!enemy && un_it->second.can_recruit()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//insert the trivial moves of staying on the same location
|
||||
if(un_it->second.movement_left() == un_it->second.total_movement()) {
|
||||
std::pair<location,location> trivial_mv(un_it->first,un_it->first);
|
||||
|
@ -204,8 +208,6 @@ void ai::do_move()
|
|||
|
||||
move_map srcdst, dstsrc, enemy_srcdst, enemy_dstsrc;
|
||||
|
||||
std::vector<gamemap::location> leader_locations;
|
||||
|
||||
calculate_possible_moves(possible_moves,srcdst,dstsrc,false);
|
||||
calculate_possible_moves(enemy_possible_moves,enemy_srcdst,enemy_dstsrc,true);
|
||||
|
||||
|
@ -417,18 +419,9 @@ void ai::do_move()
|
|||
already_done.insert(loc);
|
||||
}
|
||||
}
|
||||
|
||||
//mark the leader as having moved and attacked by now
|
||||
for(std::vector<location>::const_iterator lead = leader_locations.begin();
|
||||
lead != leader_locations.end(); ++lead) {
|
||||
//remove leader from further consideration
|
||||
srcdst.erase(*lead);
|
||||
dstsrc.erase(*lead);
|
||||
}
|
||||
|
||||
|
||||
//try to acquire towers
|
||||
for(std::multimap<location,location>::const_iterator i = dstsrc.begin();
|
||||
i != dstsrc.end(); ++i) {
|
||||
for(move_map::const_iterator i = dstsrc.begin(); i != dstsrc.end(); ++i) {
|
||||
if(map_.underlying_terrain(map_[i->first.x][i->first.y]) != gamemap::TOWER)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -421,8 +421,8 @@ std::vector<ai::attack_analysis> ai::analyze_targets(
|
|||
|
||||
for(unit_map::const_iterator j = units_.begin(); j != units_.end(); ++j) {
|
||||
|
||||
//attack anyone who is on the enemy side, and who is not invisible
|
||||
if(current_team().is_enemy(j->second.side()) &&
|
||||
//attack anyone who is on the enemy side, and who is not invisible or turned to stone
|
||||
if(current_team().is_enemy(j->second.side()) && j->second.stone() == false &&
|
||||
j->second.invisible(map_.underlying_terrain(map_[j->first.x][j->first.y]),
|
||||
state_.get_time_of_day().lawful_bonus,j->first,
|
||||
units_,teams_) == false) {
|
||||
|
|
|
@ -822,12 +822,9 @@ void display::draw_unit_details(int x, int y, const gamemap::location& loc,
|
|||
for(std::vector<attack_type>::const_iterator at_it = attacks.begin();
|
||||
at_it != attacks.end(); ++at_it) {
|
||||
|
||||
const std::string& lang_weapon
|
||||
= string_table["weapon_name_" + at_it->name()];
|
||||
const std::string& lang_type
|
||||
= string_table["weapon_type_" + at_it->type()];
|
||||
const std::string& lang_special
|
||||
= string_table["weapon_special_" + at_it->special()];
|
||||
const std::string& lang_weapon = string_table["weapon_name_" + at_it->name()];
|
||||
const std::string& lang_type = string_table["weapon_type_" + at_it->type()];
|
||||
const std::string& lang_special = string_table["weapon_special_" + at_it->special()];
|
||||
details << "\n"
|
||||
<< (lang_weapon.empty() ? at_it->name():lang_weapon) << " ("
|
||||
<< (lang_type.empty() ? at_it->type():lang_type) << ")\n"
|
||||
|
@ -1043,8 +1040,7 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
|
||||
overlaps.insert(overlaps.end(),adj.begin(),adj.end());
|
||||
|
||||
typedef std::multimap<gamemap::location,std::string>::const_iterator
|
||||
Itor;
|
||||
typedef std::multimap<gamemap::location,std::string>::const_iterator Itor;
|
||||
|
||||
for(std::pair<Itor,Itor> overlays =
|
||||
overlays_.equal_range(gamemap::location(x,y));
|
||||
|
@ -1106,7 +1102,7 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image_override,
|
|||
const unit_map::const_iterator it = units_.find(gamemap::location(x,y));
|
||||
if(it != units_.end()) {
|
||||
if(unit_image == NULL)
|
||||
unit_image.assign(image::get_image(it->second.image()));
|
||||
unit_image.assign(image::get_image(it->second.image(),it->second.stone() ? image::GREYED : image::SCALED));
|
||||
|
||||
const int unit_move = it->second.movement_left();
|
||||
const int unit_total_move = it->second.total_movement();
|
||||
|
@ -1482,7 +1478,8 @@ void display::draw_footstep(const gamemap::location& loc, int xloc, int yloc)
|
|||
SDL_Color text_colour = tile_is_light ? font::DARK_COLOUR : font::YELLOW_COLOUR;
|
||||
|
||||
const SDL_Rect& rect = map_area();
|
||||
const std::string str(1,'1' + route_.move_left);
|
||||
std::string str(1,'x');
|
||||
str[0] = '1' + route_.move_left;
|
||||
const SDL_Rect& text_area = font::draw_text(NULL,rect,18,text_colour,str,0,0);
|
||||
const int x = xloc + int(zoom_/2.0) - text_area.w/2;
|
||||
const int y = yloc + int(zoom_/2.0) - text_area.h/2;
|
||||
|
|
|
@ -131,7 +131,7 @@ bool enemy_zoc(const gamemap& map, const gamestatus& status,
|
|||
status.get_time_of_day().lawful_bonus,
|
||||
teams,current_team);
|
||||
if(it != units.end() && it->second.side() != side &&
|
||||
current_team.is_enemy(it->second.side())) {
|
||||
current_team.is_enemy(it->second.side()) && !it->second.stone()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -292,8 +292,7 @@ shortest_path_calculator::shortest_path_calculator(const unit& u, const team& t,
|
|||
{
|
||||
}
|
||||
|
||||
double shortest_path_calculator::cost(const gamemap::location& loc,
|
||||
double so_far) const
|
||||
double shortest_path_calculator::cost(const gamemap::location& loc, double so_far) const
|
||||
{
|
||||
if(!map_.on_board(loc) || team_.shrouded(loc.x,loc.y))
|
||||
return 100000.0;
|
||||
|
@ -314,7 +313,7 @@ double shortest_path_calculator::cost(const gamemap::location& loc,
|
|||
adj[i],map_,
|
||||
status_.get_time_of_day().lawful_bonus,teams_,team_);
|
||||
|
||||
if(u != units_.end() && team_.is_enemy(u->second.side()) && !team_.fogged(adj[i].x,adj[i].y)) {
|
||||
if(u != units_.end() && team_.is_enemy(u->second.side()) && !team_.fogged(adj[i].x,adj[i].y) && u->second.stone() == false) {
|
||||
return 100000.0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -701,7 +701,7 @@ void turn_info::show_attack_options(unit_map::const_iterator u)
|
|||
const int range = u->second.longest_range();
|
||||
for(unit_map::const_iterator target = units_.begin(); target != units_.end(); ++target) {
|
||||
if(current_team.is_enemy(target->second.side()) &&
|
||||
distance_between(target->first,u->first) <= range) {
|
||||
distance_between(target->first,u->first) <= range && !target->second.stone()) {
|
||||
current_paths_.routes[target->first] = paths::route();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,9 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
} else if(u->second.has_flag("poisoned")) {
|
||||
unit_status = "poisoned";
|
||||
prefix = font::BAD_TEXT;
|
||||
} else if(u->second.has_flag("stone")) {
|
||||
unit_status = "stone";
|
||||
prefix = font::BAD_TEXT;
|
||||
}
|
||||
|
||||
report res(prefix + string_table[unit_status]);
|
||||
|
|
|
@ -233,6 +233,9 @@ void unit::new_turn()
|
|||
set_flag("ambush");
|
||||
if(type().has_ability("nightstalk"))
|
||||
set_flag("nightstalk");
|
||||
|
||||
if(stone())
|
||||
set_attacked();
|
||||
}
|
||||
|
||||
void unit::end_turn()
|
||||
|
@ -354,6 +357,12 @@ bool unit::poisoned() const
|
|||
return has_flag(poisoned_str);
|
||||
}
|
||||
|
||||
bool unit::stone() const
|
||||
{
|
||||
static const std::string stone_str("stone");
|
||||
return has_flag(stone_str);
|
||||
}
|
||||
|
||||
bool unit::matches_filter(const config& cfg) const
|
||||
{
|
||||
const std::string& description = cfg["description"];
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
const gamemap::location loc,
|
||||
const unit_map& units,const std::vector<team>& teams) const;
|
||||
bool poisoned() const;
|
||||
bool stone() const;
|
||||
|
||||
bool matches_filter(const config& cfg) const;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue