00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef UNIT_H_INCLUDED
00019 #define UNIT_H_INCLUDED
00020
00021 #include "boost/tuple/tuple.hpp"
00022 #include "formula_callable.hpp"
00023 #include "resources.hpp"
00024 #include "unit_types.hpp"
00025 #include "unit_map.hpp"
00026
00027 class display;
00028 class game_state;
00029 class vconfig;
00030 class team;
00031
00032 class unit_ability_list
00033 {
00034 public:
00035 unit_ability_list() :
00036 cfgs()
00037 {
00038 }
00039
00040 bool empty() const;
00041
00042 std::pair<int,map_location> highest(const std::string& key, int def=0) const;
00043 std::pair<int,map_location> lowest(const std::string& key, int def=0) const;
00044
00045 std::vector<std::pair<const config *, map_location> > cfgs;
00046 };
00047
00048
00049 class unit
00050 {
00051 public:
00052
00053
00054
00055
00056 static void clear_status_caches();
00057
00058 friend struct unit_movement_resetter;
00059
00060 unit(const unit& u);
00061
00062 unit(const config& cfg, bool use_traits = false, game_state *state = NULL, const vconfig* vcfg = NULL);
00063
00064
00065
00066
00067
00068 unit(const unit_type* t, int side, bool real_unit,
00069 unit_race::GENDER gender = unit_race::NUM_GENDERS);
00070 virtual ~unit();
00071 unit& operator=(const unit&);
00072
00073
00074
00075 void advance_to(const unit_type *t, bool use_traits = false,
00076 game_state *state = 0)
00077 {
00078 advance_to(cfg_, t, use_traits, state);
00079 }
00080 const std::vector<std::string>& advances_to() const { return advances_to_; }
00081 const std::vector<std::string> advances_to_translated() const;
00082 void set_advances_to(const std::vector<std::string>& advances_to);
00083
00084
00085 const std::string& type_id() const { return type_; }
00086 const unit_type* type() const;
00087
00088
00089 const std::string& id() const { if (id_.empty()) return type_name(); else return id_; }
00090
00091 size_t underlying_id() const { return underlying_id_; }
00092
00093
00094 const t_string& type_name() const {return type_name_;}
00095 const std::string& undead_variation() const {return undead_variation_;}
00096
00097
00098 const t_string &name() const { return name_; }
00099 void set_name(const t_string &name) { name_ = name; }
00100 void rename(const std::string& name) {if (!unrenamable_) name_= name;}
00101
00102
00103 std::string small_profile() const;
00104 std::string big_profile() const;
00105
00106 t_string unit_description() const { return cfg_["description"]; }
00107
00108 int hitpoints() const { return hit_points_; }
00109 int max_hitpoints() const { return max_hit_points_; }
00110 void set_hitpoints(int hp) { hit_points_ = hp; }
00111 int experience() const { return experience_; }
00112 int max_experience() const { return max_experience_; }
00113 void set_experience(int xp) { experience_ = xp; }
00114 int level() const { return level_; }
00115 void remove_movement_ai();
00116 void remove_attacks_ai();
00117
00118
00119
00120
00121
00122
00123 SDL_Color hp_color() const;
00124
00125
00126
00127
00128 SDL_Color hp_color(int hitpoints) const;
00129
00130 SDL_Color xp_color() const;
00131
00132 bool unrenamable() const { return unrenamable_; }
00133 int side() const { return side_; }
00134 std::string side_id() const;
00135 const std::string& team_color() const { return flag_rgb_; }
00136 unit_race::GENDER gender() const { return gender_; }
00137 void set_side(unsigned int new_side) { side_ = new_side; }
00138 fixed_t alpha() const { return alpha_; }
00139
00140 bool can_recruit() const { return canrecruit_; }
00141 const std::vector<std::string>& recruits() const
00142 { return recruit_list_; }
00143 void set_recruits(const std::vector<std::string>& recruits);
00144 const config& recall_filter() const { return filter_recall_; }
00145
00146 bool incapacitated() const { return get_state(STATE_PETRIFIED); }
00147 int total_movement() const { return max_movement_; }
00148 int movement_left() const { return (movement_ == 0 || incapacitated()) ? 0 : movement_; }
00149 int vision() const { return vision_ < 0 ? max_movement_ : vision_; }
00150 int jamming() const { return jamming_; }
00151 void set_hold_position(bool value) { hold_position_ = value; }
00152 bool hold_position() const { return hold_position_; }
00153 void set_user_end_turn(bool value=true) { end_turn_ = value; }
00154 bool user_end_turn() const { return end_turn_; }
00155 int attacks_left() const { return (attacks_left_ == 0 || incapacitated()) ? 0 : attacks_left_; }
00156 int max_attacks() const { return max_attacks_; }
00157 void set_movement(int moves);
00158 void set_attacks(int left) { attacks_left_ = std::max<int>(0, left); }
00159 void unit_hold_position() { hold_position_ = end_turn_ = true; }
00160 void new_turn();
00161 void end_turn();
00162 void new_scenario();
00163
00164 void refresh();
00165
00166 bool take_hit(int damage) { hit_points_ -= damage; return hit_points_ <= 0; }
00167 void heal(int amount);
00168 void heal_all() { hit_points_ = max_hitpoints(); }
00169 bool resting() const { return resting_; }
00170 void set_resting(bool rest) { resting_ = rest; }
00171
00172 const std::map<std::string,std::string> get_states() const;
00173 bool get_state(const std::string& state) const;
00174 void set_state(const std::string &state, bool value);
00175 enum state_t { STATE_SLOWED = 0, STATE_POISONED, STATE_PETRIFIED,
00176 STATE_UNCOVERED, STATE_NOT_MOVED, STATE_UNHEALABLE, STATE_GUARDIAN, STATE_UNKNOWN = -1 };
00177 void set_state(state_t state, bool value);
00178 bool get_state(state_t state) const;
00179 static state_t get_known_boolean_state_id(const std::string &state);
00180 static std::map<std::string, state_t> get_known_boolean_state_names();
00181
00182 bool has_moved() const { return movement_left() != total_movement(); }
00183 bool has_goto() const { return get_goto().valid(); }
00184 bool emits_zoc() const { return emit_zoc_ && !incapacitated();}
00185 bool matches_id(const std::string& unit_id) const;
00186
00187 bool matches_filter(const vconfig& cfg,const map_location& loc,bool use_flat_tod=false) const;
00188 const std::vector<std::string>& overlays() const { return overlays_; }
00189
00190 void write(config& cfg) const;
00191
00192 void set_role(const std::string& role) { role_ = role; }
00193 const std::string &get_role() const { return role_; }
00194
00195 const std::vector<attack_type>& attacks() const { return attacks_; }
00196 std::vector<attack_type>& attacks() { return attacks_; }
00197
00198 int damage_from(const attack_type& attack,bool attacker,const map_location& loc) const { return resistance_against(attack,attacker,loc); }
00199
00200
00201 const surface still_image(bool scaled = false) const;
00202
00203
00204 void redraw_unit();
00205
00206 void clear_haloes();
00207
00208 void set_standing(bool with_bars = true);
00209
00210 void set_ghosted(bool with_bars = true);
00211 void set_disabled_ghosted(bool with_bars = true);
00212
00213 void set_idling();
00214 void set_selecting();
00215 unit_animation* get_animation() { return anim_;};
00216 const unit_animation* get_animation() const { return anim_;};
00217 void set_facing(map_location::DIRECTION dir);
00218 map_location::DIRECTION facing() const { return facing_; }
00219
00220 bool invalidate(const map_location &loc);
00221 const std::vector<t_string>& trait_names() const { return trait_names_; }
00222 const std::vector<t_string>& trait_descriptions() const { return trait_descriptions_; }
00223 std::vector<std::string> get_traits_list() const;
00224
00225 int cost () const { return unit_value_; }
00226
00227 const map_location &get_location() const { return loc_; }
00228
00229 void set_location(const map_location &loc) { loc_ = loc; }
00230
00231 const map_location& get_goto() const { return goto_; }
00232 void set_goto(const map_location& new_goto) { goto_ = new_goto; }
00233
00234 int upkeep() const;
00235 bool loyal() const;
00236
00237 void set_hidden(bool state);
00238 bool get_hidden() const { return hidden_; }
00239 bool is_flying() const { return flying_; }
00240 bool is_fearless() const { return is_fearless_; }
00241 bool is_healthy() const { return is_healthy_; }
00242 int movement_cost(const t_translation::t_terrain terrain) const;
00243 int vision_cost(const t_translation::t_terrain terrain) const;
00244 int jamming_cost(const t_translation::t_terrain terrain) const;
00245 int defense_modifier(t_translation::t_terrain terrain) const;
00246 int resistance_against(const std::string& damage_name,bool attacker,const map_location& loc) const;
00247 int resistance_against(const attack_type& damage_type,bool attacker,const map_location& loc) const
00248 {return resistance_against(damage_type.type(), attacker, loc);};
00249
00250
00251 utils::string_map get_base_resistances() const;
00252
00253
00254 bool can_advance() const { return advances_to_.empty()==false || get_modification_advances().empty() == false; }
00255 bool advances() const { return experience_ >= max_experience() && can_advance(); }
00256
00257 std::map<std::string,std::string> advancement_icons() const;
00258 std::vector<std::pair<std::string,std::string> > amla_icons() const;
00259
00260 std::vector<config> get_modification_advances() const;
00261 config::const_child_itors modification_advancements() const
00262 { return cfg_.child_range("advancement"); }
00263
00264 size_t modification_count(const std::string& type, const std::string& id) const;
00265
00266 void add_modification(const std::string& type, const config& modification,
00267 bool no_add=false);
00268
00269 bool move_interrupted() const { return movement_left() > 0 && interrupted_move_.x >= 0 && interrupted_move_.y >= 0; }
00270 const map_location& get_interrupted_move() const { return interrupted_move_; }
00271 void set_interrupted_move(const map_location& interrupted_move) { interrupted_move_ = interrupted_move; }
00272
00273
00274 enum STATE {
00275 STATE_STANDING,
00276 STATE_FORGET,
00277 STATE_ANIM};
00278 void start_animation(int start_time, const unit_animation *animation,
00279 bool with_bars, const std::string &text = "",
00280 Uint32 text_color = 0, STATE state = STATE_ANIM);
00281
00282
00283 std::string absolute_image() const;
00284 std::string image_halo() const { return cfg_["halo"]; }
00285
00286 std::string image_ellipse() const { return cfg_["ellipse"]; }
00287
00288 config &variables() { return variables_; }
00289 const config &variables() const { return variables_; }
00290
00291 std::string usage() const { return cfg_["usage"]; }
00292 unit_type::ALIGNMENT alignment() const { return alignment_; }
00293 const unit_race* race() const { return race_; }
00294
00295 const unit_animation* choose_animation(const display& disp,
00296 const map_location& loc, const std::string& event,
00297 const map_location& second_loc = map_location::null_location,
00298 const int damage=0,
00299 const unit_animation::hit_type hit_type = unit_animation::INVALID,
00300 const attack_type* attack=NULL,const attack_type* second_attack = NULL,
00301 int swing_num =0) const;
00302
00303
00304
00305
00306
00307 bool get_ability_bool(const std::string& tag_name, const map_location& loc) const;
00308
00309
00310
00311
00312 bool get_ability_bool(const std::string &tag_name) const
00313 { return get_ability_bool(tag_name, loc_); }
00314 unit_ability_list get_abilities(const std::string &tag_name, const map_location& loc) const;
00315 unit_ability_list get_abilities(const std::string &tag_name) const
00316 { return get_abilities(tag_name, loc_); }
00317
00318 std::vector<boost::tuple<t_string,t_string,t_string> > ability_tooltips(bool force_active = false) const;
00319 std::vector<std::string> get_ability_list() const;
00320 bool has_ability_type(const std::string& ability) const;
00321
00322 const game_logic::map_formula_callable_ptr& formula_vars() const { return formula_vars_; }
00323 void add_formula_var(std::string str, variant var);
00324 bool has_formula() const { return !unit_formula_.empty(); }
00325 bool has_loop_formula() const { return !unit_loop_formula_.empty(); }
00326 bool has_priority_formula() const { return !unit_priority_formula_.empty(); }
00327 const std::string& get_formula() const { return unit_formula_; }
00328 const std::string& get_loop_formula() const { return unit_loop_formula_; }
00329 const std::string& get_priority_formula() const { return unit_priority_formula_; }
00330
00331 void backup_state();
00332 void apply_modifications();
00333 void generate_traits(bool musthaveonly=false, game_state* state = 0);
00334 void generate_name(rand_rng::simple_rng *rng = 0);
00335
00336
00337 bool invisible(const map_location& loc, bool see_all=true) const;
00338
00339 bool is_visible_to_team(team const& team, bool const see_all = true, gamemap const& map = *resources::game_map) const;
00340
00341
00342
00343
00344 unit& clone(bool is_temporary=true);
00345
00346 std::string TC_image_mods() const;
00347 const std::string& effect_image_mods() const;
00348 std::string image_mods() const;
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 const tportrait* portrait(
00360 const unsigned size, const tportrait::tside side) const;
00361
00362 private:
00363 void advance_to(const config &old_cfg, const unit_type *t,
00364 bool use_traits, game_state *state);
00365
00366 bool internal_matches_filter(const vconfig& cfg,const map_location& loc,
00367 bool use_flat_tod) const;
00368
00369
00370
00371 bool ability_active(const std::string& ability,const config& cfg,const map_location& loc) const;
00372 bool ability_affects_adjacent(const std::string& ability,const config& cfg,int dir,const map_location& loc) const;
00373 bool ability_affects_self(const std::string& ability,const config& cfg,const map_location& loc) const;
00374 bool resistance_filter_matches(const config& cfg,bool attacker,const std::string& damage_name, int res) const;
00375
00376 bool has_ability_by_id(const std::string& ability) const;
00377 void remove_ability_by_id(const std::string& ability);
00378
00379
00380 void add_trait_description(const config& trait, const t_string& description);
00381
00382 void set_underlying_id();
00383
00384 config cfg_;
00385 map_location loc_;
00386
00387 std::vector<std::string> advances_to_;
00388 std::string type_;
00389 const unit_race* race_;
00390 std::string id_;
00391 t_string name_;
00392 size_t underlying_id_;
00393 t_string type_name_;
00394 std::string undead_variation_;
00395 std::string variation_;
00396
00397 int hit_points_;
00398 int max_hit_points_;
00399 int experience_;
00400 int max_experience_;
00401 int level_;
00402 bool canrecruit_;
00403 std::vector<std::string> recruit_list_;
00404 unit_type::ALIGNMENT alignment_;
00405 std::string flag_rgb_;
00406 std::string image_mods_;
00407
00408 bool unrenamable_;
00409 int side_;
00410 const unit_race::GENDER gender_;
00411
00412 fixed_t alpha_;
00413
00414 std::string unit_formula_;
00415 std::string unit_loop_formula_;
00416 std::string unit_priority_formula_;
00417 game_logic::map_formula_callable_ptr formula_vars_;
00418
00419 int movement_;
00420 int max_movement_;
00421 mutable std::map<t_translation::t_terrain, int> movement_costs_;
00422 int vision_;
00423 mutable std::map<t_translation::t_terrain, int> vision_costs_;
00424 int jamming_;
00425 mutable std::map<t_translation::t_terrain, int> jamming_costs_;
00426 mutable defense_cache defense_mods_;
00427 bool hold_position_;
00428 bool end_turn_;
00429 bool resting_;
00430 int attacks_left_;
00431 int max_attacks_;
00432
00433 std::set<std::string> states_;
00434 std::vector<bool> known_boolean_states_;
00435 static std::map<std::string, state_t> known_boolean_state_names_;
00436 config variables_;
00437 config events_;
00438 config filter_recall_;
00439 bool emit_zoc_;
00440 STATE state_;
00441
00442 std::vector<std::string> overlays_;
00443
00444 std::string role_;
00445 std::vector<attack_type> attacks_;
00446 map_location::DIRECTION facing_;
00447
00448 std::vector<t_string> trait_names_;
00449 std::vector<t_string> trait_descriptions_;
00450
00451 int unit_value_;
00452 map_location goto_, interrupted_move_;
00453
00454 bool flying_, is_fearless_, is_healthy_;
00455
00456 utils::string_map modification_descriptions_;
00457
00458 std::vector<unit_animation> animations_;
00459
00460 unit_animation *anim_;
00461 int next_idling_;
00462 int frame_begin_time_;
00463
00464
00465 int unit_halo_;
00466 bool getsHit_;
00467 bool refreshing_;
00468 bool hidden_;
00469 bool draw_bars_;
00470
00471 config modifications_;
00472
00473 friend void attack_type::set_specials_context(const map_location& loc, const map_location&, const unit& un, bool) const;
00474
00475
00476 mutable std::map<map_location, bool> invisibility_cache_;
00477
00478
00479
00480
00481
00482
00483
00484 void clear_visibility_cache() const { invisibility_cache_.clear(); }
00485 };
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 struct unit_movement_resetter
00496 : private boost::noncopyable
00497 {
00498 unit_movement_resetter(unit& u, bool operate=true);
00499 ~unit_movement_resetter();
00500
00501 private:
00502 unit& u_;
00503 int moves_;
00504 };
00505
00506
00507 std::vector<unit>::iterator find_if_matches_id(
00508 std::vector<unit> &unit_list,
00509 const std::string &unit_id);
00510
00511 std::vector<unit>::const_iterator find_if_matches_id(
00512 const std::vector<unit> &unit_list,
00513 const std::string &unit_id);
00514
00515 std::vector<unit>::iterator erase_if_matches_id(
00516 std::vector<unit> &unit_list,
00517 const std::string &unit_id);
00518
00519
00520 int side_units(int side_num);
00521
00522
00523 int side_units_cost(int side_num);
00524
00525 int side_upkeep(int side_num);
00526
00527 unit_map::iterator find_visible_unit(const map_location &loc,
00528 const team ¤t_team, bool see_all = false);
00529
00530 unit *get_visible_unit(const map_location &loc,
00531 const team ¤t_team, bool see_all = false);
00532
00533 struct team_data
00534 {
00535 team_data() :
00536 units(0),
00537 upkeep(0),
00538 villages(0),
00539 expenses(0),
00540 net_income(0),
00541 gold(0),
00542 teamname()
00543 {
00544 }
00545
00546 int units, upkeep, villages, expenses, net_income, gold;
00547 std::string teamname;
00548 };
00549
00550 team_data calculate_team_data(const class team& tm, int side);
00551
00552
00553
00554
00555
00556
00557 struct temporary_unit_placer
00558 {
00559 temporary_unit_placer(unit_map& m, const map_location& loc, unit& u);
00560 virtual ~temporary_unit_placer();
00561
00562 private:
00563 unit_map& m_;
00564 const map_location loc_;
00565 unit *temp_;
00566 };
00567
00568
00569
00570
00571
00572
00573
00574 struct temporary_unit_remover
00575 {
00576 temporary_unit_remover(unit_map& m, const map_location& loc);
00577 virtual ~temporary_unit_remover();
00578
00579 private:
00580 unit_map& m_;
00581 const map_location loc_;
00582 unit *temp_;
00583 };
00584
00585
00586
00587
00588
00589
00590
00591 struct temporary_unit_mover
00592 {
00593 temporary_unit_mover(unit_map& m, const map_location& src, const map_location& dst);
00594 virtual ~temporary_unit_mover();
00595
00596 private:
00597 unit_map& m_;
00598 const map_location src_;
00599 const map_location dst_;
00600 unit *temp_;
00601 };
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 std::string get_checksum(const unit& u);
00615
00616 #endif