1 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2014, 2015, 2020 Ben Asselstine 2 // 3 // This program is free software; you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation; either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Library General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program; if not, write to the Free Software 15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 // 02110-1301, USA. 17 18 #pragma once 19 #ifndef ARMYSET_H 20 #define ARMYSET_H 21 22 #include <gtkmm.h> 23 #include <map> 24 #include <vector> 25 #include <sigc++/trackable.h> 26 27 #include "armyproto.h" 28 #include "set.h" 29 #include "hero.h" 30 31 //! A collection of Army prototype objects. 32 /** 33 * An Armyset is a complete set of Army prototype objects. An Army prototype 34 * is a kind of Army, as opposed to an Army unit instance (e.g. on the game 35 * map). See the Army class for more information about what an Army prototype 36 * is. The Armyset describes the size of the graphic tiles that each Army 37 * graphic occupies on the screen (Army::d_tilesize). 38 * There special images are kept with the Armyset: the ship picture, the 39 * planted standard picture, and the bag of items picture. 40 * 41 * The ship picture is what the Stack looks like when it is in a boat. 42 * The planted standard is what the player's standard looks like when it has 43 * been planted in the ground. The bag of items picture is what it looks like 44 * when a hero has dropped an item on the ground. 45 * 46 * Armysets are most often referred to by their Id (Armyset::d_id), but may 47 * sometimes be referred to by their name (Armyset::d_name) or basename 48 * name (Armyset::d_basename). 49 * 50 * Armyset objects are loaded from an armyset configuration file. 51 * 52 * Armyset objects are created by the armyset editor. 53 * 54 * Every Player has an Armyset that dictates the characteristics of the 55 * player's forces, but in practise there is only one Armyset per scenario. 56 * 57 * The armyset configuration file is a tar file that contains an XML file, 58 * and a set of png files. Filenames have the following form: 59 * army/${Armyset::d_basename}.lwa. 60 */ 61 class Armyset: public std::list<ArmyProto *>, public sigc::trackable, public Set 62 { 63 public: 64 65 //! The xml tag of this object in an armyset configuration file. 66 static Glib::ustring d_tag; 67 static Glib::ustring file_extension; 68 69 //! Default constructor. 70 /** 71 * Make a new Armyset. 72 * 73 * @param id The unique Id of this Armyset among all other Armyset 74 * objects. Must be more than 0. 75 * @param name The name of the Armyset. Analagous to Armyset::d_name. 76 */ 77 Armyset(guint32 id, Glib::ustring name); 78 //! Loading constructor. 79 /** 80 * Load armyset XML entities from armyset configuration files. 81 */ 82 Armyset(XML_Helper* helper, Glib::ustring directory); 83 84 //! Copy constructor. 85 Armyset(const Armyset& armyset); 86 87 static Armyset *create(Glib::ustring filename, bool &unsupported); 88 89 static Armyset *copy (const Armyset *orig); 90 91 //! Destructor. 92 ~Armyset(); 93 94 /** 95 * @param helper An opened armyset configuration file. 96 */ 97 //! Save the Armyset to an Armyset configuration file. 98 bool save(XML_Helper* helper) const; 99 100 bool save(Glib::ustring filename, Glib::ustring ext) const; 101 102 //! Get the image of the stack in a ship (minus the mask). getShipPic()103 PixMask* getShipPic() const {return d_ship;} 104 105 //! Set the image of the stack in a ship setShipImage(PixMask * ship)106 void setShipImage(PixMask* ship) {d_ship = ship;}; 107 108 //! Get the mask portion of the image of the stack in a ship. getShipMask()109 PixMask* getShipMask() const {return d_shipmask;} 110 111 //! Set the mask portion of the image of the stack in a ship. setShipMask(PixMask * shipmask)112 void setShipMask(PixMask* shipmask) {d_shipmask = shipmask;}; 113 114 //! Clear the ship name, pic, and mask 115 void clearShipImage (bool clear_name = true); 116 117 //! Instantiate the ship image by loading it from the lwa file. 118 bool instantiateShipImage (); 119 120 //! Get the image of the bag. getBagPic()121 PixMask* getBagPic() const {return d_bag;} 122 123 //! Set the image of the bag. setBagPic(PixMask * s)124 void setBagPic(PixMask* s) {d_bag = s;}; 125 126 //! Clear the bag name and pic 127 void clearBagImage (bool clear_name = true); 128 129 //! Instantiate the bag image by loading it from the lwa file. 130 bool instantiateBagImage (); 131 132 //! Get the image of the planted standard (minus the mask). getStandardPic()133 PixMask* getStandardPic() const {return d_standard;} 134 135 //! Set the image of the planted standard (minus the mask). setStandardPic(PixMask * s)136 void setStandardPic(PixMask* s) {d_standard = s;}; 137 138 //! Get the mask portion of the image of the planted standard. getStandardMask()139 PixMask* getStandardMask() const {return d_standard_mask;} 140 141 //! Set the mask portion of the image of the planted standard. setStandardMask(PixMask * s)142 void setStandardMask(PixMask* s) {d_standard_mask = s;}; 143 144 //! Clear the standard (hero's flag) name, pic and mask 145 void clearStandardImage (bool clear_name = true); 146 147 //! Instantiate the standard image by loading it from the lwa file. 148 bool instantiateStandardImage (); 149 150 //! Set the name of the file holding the image of the stack in a boat. setShipImageName(Glib::ustring n)151 void setShipImageName(Glib::ustring n) {d_stackship_name = n;}; 152 153 //! Get the name of the file holding the image of the stack in a boat. getShipImageName()154 Glib::ustring getShipImageName() {return d_stackship_name;}; 155 156 //! Set the name of the file holding the image of the hero's flag. setStandardImageName(Glib::ustring n)157 void setStandardImageName(Glib::ustring n) {d_standard_name = n;}; 158 159 //! Get the name of the file holding the image of the hero's flag. getStandardImageName()160 Glib::ustring getStandardImageName() {return d_standard_name;}; 161 162 //! Set the name of the file holding the image of the bag. setBagImageName(Glib::ustring n)163 void setBagImageName(Glib::ustring n) {d_bag_name = n;}; 164 165 //! Get the name of the file holding the image of the bag. getBagImageName()166 Glib::ustring getBagImageName() {return d_bag_name;}; 167 168 //! Find the type id with the highest value and return it. 169 guint32 getMaxId() const; 170 171 //! Find an army with a type in this armyset. 172 /** 173 * Scan the Army prototype objects in this Armyset and return it. 174 * 175 * @note This is only used for the editor. Most callers should use 176 * Armysetlist::getArmy instead. 177 * 178 * @param army_type The army type id of the Army prototype object 179 * to search for in this Armyset. 180 * 181 * @return The Army with the given army type id, or NULL if none 182 * could be found. 183 */ 184 ArmyProto * lookupArmyByType(guint32 army_type) const; 185 186 ArmyProto * lookupArmyByName(Glib::ustring name) const; 187 188 ArmyProto * lookupArmyByStrengthAndTurns(guint32 str, guint32 turns) const; 189 190 ArmyProto * lookupArmyByGender(Hero::Gender gender) const; 191 192 ArmyProto * lookupSimilarArmy(ArmyProto *army) const; 193 194 ArmyProto * lookupWeakestQuickestArmy() const; 195 196 //! can this armyset be used within the game? 197 bool validate(); 198 bool validateHero(); 199 bool validatePurchasables(); 200 bool validateRuinDefenders(); 201 bool validateAwardables(); 202 bool validateShip(); 203 bool validateStandard(); 204 bool validateBag(); 205 bool validateArmyUnitImages(); 206 bool validateArmyUnitImage(ArmyProto *a, Shield::Colour &c); 207 bool validateArmyUnitNames(); 208 bool validateArmyUnitName(ArmyProto *a); 209 bool validateArmyTypeIds(); 210 211 //! Load the images associated with this armyset. 212 /** 213 * Go get the image files from the armyset file and create the 214 * various pixmask objects. 215 * 216 * @param scale The images are clamped to the tile size or not. 217 * @param broken True when things went wrong reading the armyset file. 218 */ 219 void instantiateImages(bool scale, bool &broken); 220 void uninstantiateImages(); 221 void uninstantiateSameNamedImages (Glib::ustring name); 222 223 void loadStandardPic(Glib::ustring image_filename, bool scale, bool &broken); 224 void loadShipPic(Glib::ustring image_filename, bool scale, bool &broken); 225 void loadBagPic(Glib::ustring image_filename, bool &broken); 226 227 static void switchArmyset(Army *army, const Armyset *armyset); 228 static void switchArmyset(ArmyProdBase *army, const Armyset *armyset); 229 static void switchArmysetForRuinKeeper(Army *army, const Armyset *armyset); 230 const ArmyProto * getRandomRuinKeeper() const; 231 const ArmyProto *getRandomAwardableAlly() const; 232 233 //! Load the armyset again. 234 void reload(bool &broken); 235 bool calculate_preferred_tile_size(guint32 &ts) const; 236 237 //! callback to upgrade old files. 238 static bool upgrade(Glib::ustring filename, Glib::ustring old_version, Glib::ustring new_version); 239 static void support_backward_compatibility(); 240 241 static guint32 get_default_tile_size (); 242 private: 243 244 //! Callback function for the army tag (see XML_Helper) 245 bool loadArmyProto(Glib::ustring tag, XML_Helper* helper); 246 247 //! The unshaded picture of the stack when it's in a boat. 248 PixMask* d_ship; 249 250 //! The mask of what to shade with the player's colour on the boat. 251 PixMask* d_shipmask; 252 253 //! The unshaded picture of the planted standard. 254 PixMask* d_standard; 255 256 //! The mask of what to shade with the player's colour on the standard. 257 PixMask* d_standard_mask; 258 259 //! The picture of an item when it's lying on the ground. 260 PixMask *d_bag; 261 262 //! The name of the file that holds the picture of the hero's flag. 263 Glib::ustring d_standard_name; 264 265 //! The name of the file that holds the picture of stack on water. 266 Glib::ustring d_stackship_name; 267 268 //! The name of the file that holds the picture of the sack of items. 269 Glib::ustring d_bag_name; 270 }; 271 272 bool weakest_quickest (const ArmyProto* first, const ArmyProto* second); 273 #endif // ARMYSET_H 274 275