1 /* 2 * Copyright (C) 2002-2020 by the Widelands Development Team 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * 18 */ 19 20 #ifndef WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_H 21 #define WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_H 22 23 #include "ai/ai_hints.h" 24 #include "base/macros.h" 25 #include "logic/map_objects/buildcost.h" 26 #include "logic/map_objects/immovable.h" 27 #include "logic/map_objects/tribes/attack_target.h" 28 #include "logic/map_objects/tribes/building_settings.h" 29 #include "logic/map_objects/tribes/soldiercontrol.h" 30 #include "logic/map_objects/tribes/wareworker.h" 31 #include "logic/map_objects/tribes/workarea_info.h" 32 #include "logic/message.h" 33 #include "scripting/lua_table.h" 34 35 namespace Widelands { 36 37 class InputQueue; 38 39 constexpr int32_t kPriorityLow = 2; 40 constexpr int32_t kPriorityNormal = 4; 41 constexpr int32_t kPriorityHigh = 8; 42 43 /* The value "" means that the DescriptionIndex is a normal building, as happens e.g. when enhancing 44 * a building. The value "tribe"/"world" means that the DescriptionIndex refers to an immovable of 45 * OwnerType kTribe/kWorld, as happens e.g. with amazon treetop sentry. This immovable 46 * should therefore always be painted below the building image. 47 */ 48 using FormerBuildings = std::vector<std::pair<DescriptionIndex, std::string>>; 49 50 /* 51 * Common to all buildings! 52 */ 53 class BuildingDescr : public MapObjectDescr { 54 public: 55 BuildingDescr(const std::string& init_descname, 56 MapObjectType type, 57 const LuaTable& t, 58 const Tribes& tribes); ~BuildingDescr()59 ~BuildingDescr() override { 60 } 61 is_buildable()62 bool is_buildable() const { 63 return buildable_; 64 } can_be_dismantled()65 bool can_be_dismantled() const { 66 return can_be_dismantled_; 67 } is_destructible()68 bool is_destructible() const { 69 return destructible_; 70 } is_enhanced()71 bool is_enhanced() const { 72 return enhanced_building_; 73 } 74 75 /** 76 * The build cost for direct construction 77 */ buildcost()78 const Buildcost& buildcost() const { 79 return buildcost_; 80 } 81 82 /** 83 * Returned wares for dismantling 84 */ returned_wares()85 const Buildcost& returned_wares() const { 86 return return_dismantle_; 87 } 88 89 /** 90 * The build cost for enhancing a previous building 91 */ enhancement_cost()92 const Buildcost& enhancement_cost() const { 93 return enhance_cost_; 94 } 95 96 /** 97 * The returned wares for a enhaced building 98 */ returned_wares_enhanced()99 const Buildcost& returned_wares_enhanced() const { 100 return return_enhanced_; 101 } 102 get_size()103 int32_t get_size() const { 104 return size_; 105 } get_ismine()106 bool get_ismine() const { 107 return mine_; 108 } get_isport()109 bool get_isport() const { 110 return port_; 111 } needs_seafaring()112 bool needs_seafaring() const { 113 return needs_seafaring_; 114 } needs_waterways()115 bool needs_waterways() const { 116 return needs_waterways_; 117 } 118 119 bool is_useful_on_map(bool seafaring_allowed, bool waterways_allowed) const; 120 121 // Returns the enhancement this building can become or 122 // INVALID_INDEX if it cannot be enhanced. enhancement()123 const DescriptionIndex& enhancement() const { 124 return enhancement_; 125 } 126 // Returns the building from which this building can be enhanced or 127 // INVALID_INDEX if it cannot be built as an enhanced building. enhanced_from()128 const DescriptionIndex& enhanced_from() const { 129 return enhanced_from_; 130 } set_enhanced_from(const DescriptionIndex & index)131 void set_enhanced_from(const DescriptionIndex& index) { 132 enhanced_from_ = index; 133 } 134 135 /// Create a building of this type in the game. Calls init, which does 136 /// different things for different types of buildings (such as conquering 137 /// land and requesting things). Therefore this must not be used to allocate 138 /// a building during savegame loading. (It would cause many bugs.) 139 /// 140 /// Does not perform any sanity checks. 141 /// If former_buildings is not empty this is an enhancing. 142 Building& create(EditorGameBase&, 143 Player*, 144 Coords, 145 bool construct, 146 bool loading = false, 147 FormerBuildings former_buildings = FormerBuildings()) const; 148 149 virtual uint32_t get_conquers() const; 150 virtual uint32_t vision_range() const; 151 workarea_info()152 const WorkareaInfo& workarea_info() const { 153 return workarea_info_; 154 } 155 156 // TODO(sirver): This should not be public. It is mutated by other classes 157 // in many places. 158 WorkareaInfo workarea_info_; 159 160 bool suitability(const Map&, const FCoords&) const; 161 const BuildingHints& hints() const; 162 void set_hints_trainingsites_max_percent(int percent); 163 164 uint32_t get_unoccupied_animation() const; 165 get_built_over_immovable()166 DescriptionIndex get_built_over_immovable() const { 167 return built_over_immovable_; 168 } 169 170 protected: 171 virtual Building& create_object() const = 0; 172 Building& create_constructionsite() const; 173 174 private: 175 const Tribes& tribes_; 176 const bool buildable_; // the player can build this himself 177 const bool can_be_dismantled_; // the player can dismantle this building 178 const bool destructible_; // the player can destruct this himself 179 Buildcost buildcost_; 180 Buildcost return_dismantle_; // Returned wares on dismantle 181 Buildcost enhance_cost_; // cost for enhancing 182 Buildcost return_enhanced_; // Returned ware for dismantling an enhanced building 183 int32_t size_; // size of the building 184 bool mine_; 185 bool port_; 186 bool needs_seafaring_; // This building should only be built on seafaring maps. 187 bool needs_waterways_; // This building should only be built on maps with waterways/ferries 188 // enabled 189 DescriptionIndex enhancement_; 190 DescriptionIndex 191 enhanced_from_; // The building this building was enhanced from, or INVALID_INDEX 192 bool enhanced_building_; // if it is one, it is bulldozable 193 BuildingHints hints_; // hints (knowledge) for computer players 194 DescriptionIndex built_over_immovable_; // can be built only on nodes where an immovable with 195 // this attribute stands 196 197 // for migration, 0 is the default, meaning get_conquers() + 4 198 uint32_t vision_range_; 199 DISALLOW_COPY_AND_ASSIGN(BuildingDescr); 200 }; 201 202 struct NoteBuilding { 203 CAN_BE_SENT_AS_NOTE(NoteId::Building) 204 205 Serial serial; 206 207 enum class Action { kChanged, kStartWarp, kFinishWarp, kWorkersChanged }; 208 const Action action; 209 NoteBuildingNoteBuilding210 NoteBuilding(Serial init_serial, const Action& init_action) 211 : serial(init_serial), action(init_action) { 212 } 213 }; 214 215 class Building : public PlayerImmovable { 216 friend class BuildingDescr; 217 friend class MapBuildingdataPacket; 218 219 MO_DESCR(BuildingDescr) 220 221 public: 222 // Player capabilities: which commands can a player issue for this building? 223 enum { 224 PCap_Bulldoze = 1, // can bulldoze/remove this buildings 225 PCap_Dismantle = 1 << 1, // can dismantle this buildings 226 PCap_Enhancable = 1 << 2, // can be enhanced to something 227 }; 228 229 public: 230 enum class InfoStringFormat { kCensus, kStatistics, kTooltip }; 231 232 explicit Building(const BuildingDescr&); 233 234 void load_finish(EditorGameBase&) override; 235 236 int32_t get_size() const override; 237 bool get_passable() const override; 238 239 Flag& base_flag() override; 240 virtual uint32_t get_playercaps() const; 241 get_position()242 virtual Coords get_position() const { 243 return position_; 244 } 245 PositionList get_positions(const EditorGameBase&) const override; 246 247 std::string info_string(const InfoStringFormat& format); 248 249 // Return the overlay string that is displayed on the map view when enabled 250 // by the player. update_and_get_statistics_string()251 const std::string& update_and_get_statistics_string() { 252 update_statistics_string(&statistics_string_); 253 return statistics_string_; 254 } 255 256 /// \returns the queue for the matching ware or worker type or \throws WException. 257 virtual InputQueue& inputqueue(DescriptionIndex, WareWorker); 258 259 virtual bool burn_on_destroy(); 260 void destroy(EditorGameBase&) override; 261 262 virtual bool fetch_from_flag(Game&); 263 virtual bool get_building_work(Game&, Worker&, bool success); 264 265 bool leave_check_and_wait(Game&, Worker&); 266 void leave_skip(Game&, Worker&); 267 268 // Get/Set the priority for this waretype for this building. 'type' defines 269 // if this is for a worker or a ware, 'index' is the type of worker or ware. 270 // If 'adjust' is false, the three possible states kPriorityHigh, 271 // kPriorityNormal and kPriorityLow are returned, otherwise numerical 272 // values adjusted to the preciousness of the ware in general are returned. 273 virtual int32_t get_priority(WareWorker type, DescriptionIndex, bool adjust = true) const; 274 void set_priority(int32_t type, DescriptionIndex ware_index, int32_t new_priority); 275 276 void collect_priorities(std::map<int32_t, std::map<DescriptionIndex, int32_t>>& p) const; 277 278 /** 279 * The former buildings vector keeps track of all former buildings 280 * that have been enhanced up to the current one. The current building 281 * index will be in the last position. For construction sites, it is 282 * empty except enhancements. For a dismantle site, the last item will 283 * be the one being dismantled. 284 */ get_former_buildings()285 const FormerBuildings get_former_buildings() { 286 return old_buildings_; 287 } 288 289 void log_general_info(const EditorGameBase&) const override; 290 291 // Use on training sites only. change_train_priority(uint32_t,int32_t)292 virtual void change_train_priority(uint32_t, int32_t) { 293 } switch_train_mode()294 virtual void switch_train_mode() { 295 } 296 297 /// Stores the PlayerNumber of the player who has defeated this building. set_defeating_player(PlayerNumber const player_number)298 void set_defeating_player(PlayerNumber const player_number) { 299 defeating_player_ = player_number; 300 } 301 302 void add_worker(Worker&) override; 303 void remove_worker(Worker&) override; 304 create_building_settings()305 virtual const BuildingSettings* create_building_settings() const { 306 return nullptr; 307 } 308 309 // AttackTarget object associated with this building. If the building can 310 // never be attacked (for example productionsites) this will be nullptr. attack_target()311 const AttackTarget* attack_target() const { 312 return attack_target_; 313 } 314 315 // SoldierControl object associated with this building. If the building can 316 // not house soldiers (for example productionsites) this will be nullptr. soldier_control()317 const SoldierControl* soldier_control() const { 318 return soldier_control_; 319 } mutable_soldier_control()320 SoldierControl* mutable_soldier_control() { 321 return soldier_control_; 322 } 323 324 void send_message(Game& game, 325 const Message::Type msgtype, 326 const std::string& title, 327 const std::string& icon_filename, 328 const std::string& heading, 329 const std::string& description, 330 bool link_to_building_lifetime = true, 331 uint32_t throttle_time = 0, 332 uint32_t throttle_radius = 0); 333 334 void start_animation(EditorGameBase&, uint32_t anim); 335 336 protected: 337 // Updates 'statistics_string' with the string that should be displayed for 338 // this building right now. Overwritten by child classes. update_statistics_string(std::string *)339 virtual void update_statistics_string(std::string*) { 340 } 341 342 bool init(EditorGameBase&) override; 343 void cleanup(EditorGameBase&) override; 344 void act(Game&, uint32_t data) override; 345 346 void draw(uint32_t gametime, 347 InfoToDraw info_to_draw, 348 const Vector2f& point_on_dst, 349 const Coords& coords, 350 float scale, 351 RenderTarget* dst) override; 352 void 353 draw_info(InfoToDraw info_to_draw, const Vector2f& point_on_dst, float scale, RenderTarget* dst); 354 355 void set_seeing(bool see); 356 void set_attack_target(AttackTarget* new_attack_target); 357 void set_soldier_control(SoldierControl* new_soldier_control); 358 359 Coords position_; 360 Flag* flag_; 361 362 uint32_t anim_; 363 int32_t animstart_; 364 365 using LeaveQueue = std::vector<OPtr<Worker>>; 366 LeaveQueue leave_queue_; // FIFO queue of workers leaving the building 367 uint32_t leave_time_; // when to wake the next one from leave queue 368 ObjectPointer leave_allow_; // worker that is allowed to leave now 369 370 // The player who has defeated this building. 371 PlayerNumber defeating_player_; 372 373 std::map<DescriptionIndex, int32_t> ware_priorities_; 374 375 /// Whether we see our vision_range area based on workers in the building 376 bool seeing_; 377 378 // The former buildings names, with the current one in last position. 379 FormerBuildings old_buildings_; 380 const MapObjectDescr* was_immovable_; 381 382 private: 383 std::string statistics_string_; 384 AttackTarget* attack_target_; // owned by the base classes, set by 'set_attack_target'. 385 SoldierControl* soldier_control_; // owned by the base classes, set by 'set_soldier_control'. 386 }; 387 } // namespace Widelands 388 389 #endif // end of include guard: WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_H 390