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_IMMOVABLE_H 21 #define WL_LOGIC_MAP_OBJECTS_IMMOVABLE_H 22 23 #include <memory> 24 25 #include "base/macros.h" 26 #include "logic/map_objects/buildcost.h" 27 #include "logic/map_objects/info_to_draw.h" 28 #include "logic/map_objects/map_object.h" 29 #include "logic/map_objects/tribes/wareworker.h" 30 #include "logic/map_objects/world/editor_category.h" 31 #include "logic/widelands_geometry.h" 32 #include "notifications/note_ids.h" 33 #include "notifications/notifications.h" 34 35 class TribesLegacyLookupTable; 36 class WorldLegacyLookupTable; 37 38 namespace Widelands { 39 40 class Building; 41 class BuildingDescr; 42 class Economy; 43 class Map; 44 class TerrainAffinity; 45 class Worker; 46 class World; 47 struct Flag; 48 struct PlayerImmovable; 49 50 struct NoteImmovable { 51 CAN_BE_SENT_AS_NOTE(NoteId::Immovable) 52 53 PlayerImmovable* pi; 54 55 enum class Ownership { LOST, GAINED }; 56 Ownership ownership; 57 NoteImmovableNoteImmovable58 NoteImmovable(PlayerImmovable* const init_pi, Ownership const init_ownership) 59 : pi(init_pi), ownership(init_ownership) { 60 } 61 }; 62 63 /** 64 * BaseImmovable is the base for all non-moving objects (immovables such as 65 * trees, buildings, flags, roads). 66 * 67 * The Immovable's size influences building capabilities around it. 68 * If size is NONE, the immovable can simply be removed by placing something on 69 * it (this is usually true for decorations). 70 * 71 * For more information, see the Map::recalc_* functions. 72 */ 73 struct BaseImmovable : public MapObject { 74 enum Size { 75 NONE = 0, ///< not robust (i.e. removable by building something over it) 76 SMALL, ///< small building or robust map element, including trees 77 MEDIUM, ///< medium size building 78 BIG ///< big building 79 }; 80 81 explicit BaseImmovable(const MapObjectDescr&); 82 83 virtual int32_t get_size() const = 0; 84 virtual bool get_passable() const = 0; 85 86 virtual void set_owner(Player* player); 87 88 using PositionList = std::vector<Coords>; 89 /** 90 * Return all coordinates occupied by this Immovable. We gurantee that the 91 * list always contains one entry and the first one is the main position 92 * if one can be chosen as main. 93 */ 94 virtual PositionList get_positions(const EditorGameBase&) const = 0; 95 96 // Draw this immovable onto 'dst' choosing the frame appropriate for 97 // 'gametime'. 'info_to_draw' decides if census and statistics are written too. 98 // The 'coords_to_draw' are passed one to give objects that occupy multiple 99 // fields a way to only draw themselves once. The 'point_on_dst' determines 100 // the point for the hotspot of the animation and 'scale' determines how big 101 // the immovable will be plotted. 102 virtual void draw(uint32_t gametime, 103 InfoToDraw info_to_draw, 104 const Vector2f& point_on_dst, 105 const Coords& coords, 106 float scale, 107 RenderTarget* dst) = 0; 108 109 static int32_t string_to_size(const std::string& size); 110 static std::string size_to_string(int32_t size); 111 112 protected: 113 void set_position(EditorGameBase&, const Coords&); 114 void unset_position(EditorGameBase&, const Coords&); 115 }; 116 117 class Immovable; 118 struct ImmovableProgram; 119 struct ImmovableAction; 120 struct ImmovableActionData; 121 122 /** 123 * Immovable represents a standard immovable such as trees or rocks. 124 */ 125 class ImmovableDescr : public MapObjectDescr { 126 public: 127 using Programs = std::map<std::string, ImmovableProgram*>; 128 129 /// World immovable 130 ImmovableDescr(const std::string& init_descname, const LuaTable&, const World& world); 131 /// Tribes immovable 132 ImmovableDescr(const std::string& init_descname, const LuaTable&, const Tribes& tribes); 133 ~ImmovableDescr() override; 134 get_size()135 int32_t get_size() const { 136 return size_; 137 } 138 ImmovableProgram const* get_program(const std::string&) const; 139 140 Immovable& create(EditorGameBase&, 141 const Coords&, 142 const Widelands::BuildingDescr* former_building_descr) const; 143 owner_type()144 MapObjectDescr::OwnerType owner_type() const { 145 return owner_type_; 146 } 147 buildcost()148 const Buildcost& buildcost() const { 149 return buildcost_; 150 } 151 152 // Returns the editor category, or nullptr if the immovable has no editor category 153 // (e.g. Tribe immovables never have one). 154 const EditorCategory* editor_category() const; 155 156 // A basic localized name for the immovable, used by trees species()157 const std::string& species() const { 158 return species_; 159 } 160 161 // Every immovable that can 'grow' needs to have terrain affinity defined, 162 // all others do not. Returns true if this one has it defined. 163 bool has_terrain_affinity() const; 164 165 // Returns the terrain affinity. If !has_terrain_affinity() this will return 166 // an undefined value. 167 const TerrainAffinity& terrain_affinity() const; 168 169 protected: 170 int32_t size_; 171 Programs programs_; 172 173 /// Whether this ImmovableDescr belongs to a tribe or the world 174 const MapObjectDescr::OwnerType owner_type_; 175 176 /// Buildcost for externally constructible immovables (for ship construction) 177 /// \see ActConstruct 178 Buildcost buildcost_; 179 180 std::string species_; 181 182 private: 183 // Common constructor functions for tribes and world. 184 ImmovableDescr(const std::string& init_descname, 185 const LuaTable&, 186 MapObjectDescr::OwnerType type); 187 188 // Adds a default program if none was defined. 189 void make_sure_default_program_is_there(); 190 191 EditorCategory* editor_category_; // not owned. 192 std::unique_ptr<TerrainAffinity> terrain_affinity_; 193 DISALLOW_COPY_AND_ASSIGN(ImmovableDescr); 194 }; 195 196 class Immovable : public BaseImmovable { 197 friend class ImmovableDescr; 198 friend struct ImmovableProgram; 199 friend class Map; 200 201 MO_DESCR(ImmovableDescr) 202 203 public: 204 /// If this immovable was created by a building, 'former_building_descr' can be set in order to 205 /// display information about it. 206 Immovable(const ImmovableDescr&, 207 const Widelands::BuildingDescr* former_building_descr = nullptr); 208 ~Immovable() override; 209 get_position()210 Coords get_position() const { 211 return position_; 212 } 213 PositionList get_positions(const EditorGameBase&) const override; 214 215 int32_t get_size() const override; 216 bool get_passable() const override; 217 void start_animation(const EditorGameBase&, uint32_t anim); 218 219 void program_step(Game& game, uint32_t const delay = 1) { 220 if (delay) 221 program_step_ = schedule_act(game, delay); 222 increment_program_pointer(); 223 } 224 225 bool init(EditorGameBase&) override; 226 void cleanup(EditorGameBase&) override; 227 void act(Game&, uint32_t data) override; 228 void draw(uint32_t gametime, 229 InfoToDraw info_to_draw, 230 const Vector2f& point_on_dst, 231 const Coords& coords, 232 float scale, 233 RenderTarget* dst) override; 234 235 void switch_program(Game& game, const std::string& programname); 236 bool construct_ware(Game& game, DescriptionIndex index); 237 bool construct_remaining_buildcost(Game& game, Buildcost* buildcost); 238 239 void set_action_data(ImmovableActionData* data); get_action_data()240 template <typename T> T* get_action_data() { 241 if (!action_data_) 242 return nullptr; 243 if (T* data = dynamic_cast<T*>(action_data_.get())) 244 return data; 245 set_action_data(nullptr); 246 return nullptr; 247 } 248 249 protected: 250 // The building type that created this immovable, if any. 251 const BuildingDescr* former_building_descr_; 252 253 Coords position_; 254 255 uint32_t anim_; 256 int32_t animstart_; 257 258 const ImmovableProgram* program_; 259 uint32_t program_ptr_; ///< index of next instruction to execute 260 261 /* GCC 4.0 has problems with friend declarations: It doesn't allow 262 * substructures of friend classes private access but we rely on this behaviour 263 * for ImmovableProgram::ActConstruct. As a dirty workaround, we make the 264 * following variables public for this versions but keep the protected for 265 * other GCC versions. 266 * See the related bug lp:688832. 267 */ 268 #if (__GNUC__ == 4) && (__GNUC_MINOR__ == 0) 269 public: 270 uint32_t anim_construction_total_; 271 uint32_t anim_construction_done_; 272 uint32_t program_step_; 273 274 protected: 275 #else 276 uint32_t anim_construction_total_; 277 uint32_t anim_construction_done_; 278 uint32_t program_step_; ///< time of next step 279 #endif 280 281 /** 282 * Private persistent data for the currently active program action. 283 * 284 * \warning Use get_action_data to access this. 285 */ 286 std::unique_ptr<ImmovableActionData> action_data_; 287 288 // Load/save support 289 protected: 290 struct Loader : public BaseImmovable::Loader { 291 void load(FileRead&, uint8_t packet_version); 292 void load_pointers() override; 293 void load_finish() override; 294 }; 295 296 public: 297 // TODO(unknown): Remove as soon as we fully support the new system has_new_save_support()298 bool has_new_save_support() override { 299 return true; 300 } 301 302 void save(EditorGameBase&, MapObjectSaver&, FileWrite&) override; 303 static MapObject::Loader* load(EditorGameBase&, 304 MapObjectLoader&, 305 FileRead&, 306 const WorldLegacyLookupTable& world_lookup_table, 307 const TribesLegacyLookupTable& tribes_lookup_table); 308 309 private: 310 /// If this immovable was created by a building, this can be set in order to display information 311 /// about it. If this is a player immovable, you will need to set the owner first. 312 void set_former_building(const BuildingDescr& building); 313 314 void increment_program_pointer(); 315 void draw_construction(uint32_t gametime, 316 InfoToDraw info_to_draw, 317 const Vector2f& point_on_dst, 318 const Widelands::Coords& coords, 319 float scale, 320 RenderTarget* dst); 321 }; 322 323 /** 324 * PlayerImmovable is an immovable owned by a player that belongs to an economy: 325 * building, flag or road 326 * 327 * A PlayerImmovable can also house a number of workers, which are automatically 328 * turned into fugitives when the immovable is destroyed, and their economy is 329 * also adjusted automatically. 330 */ 331 struct PlayerImmovable : public BaseImmovable { 332 explicit PlayerImmovable(const MapObjectDescr&); 333 ~PlayerImmovable() override; 334 get_economyPlayerImmovable335 Economy* get_economy(WareWorker type) const { 336 return type == wwWARE ? ware_economy_ : worker_economy_; 337 } economyPlayerImmovable338 Economy& economy(WareWorker type) const { 339 return *(type == wwWARE ? ware_economy_ : worker_economy_); 340 } 341 342 virtual Flag& base_flag() = 0; 343 344 virtual void set_economy(Economy*, WareWorker); 345 346 virtual void add_worker(Worker&); 347 virtual void remove_worker(Worker&); 348 349 using Workers = std::vector<Worker*>; 350 351 /** 352 * \return a list of workers that are currently located at this 353 * immovable. This is not the same as the list of production 354 * workers returned by \ref ProductionSite::working_positions 355 */ get_workersPlayerImmovable356 const Workers& get_workers() const { 357 return workers_; 358 } 359 360 void log_general_info(const EditorGameBase&) const override; 361 362 /** 363 * These functions are called when a ware or worker arrives at 364 * this immovable as the destination of a transfer that does not 365 * have an associated request. 366 * 367 * At the time of this writing, this happens only for warehouses. 368 * 369 * \note This is independent of the \ref add_worker / \ref remove_worker 370 * functionality, which has to do with setting up locations. 371 */ 372 /*@{*/ 373 virtual void receive_ware(Game&, DescriptionIndex ware); 374 virtual void receive_worker(Game&, Worker& worker); 375 /*@}*/ 376 377 void set_owner(Player*) override; 378 379 protected: 380 bool init(EditorGameBase&) override; 381 void cleanup(EditorGameBase&) override; 382 383 private: 384 Economy* ware_economy_; 385 Economy* worker_economy_; 386 387 Workers workers_; 388 389 // load/save support 390 protected: 391 struct Loader : BaseImmovable::Loader { 392 Loader(); 393 394 void load(FileRead&); 395 }; 396 397 public: 398 void save(EditorGameBase&, MapObjectSaver&, FileWrite&) override; 399 }; 400 } // namespace Widelands 401 402 #endif // end of include guard: WL_LOGIC_MAP_OBJECTS_IMMOVABLE_H 403