1 // Copyright (C) 2000, 2001, 2003 Michael Bartl 2 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz 3 // Copyright (C) 2004, 2005 Andrea Paternesi 4 // Copyright (C) 2007, 2008, 2011, 2014, 2015, 2017 Ben Asselstine 5 // Copyright (C) 2007, 2008 Ole Laursen 6 // 7 // This program is free software; you can redistribute it and/or modify 8 // it under the terms of the GNU General Public License as published by 9 // the Free Software Foundation; either version 3 of the License, or 10 // (at your option) any later version. 11 // 12 // This program is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU Library General Public License for more details. 16 // 17 // You should have received a copy of the GNU General Public License 18 // along with this program; if not, write to the Free Software 19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 // 02110-1301, USA. 21 22 #pragma once 23 #ifndef ARMY_H 24 #define ARMY_H 25 26 #include <gtkmm.h> 27 #include <sigc++/trackable.h> 28 #include <sigc++/signal.h> 29 30 #include "Ownable.h" 31 #include "armybase.h" 32 #include "UniquelyIdentified.h" 33 34 class Player; 35 class Temple; 36 class XML_Helper; 37 class ArmyProto; 38 class ArmyProdBase; 39 40 //! An instance of an Army unit, an Army unit type, or an Army production base. 41 /** 42 * This class is the atom of every army. It contains values such as 43 * strength, movement points, upkeep, and so on. 44 * 45 * The purpose of the Army class is three-fold; an Army class can hold a 46 * an Army prototype, or a production base, or an Army instance. 47 * 48 * The Army instance is the most frequently used purpose of the Army class. 49 * An Army instance has a unique Id among all other game objects, has an 50 * owner (Player), and is included in a Stack. 51 * 52 * The Army unit prototype purpose is the second-most frequently used 53 * purpose of the Army class. These types originate from a configuration 54 * file; for example: army/default/default.xml. Every Army unit type has an 55 * type value that makes it unique among all other Army unit types in an 56 * Armyset. 57 * 58 * The production base purpose refers to the Army units that are included 59 * in the City class as potential Army units that the City can produce. 60 * This purpose is exactly the same as the Army unit prototype purpose, 61 * except it knows which Armyset it comes from, and it knows which Army 62 * unit type it derives from. 63 * 64 * Maybe these three purposes will be split up into three or more classes 65 * in the future. 66 */ 67 class Army :public ArmyBase, public UniquelyIdentified, public Ownable, public sigc::trackable 68 { 69 public: 70 71 //! The xml tag of this object in a saved-game file. 72 static Glib::ustring d_tag; 73 74 //! Various kinds of statistics that an instance of Army unit has. 75 /** 76 * This enumeration assists in getting and setting of statistics in 77 * an instance of an Army unit. 78 */ 79 enum Stat { 80 //! How strong the Army unit is in battle. 81 STRENGTH = 0, 82 //! The maximum number of hitpoints that the Army unit can have. 83 HP = 3, 84 //! The maximum number of moves the Army unit has. 85 MOVES = 4, 86 //! The various Tile::Type that the Army moves efficiently in. 87 MOVE_BONUS = 5, 88 //! The special bonus the Army has (Army::Bonus). 89 ARMY_BONUS = 6, 90 //! How far the Army unit can see on a hidden map. 91 SIGHT = 7, 92 //! If the Army unit is in a boat or not. 93 SHIP = 8, 94 //! If the Army unit is having it's movement doubled/tripled or not. 95 MOVES_MULTIPLIER = 9, 96 //! If SHIP, then this is how strong the army is on a boat. 97 BOAT_STRENGTH = 10 98 }; 99 100 //! Copy constructor. 101 Army(const ArmyProdBase& armyprodbase, Player* owner = 0); 102 103 //! Copy constructor. 104 Army(const ArmyProto& armyproto, Player* owner = 0); 105 106 //! Copy constructor. 107 Army(const Army& army, Player *owner = 0); 108 109 /** 110 * Load an Army from an opened saved-game file or from an opened 111 * armyset configuration file. 112 * 113 * The constructor has to care for all three cases. Sometimes, an army 114 * prototype is loaded, from which other units are cloned, sometimes 115 * actual Army instances have to be loaded, and sometimes we load 116 * up a production base when loading the Army units that a City 117 * can produce. 118 * 119 * @param helper The opened saved-game file to load from. 120 */ 121 //! Loading constructor. 122 Army(XML_Helper* helper); 123 124 /** 125 * Creates an empty prototype Army unit. This constructor is only 126 * used in the ArmySetWindow (the Armyset editor). 127 */ 128 //! Create an empty army. 129 Army(); 130 131 //! Destructor. 132 virtual ~Army(); 133 134 static Army* createNonUniqueArmy(const ArmyProto& a, Player *p=NULL); 135 static Army* createNonUniqueArmy(const ArmyProdBase& a, Player *p=NULL); 136 137 138 // Set Methods 139 140 //! Set the Id of Armyset and type that this Army belongs to. 141 void setArmyset(guint32 armyset, guint32 type); 142 143 //! Change the armyset that the army type for this army belongs to. setArmyset(guint32 armyset_id)144 void setArmyset(guint32 armyset_id) {d_armyset = armyset_id;}; 145 146 //! Set an Army statistic. 147 void setStat(Stat stat, guint32 value); 148 149 //! Set the current number of hitpoints of this army. setHP(guint32 hp)150 void setHP(guint32 hp) {d_hp = hp;} 151 152 //! Set the current number of hitpoints of this army to zero. kill()153 void kill() {setHP(0);} 154 155 //! Sets whether or not the Army has a particular medal. setMedalBonus(guint32 index,bool value)156 void setMedalBonus(guint32 index, bool value) 157 {d_medal_bonus[index]=value;} 158 159 //! Sets the number of battles the Army unit participated in. setBattlesNumber(guint32 value)160 void setBattlesNumber(guint32 value) {d_battles_number=value;} 161 162 //! Sets the number of hits this Army unit has scored against a foe. setNumberHasHit(double value)163 void setNumberHasHit(double value) {d_number_hashit=value;} 164 165 //! Sets the number of hits this Army unit has suffered against a foe. setNumberHasBeenHit(double value)166 void setNumberHasBeenHit(double value) {d_number_hasbeenhit=value;} 167 168 //! Sets whether or not this Army unit is in a boat. 169 void setInShip (bool s); 170 171 //! Sets whether or not this Army unit is in a tower. 172 void setFortified (bool f); 173 174 // Get Methods 175 176 //! Get the Id of the Armyset to which the Army's type belongs. getArmyset()177 guint32 getArmyset() const {return d_armyset;} 178 179 //! Get the type of this army. 180 /** 181 * The type of the Army is the index of it's type in the Armyset. 182 */ getTypeId()183 guint32 getTypeId() const {return d_type_id;} 184 185 /** 186 * If modified is set to false, you get the raw, inherent value of 187 * the army. Set it to true to get the modified one. This is not 188 * important for generic armies, but heroes can have their stats 189 * modified by wearing items. 190 * 191 * @param stat The statistic to get the value of. 192 * @param modified Whether or not we get the modified stat value. 193 * 194 * @return The value of the statistic. 195 */ 196 //! Returns the value of the given stat for the Army. 197 virtual guint32 getStat(Stat stat, bool modified=true) const; 198 199 //! Get the current number of hitpoints that the Army has. getHP()200 guint32 getHP() const {return d_hp;} 201 202 //! Get the current number of movement points that the Army has. getMoves()203 guint32 getMoves() const {return d_moves;} 204 205 //! Get the current number of experience points that the Army unit has. getXP()206 double getXP() const {return d_xp;} 207 208 //! Get the current level of the Army. getLevel()209 guint32 getLevel() const {return d_level;} 210 211 //! Return which medals this Army unit has. getMedalBonuses()212 bool* getMedalBonuses() const {return (bool*)&d_medal_bonus;} 213 214 //! Return whether or not the Army has a particular medal. getMedalBonus(guint32 index)215 bool getMedalBonus(guint32 index) const {return d_medal_bonus[index];} 216 217 //! Returns the number of battles the Army unit participated in. getBattlesNumber()218 guint32 getBattlesNumber() const {return d_battles_number;} 219 220 //! Returns the number of blows the Army unit has scored against a foe. getNumberHasHit()221 double getNumberHasHit() const {return d_number_hashit;} 222 223 //! Returns the number of hits this Army unit has suffered. getNumberHasBeenHit()224 double getNumberHasBeenHit() const {return d_number_hasbeenhit;} 225 226 //! Return whether or not the Army is in a tower. 227 bool getFortified () const; 228 229 //! Is this army a hero? 230 /** 231 * isHero is overridden by the Hero class. 232 */ isHero()233 virtual bool isHero() const {return false;}; 234 235 //! This army is of an army type that can be awarded as a reward. 236 bool getAwardable() const; 237 238 //! This army is of an army type that can be the keeper in a ruin. 239 bool getDefendsRuins() const; 240 241 //! This army is of an army type that has this name. 242 virtual Glib::ustring getName() const; 243 244 //! Does this army unit have wings? 245 virtual bool isFlyer() const; 246 247 //Methods that operate on class data and modify the class data 248 /** 249 * Regenerate an amount of the Army unit's hitpoints but not 250 * exceeding the maximum number of hitpoints. 251 * 252 * @param hp The amount of hitpoints to heal. Set to zero for 253 * "natural" healing -- but this feature is not 254 * currently used because wounded army units are always 255 * fully healed after battle. 256 */ 257 //! Heal the Army unit. 258 void heal(guint32 hp = 0); 259 260 /** 261 * Decrease the number of hitpoints that this Army has. 262 * 263 * @param damageDone The amount of damage that the Army suffers. 264 * 265 * @return True if the Army unit has died, otherwise false. 266 */ 267 //! Damage the Army. 268 bool damage(guint32 damageDone); 269 270 /** 271 * Reduce the number of moves that the Army unit has. 272 * @note This method doesn't reduce the maximum number of movement 273 * points; it reduces the current number of movement points, which 274 * get restored at the start of the next turn. 275 * 276 * @param moves The number of movement points to consume. 277 */ 278 //! Consume some movement points. 279 void decrementMoves(guint32 moves); 280 281 /** 282 * Add to the number of moves that the Army unit has. 283 * @note This method doesn't increase the maximum number of movement 284 * points; it adds to the current number of movement points, which 285 * get restored at the start of the next turn. 286 * 287 * @param moves The number of movement points to add. 288 */ 289 //! Add some movement points. 290 void incrementMoves(guint32 moves); 291 292 //! Restores the number of movement points to the maximum level. 293 void resetMoves(); 294 295 /** 296 * Add 1 to the strength of the Army unit if it has not already 297 * visited the Temple at which it's parent stack is currently 298 * sitting on. 299 * 300 * @param temple The temple that the army is being blessed at. 301 * 302 * @return True if the Army unit was blessed, otherwise false. 303 */ 304 //! Bless the Army unit if it hasn't already visited this Temple. 305 bool bless(Temple *temple); 306 307 //! Increases the experience points of the Army by the given amount. 308 void gainXp(double n); 309 310 //! Make this army look and behave like another one. 311 void morph(const ArmyProto *armyproto); 312 313 //Methods that operate on class data and do not modify the class data 314 315 //! Returns whether or not the army was blessed at the given temple. 316 bool blessedAtTemple(guint32 temple_id) const; 317 318 //! Saves the Army to an opened saved-game file. 319 virtual bool save(XML_Helper* helper) const; 320 321 //signals 322 323 /** 324 * @note This signal is static because sometimes the army doesn't 325 * exist yet when the signal is connected. 326 * 327 * @param army The army that has died. 328 */ 329 //! Emitted when an Army has died. 330 static sigc::signal<void, Army*> sdying; 331 332 protected: 333 334 //! Generic method for saving Army data. Useful to the Hero class. 335 bool saveData(XML_Helper* helper) const; 336 337 //! The index of the Army unit's type in it's Armyset. 338 guint32 d_type_id; 339 340 //! The Id of the Armyset that the Army prototype belongs to. 341 guint32 d_armyset; 342 343 /** 344 * The maximum number of hitpoints is the secondmost important 345 * factor when calculating the outgoing of a Fight. 346 * 347 * This value should always be 2. 348 * 349 * This value does not change during gameplay. 350 */ 351 //! The maximum number of hitpoints this Army unit has. 352 guint32 d_max_hp; 353 354 //! Movement point multiplier of the Army unit. 355 /** 356 * If an Army unit is being affected by a Hero unit's Item that 357 * confers the Item::DOUBLEMOVESTACK Item::Bonus, the effect is 358 * stored in d_max_moves_multiplier. 359 * 360 * This value must be 1 or more. 361 * 362 * This value typically changes from 1 to 2, and back to 1 during 363 * gameplay. 364 */ 365 guint32 d_max_moves_multiplier; 366 367 //! Movement point bonus due to resting. 368 /** 369 * When an army unit doesn't use all of it's movement points in a 370 * turn, some of those points get held-over until the following turn. 371 * If a unit has 3 movement points remaining, the bonus is 2. If the 372 * unit has 2 movement points remaining, the bonus is 2. If the unit 373 * has 1 movement point remaining, the bonus is 1. 374 * 375 * This value is a number between 0 and 2. 376 */ 377 guint32 d_max_moves_rest_bonus; 378 379 /** 380 * Being in a ship affects the Army's strength in battle. 381 * Every army has a strength of 4 when fighting on a boat. 382 * It also affects the number of moves that the Army has. 383 * See MAX_BOAT_MOVES. 384 * 385 * This value gets set and unset as Army unit's stack goes in 386 * and out of the water. 387 */ 388 //! Whether or not this Army unit is afloat in a boat. 389 bool d_ship; 390 391 //! The current number of hitpoints that the Army unit has. 392 /** 393 * When this value is 0 it means the Army unit is dead. 394 * 395 * During a Fight this value gets decremented as the Army unit 396 * suffers attacks by enemy Army units. 397 * 398 * After a Fight, this value gets restored to d_max_hp. 399 * 400 * d_hp does not exceed d_max_hp. 401 */ 402 guint32 d_hp; 403 404 //! The current number of movement points that the Army unit has. 405 /** 406 * As the Army unit moves around in a Stack on the GameMap, it travels 407 * over certain terrain tiles. As the Army unit moves over a 408 * particular terrain Tile, d_moves dwindles in value. 409 * 410 * At the end of a round, this value gets restored to d_max_moves. 411 * 412 * d_moves does not exceed d_moves_hp. 413 */ 414 guint32 d_moves; 415 416 //! The current level of experience points the Army unit has. 417 /** 418 * This value increases as the Army unit assists in killing enemy 419 * Army units. This value does not decrease during gameplay. 420 * 421 * This value affects what d_level the Army unit is. 422 */ 423 double d_xp; 424 425 //! The experience level the Army unit has attained. 426 /** 427 * This value increases as the Army unit increases it's experience 428 * points. d_level increases when a multiple of Army::xp_per_level 429 * is surpassed. d_level does not decrease during gameplay. 430 * 431 * d_level is not factored into any calculations that affect the 432 * outcome of the game. It's just for show. 433 * 434 * @note Only Hero units advance in levels. 435 */ 436 guint32 d_level; 437 438 /** 439 * There are three different medals that an Army unit can win. 440 * 441 * Merciless Medal: medal for being extremely merciless. A unit 442 * gets this medal if in a combat it scores more 443 * than 90% of hits. 444 * Defender Medal: medal for being very good in defense. A unit 445 * gets this medal if in a combat is never hit. 446 * Veteran Medal: medal for being very good in combat. A unit gets 447 * this medal if it survives 10 battles. 448 * 449 * Medals do not affect the game outcome and are just for show. 450 */ 451 //! The medals that the Army unit has been given. 452 bool d_medal_bonus[3]; 453 454 //! The total number of battles that this Army unit has fought in. 455 /** 456 * d_battles_number is a counter that is used to know when to 457 * award the Veteran's medal to this Army unit. 458 * 459 * This value does not decrease during gameplay. 460 */ 461 guint32 d_battles_number; 462 463 //! The weighted number of hits per battle for this Army unit. 464 /** 465 * d_number_hashit is a counter that is used to know when to award 466 * the Merciless medal to this Army unit. 467 * 468 * This value does not decrease during gameplay. 469 */ 470 double d_number_hashit; 471 472 //! The weighted number of times the Army unit has been hit in a battle. 473 /** 474 * d_number_hasbeenhit is a counter that is used to know when to award 475 * the Defender medal to this Army unit. 476 * 477 * This value does not decrease during gameplay. 478 */ 479 double d_number_hasbeenhit; 480 481 //! A list of the Ids of Temples the Army unit has visited. 482 /** 483 * As the Army unit gets blessed at various Temple objects, this 484 * list grows with unique Temple Ids. 485 * The purpose of the list is to prevent the Army unit from being 486 * blessed at the same Temple more than once. 487 * 488 * The length of the list does not decrease during gameplay. 489 */ 490 std::list<guint32> d_visitedTemples; 491 492 //! The number of experience points per experience level. 493 /** 494 * When an Army unit's d_xp surpasses a multiple of xp_per_level, 495 * it increases it's d_level by 1. 496 */ 497 static const int xp_per_level = 10; 498 499 private: 500 501 //! Create an army with a non-unique id from an army prototype. 502 Army(const ArmyProto& a, guint32 id, Player *player = NULL); 503 //! Create an army with a non-unique id from an army production base. 504 Army(const ArmyProdBase& a, guint32 id, Player *player = NULL); 505 506 }; 507 508 #endif // ARMY_H 509