00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef UNIT_TYPES_H_INCLUDED
00016 #define UNIT_TYPES_H_INCLUDED
00017
00018 #include "unit_animation.hpp"
00019 #include "portrait.hpp"
00020 #include "race.hpp"
00021
00022 class gamemap;
00023 class unit;
00024 class unit_ability_list;
00025 class unit_map;
00026 class unit_type_data;
00027
00028
00029
00030 class attack_type
00031 {
00032 public:
00033
00034 attack_type(const config& cfg);
00035
00036 ~attack_type();
00037 const t_string& name() const { return description_; }
00038 const std::string& id() const { return id_; }
00039 const std::string& type() const { return type_; }
00040 const std::string& icon() const { return icon_; }
00041 const std::string& range() const { return range_; }
00042 std::string accuracy_parry_description() const;
00043 int accuracy() const { return accuracy_; }
00044 int parry() const { return parry_; }
00045 int damage() const { return damage_; }
00046 int num_attacks() const { return num_attacks_; }
00047 double attack_weight() const { return attack_weight_; }
00048 double defense_weight() const { return defense_weight_; }
00049
00050 bool get_special_bool(const std::string& special,bool force=false) const;
00051 unit_ability_list get_specials(const std::string& special) const;
00052 std::vector<t_string> special_tooltips(bool force=false) const;
00053 std::string weapon_specials(bool force=false) const;
00054 void set_specials_context(const map_location& aloc,const map_location& dloc,
00055 const unit_map &unitmap, bool attacker, const attack_type *other_attack) const;
00056 void set_specials_context(const map_location& loc,const map_location& dloc, const unit& un, bool attacker =true) const;
00057
00058 bool matches_filter(const config& cfg,bool self=false) const;
00059 bool apply_modification(const config& cfg,std::string* description);
00060 bool describe_modification(const config& cfg,std::string* description);
00061
00062 int movement_used() const { return cfg_["movement_used"].to_int(100000); }
00063
00064 config& get_cfg() { return cfg_; }
00065 const config& get_cfg() const { return cfg_; }
00066 mutable map_location aloc_,dloc_;
00067 mutable bool attacker_;
00068 mutable const unit_map* unitmap_;
00069 mutable const attack_type* other_attack_;
00070
00071
00072
00073 bool special_active(const config& cfg, bool self) const;
00074 bool special_affects_opponent(const config& cfg) const;
00075 bool special_affects_self(const config& cfg) const;
00076
00077
00078
00079
00080 const unit_animation* animation(const display& disp, const map_location& loc,const unit* my_unit,const unit_animation::hit_type hit,const attack_type* secondary_attack,int swing_num,int damage) const;
00081 private:
00082 config cfg_;
00083 t_string description_;
00084 std::string id_;
00085 std::string type_;
00086 std::string icon_;
00087 std::string range_;
00088 int damage_;
00089 int num_attacks_;
00090 double attack_weight_;
00091 double defense_weight_;
00092
00093 int accuracy_;
00094 int parry_;
00095 };
00096
00097 class unit_movement_type;
00098
00099
00100
00101
00102
00103 struct defense_range
00104 {
00105 int min_, max_;
00106 };
00107
00108 typedef std::map<t_translation::t_terrain, defense_range> defense_cache;
00109
00110 const defense_range &defense_range_modifier_internal(defense_cache &defense_mods,
00111 const config &cfg, const unit_movement_type *parent,
00112 const gamemap &map, t_translation::t_terrain terrain, int recurse_count = 0);
00113
00114 int defense_modifier_internal(defense_cache &defense_mods,
00115 const config &cfg, const unit_movement_type *parent,
00116 const gamemap &map, t_translation::t_terrain terrain, int recurse_count = 0);
00117
00118 int movement_cost_internal(std::map<t_translation::t_terrain, int> &move_costs,
00119 const config &cfg, const unit_movement_type *parent,
00120 const gamemap &map, t_translation::t_terrain terrain, int recurse_count = 0);
00121
00122
00123
00124 class unit_movement_type
00125 {
00126 public:
00127
00128
00129
00130 static const int UNREACHABLE = 99;
00131
00132
00133
00134 unit_movement_type(const config& cfg, const unit_movement_type* parent=NULL);
00135 unit_movement_type();
00136
00137 std::string name() const;
00138 int movement_cost(const gamemap &map, t_translation::t_terrain terrain) const
00139 { return movement_cost_internal(moveCosts_, cfg_.child("movement_costs"), parent_, map, terrain); }
00140 int vision_cost(const gamemap &map, t_translation::t_terrain terrain) const
00141 { return movement_cost_internal(visionCosts_, cfg_.child("vision_costs"), parent_, map, terrain); }
00142 int defense_modifier(const gamemap &map, t_translation::t_terrain terrain) const
00143 { return defense_modifier_internal(defenseMods_, cfg_, parent_, map, terrain); }
00144 const defense_range &defense_range_modifier(const gamemap &map, t_translation::t_terrain terrain) const
00145 { return defense_range_modifier_internal(defenseMods_, cfg_, parent_, map, terrain); }
00146 int damage_against(const attack_type& attack) const { return resistance_against(attack); }
00147 int resistance_against(const attack_type& attack) const;
00148
00149 utils::string_map damage_table() const;
00150
00151 void set_parent(const unit_movement_type* parent) { parent_ = parent; }
00152
00153 bool is_flying() const;
00154
00155 const config& get_cfg() const { return cfg_; }
00156 const unit_movement_type* get_parent() const { return parent_; }
00157 private:
00158 mutable std::map<t_translation::t_terrain, int> moveCosts_;
00159 mutable std::map<t_translation::t_terrain, int> visionCosts_;
00160 mutable std::map<t_translation::t_terrain, int> jammingCosts_;
00161
00162 mutable defense_cache defenseMods_;
00163
00164 const unit_movement_type* parent_;
00165
00166 config cfg_;
00167 };
00168
00169 typedef std::map<std::string,unit_movement_type> movement_type_map;
00170
00171 class unit_type
00172 {
00173 public:
00174 friend class unit;
00175 friend class unit_type_data;
00176
00177
00178
00179
00180
00181
00182
00183 unit_type();
00184 unit_type(config &cfg);
00185 unit_type(const unit_type& o);
00186
00187 ~unit_type();
00188
00189
00190 void build_full(const movement_type_map &movement_types,
00191 const race_map &races, const config::const_child_itors &traits);
00192
00193 void build_help_index(const movement_type_map &movement_types,
00194 const race_map &races, const config::const_child_itors &traits);
00195
00196 void build_created(const movement_type_map &movement_types,
00197 const race_map &races, const config::const_child_itors &traits);
00198
00199
00200
00201
00202
00203 void add_advancement(const unit_type &advance_to,int experience);
00204
00205
00206
00207 std::set<std::string> advancement_tree() const;
00208
00209 const std::vector<std::string>& advances_to() const { return advances_to_; }
00210 const std::vector<std::string> advances_from() const;
00211
00212 config::const_child_itors modification_advancements() const
00213 { return cfg_.child_range("advancement"); }
00214
00215 const unit_type& get_gender_unit_type(std::string gender) const;
00216 const unit_type& get_gender_unit_type(unit_race::GENDER gender) const;
00217 const unit_type& get_variation(const std::string& name) const;
00218
00219 const std::string& undead_variation() const { return undead_variation_; }
00220
00221 unsigned int num_traits() const { return num_traits_; }
00222
00223
00224 const t_string& type_name() const { return type_name_; }
00225
00226 const std::string& id() const { return id_; }
00227
00228
00229 const t_string unit_description() const;
00230 int hitpoints() const { return hitpoints_; }
00231 int level() const { return level_; }
00232 int movement() const { return movement_; }
00233 int vision() const { return vision_; }
00234 int jamming() const {return jamming_; }
00235 int max_attacks() const { return max_attacks_; }
00236 int cost() const { return cost_; }
00237 const std::string& usage() const { return usage_; }
00238 const std::string& image() const { return image_; }
00239 const std::string& icon() const { return icon_; }
00240 const std::string &small_profile() const { return small_profile_; }
00241 const std::string &big_profile() const { return big_profile_; }
00242
00243 const std::vector<unit_animation>& animations() const;
00244
00245 const std::string& flag_rgb() const { return flag_rgb_; }
00246
00247 std::vector<attack_type> attacks() const;
00248 const unit_movement_type& movement_type() const { return movementType_; }
00249
00250 int experience_needed(bool with_acceleration=true) const;
00251
00252 struct experience_accelerator {
00253 experience_accelerator(int modifier);
00254 ~experience_accelerator();
00255 static int get_acceleration();
00256 private:
00257 int old_value_;
00258 };
00259
00260 enum ALIGNMENT { LAWFUL, NEUTRAL, CHAOTIC, LIMINAL };
00261
00262 ALIGNMENT alignment() const { return alignment_; }
00263 static const char* alignment_description(ALIGNMENT align, unit_race::GENDER gender = unit_race::MALE);
00264 static const char* alignment_id(ALIGNMENT align);
00265
00266 fixed_t alpha() const { return alpha_; }
00267
00268 const std::vector<t_string>& abilities() const { return abilities_; }
00269 const std::vector<t_string>& ability_tooltips() const { return ability_tooltips_; }
00270
00271
00272 const std::vector<t_string>& adv_abilities() const { return adv_abilities_; }
00273 const std::vector<t_string>& adv_ability_tooltips() const { return adv_ability_tooltips_; }
00274
00275 bool can_advance() const { return !advances_to_.empty(); }
00276
00277 bool not_living() const;
00278
00279 bool has_zoc() const { return zoc_; }
00280
00281 bool has_ability_by_id(const std::string& ability) const;
00282 std::vector<std::string> get_ability_list() const;
00283
00284 config::const_child_itors possible_traits() const
00285 { return possibleTraits_.child_range("trait"); }
00286 bool has_random_traits() const;
00287
00288 const std::vector<unit_race::GENDER>& genders() const { return genders_; }
00289
00290 const std::string race() const { return cfg_["race"]; }
00291 bool hide_help() const;
00292
00293 enum BUILD_STATUS {NOT_BUILT, CREATED, HELP_INDEX, WITHOUT_ANIMATIONS, FULL};
00294
00295 BUILD_STATUS build_status() const { return build_status_; }
00296
00297 const std::vector<tportrait>& portraits() const { return portraits_; }
00298
00299 const config &get_cfg() const { return cfg_; }
00300
00301 private:
00302 void operator=(const unit_type& o);
00303
00304 config &cfg_;
00305
00306 std::string id_;
00307 t_string type_name_;
00308 t_string description_;
00309 int hitpoints_;
00310 int level_;
00311 int movement_;
00312 int vision_;
00313 int jamming_;
00314 int max_attacks_;
00315 int cost_;
00316 std::string usage_;
00317 std::string undead_variation_;
00318
00319 std::string image_;
00320 std::string icon_;
00321 std::string small_profile_;
00322 std::string big_profile_;
00323 std::string flag_rgb_;
00324
00325 unsigned int num_traits_;
00326
00327 unit_type* gender_types_[2];
00328
00329 typedef std::map<std::string,unit_type*> variations_map;
00330 variations_map variations_;
00331
00332 const unit_race* race_;
00333
00334 fixed_t alpha_;
00335
00336 std::vector<t_string> abilities_, adv_abilities_;
00337 std::vector<t_string> ability_tooltips_, adv_ability_tooltips_;
00338
00339 bool zoc_, hide_help_;
00340
00341 std::vector<std::string> advances_to_;
00342 int experience_needed_;
00343 bool in_advancefrom_;
00344
00345
00346 ALIGNMENT alignment_;
00347
00348 unit_movement_type movementType_;
00349
00350 config possibleTraits_;
00351
00352 std::vector<unit_race::GENDER> genders_;
00353
00354
00355 mutable std::vector<unit_animation> animations_;
00356
00357 BUILD_STATUS build_status_;
00358
00359
00360 std::vector<tportrait> portraits_;
00361 };
00362
00363 class unit_type_data
00364 {
00365 public:
00366 unit_type_data();
00367
00368 typedef std::map<std::string,unit_type> unit_type_map;
00369
00370 const unit_type_map &types() const { return types_; }
00371 const race_map &races() const { return races_; }
00372 const config::const_child_itors traits() const { return unit_cfg_->child_range("trait"); }
00373 void set_config(config &cfg);
00374
00375 const unit_type *find(const std::string &key, unit_type::BUILD_STATUS status = unit_type::FULL) const;
00376 void check_types(const std::vector<std::string>& types) const;
00377 const unit_race *find_race(const std::string &) const;
00378
00379 void build_all(unit_type::BUILD_STATUS status);
00380
00381
00382 bool hide_help(const std::string &type_id, const std::string &race_id) const;
00383
00384 private:
00385 unit_type_data(const unit_type_data &);
00386
00387
00388 void read_hide_help(const config &cfg);
00389
00390 void set_unit_config(const config& unit_cfg) { unit_cfg_ = &unit_cfg; }
00391
00392 const config &find_config(const std::string &key) const;
00393 std::pair<unit_type_map::iterator, bool> insert(const std::pair<std::string, unit_type> &utype) { return types_.insert(utype); }
00394 void clear();
00395
00396 unit_type& build_unit_type(const unit_type_map::iterator &ut, unit_type::BUILD_STATUS status) const;
00397 void add_advancefrom(const config& unit_cfg) const;
00398 void add_advancement(unit_type& to_unit) const;
00399
00400 mutable unit_type_map types_;
00401 movement_type_map movement_types_;
00402 race_map races_;
00403
00404
00405 bool hide_help_all_;
00406
00407 std::vector< std::set<std::string> > hide_help_type_;
00408 std::vector< std::set<std::string> > hide_help_race_;
00409
00410 const config *unit_cfg_;
00411 unit_type::BUILD_STATUS build_status_;
00412 };
00413
00414 extern unit_type_data unit_types;
00415
00416 void adjust_profile(std::string &small, std::string &big, std::string const &def);
00417
00418 #endif