1 /* 2 * Copyright (C) 2010-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_SHIP_H 21 #define WL_LOGIC_MAP_OBJECTS_TRIBES_SHIP_H 22 23 #include <memory> 24 25 #include "base/macros.h" 26 #include "economy/shippingitem.h" 27 #include "graphic/animation/diranimations.h" 28 #include "logic/map_objects/bob.h" 29 30 namespace Widelands { 31 32 struct ShipFleet; 33 34 // This can't be part of the Ship class because of forward declaration in game.h 35 // Keep the order of entries for savegame compatibility. 36 enum class IslandExploreDirection { 37 kNotSet, 38 kCounterClockwise, 39 kClockwise, 40 }; 41 42 struct NoteShip { 43 CAN_BE_SENT_AS_NOTE(NoteId::Ship) 44 45 Ship* ship; 46 47 enum class Action { kDestinationChanged, kWaitingForCommand, kNoPortLeft, kLost, kGained }; 48 Action action; 49 NoteShipNoteShip50 NoteShip(Ship* const init_ship, const Action& init_action) 51 : ship(init_ship), action(init_action) { 52 } 53 }; 54 55 class ShipDescr : public BobDescr { 56 public: 57 ShipDescr(const std::string& init_descname, const LuaTable& t); ~ShipDescr()58 ~ShipDescr() override { 59 } 60 61 Bob& create_object() const override; 62 63 uint32_t movecaps() const override; get_sail_anims()64 const DirAnimations& get_sail_anims() const { 65 return sail_anims_; 66 } 67 get_default_capacity()68 Quantity get_default_capacity() const { 69 return default_capacity_; 70 } 71 72 private: 73 DirAnimations sail_anims_; 74 Quantity default_capacity_; 75 DISALLOW_COPY_AND_ASSIGN(ShipDescr); 76 }; 77 78 constexpr int32_t kShipInterval = 1500; 79 80 constexpr uint32_t kInvalidDestination = std::numeric_limits<uint32_t>::max(); 81 82 /** 83 * Ships belong to a player and to an economy. The usually are in a (unique) 84 * fleet for a player, but only if they are on standard duty. Exploration ships 85 * are an economy of their own and are not part of a Fleet. 86 */ 87 struct Ship : Bob { 88 MO_DESCR(ShipDescr) 89 90 explicit Ship(const ShipDescr& descr); 91 ~Ship() override; 92 93 // Returns the fleet the ship is a part of. 94 ShipFleet* get_fleet() const; 95 get_destinationShip96 PortDock* get_destination() const { 97 return destination_; 98 } 99 void set_destination(Game&, PortDock*); 100 101 // Returns the last visited portdock of this ship or nullptr if there is none or 102 // the last visited was removed. 103 PortDock* get_lastdock(EditorGameBase& egbase) const; 104 get_economyShip105 Economy* get_economy(WareWorker type) const { 106 return type == wwWARE ? ware_economy_ : worker_economy_; 107 } 108 void set_economy(Game&, Economy* e, WareWorker); 109 110 void init_auto_task(Game&) override; 111 112 bool init(EditorGameBase&) override; 113 void cleanup(EditorGameBase&) override; 114 115 void start_task_ship(Game&); 116 void start_task_movetodock(Game&, PortDock&); 117 void start_task_expedition(Game&); 118 119 uint32_t calculate_sea_route(EditorGameBase&, PortDock&, Path* = nullptr) const; 120 121 void log_general_info(const EditorGameBase&) const override; 122 get_nritemsShip123 uint32_t get_nritems() const { 124 return items_.size(); 125 } get_itemShip126 const ShippingItem& get_item(uint32_t idx) const { 127 return items_[idx]; 128 } 129 130 void add_item(Game&, const ShippingItem&); 131 bool withdraw_item(Game&, PortDock&); 132 133 // A ship with task expedition can be in four states: kExpeditionWaiting, kExpeditionScouting, 134 // kExpeditionPortspaceFound or kExpeditionColonizing in the first states, the owning player of 135 // this ship 136 // can give direction change commands to change the direction of the moving ship / send the ship 137 // in a 138 // direction. Once the ship is on its way, it is in kExpeditionScouting state. In the backend, a 139 // click 140 // on a direction begins to the movement into that direction until a coast is reached or the user 141 // cancels the direction through a direction change. 142 // 143 // The kExpeditionWaiting state means, that an event happend and thus the ship stopped and waits 144 // for a 145 // new command by the owner. An event leading to a kExpeditionWaiting state can be: 146 // * expedition is ready to start 147 // * new island appeared in vision range (only outer ring of vision range has to be checked due 148 // to the 149 // always ongoing movement). 150 // * island was completely surrounded 151 // 152 // The kExpeditionPortspaceFound state means, that a port build space was found. 153 // 154 enum class ShipStates : uint8_t { 155 kTransport = 0, 156 kExpeditionWaiting = 1, 157 kExpeditionScouting = 2, 158 kExpeditionPortspaceFound = 3, 159 kExpeditionColonizing = 4, 160 kSinkRequest = 8, 161 kSinkAnimation = 9 162 }; 163 164 /// \returns the current state the ship is in get_ship_stateShip165 ShipStates get_ship_state() const { 166 return ship_state_; 167 } 168 169 /// \returns the current name of ship get_shipnameShip170 const std::string& get_shipname() const { 171 return shipname_; 172 } 173 174 /// \returns whether the ship is currently on an expedition state_is_expeditionShip175 bool state_is_expedition() const { 176 return (ship_state_ == ShipStates::kExpeditionScouting || 177 ship_state_ == ShipStates::kExpeditionWaiting || 178 ship_state_ == ShipStates::kExpeditionPortspaceFound || 179 ship_state_ == ShipStates::kExpeditionColonizing); 180 } 181 /// \returns whether the ship is in transport mode state_is_transportShip182 bool state_is_transport() const { 183 return (ship_state_ == ShipStates::kTransport); 184 } 185 /// \returns whether a sink request for the ship is currently valid state_is_sinkableShip186 bool state_is_sinkable() const { 187 return (ship_state_ != ShipStates::kSinkRequest && 188 ship_state_ != ShipStates::kSinkAnimation && 189 ship_state_ != ShipStates::kExpeditionColonizing); 190 } 191 192 /// \returns (in expedition mode only!) whether the next field in direction \arg dir is swimmable exp_dir_swimmableShip193 bool exp_dir_swimmable(Direction dir) const { 194 if (!expedition_) 195 return false; 196 return expedition_->swimmable[dir - 1]; 197 } 198 199 // whether the ship's expedition is in state "island-exploration" (circular movement) is_exploring_islandShip200 bool is_exploring_island() const { 201 return expedition_->island_exploration; 202 } 203 204 /// \returns whether the expedition ship is close to the coast exp_close_to_coastShip205 bool exp_close_to_coast() const { 206 if (!expedition_) 207 return false; 208 for (uint8_t dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) 209 if (!expedition_->swimmable[dir - 1]) 210 return true; 211 return false; 212 } 213 214 /// \returns (in expedition mode only!) the list of currently seen port build spaces exp_port_spacesShip215 const std::vector<Coords>& exp_port_spaces() const { 216 return expedition_->seen_port_buildspaces; 217 } 218 219 void exp_scouting_direction(Game&, WalkingDir); 220 void exp_construct_port(Game&, const Coords&); 221 void exp_explore_island(Game&, IslandExploreDirection); 222 223 // Returns integer of direction, or WalkingDir::IDLE if query invalid 224 // Intended for LUA scripting 225 WalkingDir get_scouting_direction() const; 226 227 // Returns integer of direction, or IslandExploreDirection::kNotSet 228 // if query invalid 229 // Intended for LUA scripting 230 IslandExploreDirection get_island_explore_direction() const; 231 232 void exp_cancel(Game&); 233 void sink_ship(Game&); 234 get_capacityShip235 Quantity get_capacity() const { 236 return capacity_; 237 } set_capacityShip238 void set_capacity(Quantity c) { 239 capacity_ = c; 240 } 241 242 protected: 243 void draw(const EditorGameBase&, 244 const InfoToDraw& info_to_draw, 245 const Vector2f& point_on_dst, 246 const Coords& coords, 247 float scale, 248 RenderTarget* dst) const override; 249 250 private: 251 friend struct ShipFleet; 252 friend struct ShippingSchedule; 253 254 void wakeup_neighbours(Game&); 255 256 static const Task taskShip; 257 258 void ship_update(Game&, State&); 259 void ship_wakeup(Game&); 260 261 bool ship_update_transport(Game&, State&); 262 void ship_update_expedition(Game&, State&); 263 void ship_update_idle(Game&, State&); 264 /// Set the ship's state to 'state' and if the ship state has changed, publish a notification. 265 void set_ship_state_and_notify(ShipStates state, NoteShip::Action action); 266 267 bool init_fleet(EditorGameBase&); 268 void set_fleet(ShipFleet* fleet); 269 270 void send_message(Game& game, 271 const std::string& title, 272 const std::string& heading, 273 const std::string& description, 274 const std::string& picture); 275 276 ShipFleet* fleet_; 277 Economy* ware_economy_; 278 Economy* worker_economy_; 279 OPtr<PortDock> lastdock_; 280 std::vector<ShippingItem> items_; 281 ShipStates ship_state_; 282 std::string shipname_; 283 284 PortDock* destination_; 285 286 struct Expedition { 287 ~Expedition(); 288 289 std::vector<Coords> seen_port_buildspaces; 290 bool swimmable[LAST_DIRECTION]; 291 bool island_exploration; 292 WalkingDir scouting_direction; 293 Coords exploration_start; 294 IslandExploreDirection island_explore_direction; 295 Economy* ware_economy; // Owned by Player 296 Economy* worker_economy; 297 }; 298 std::unique_ptr<Expedition> expedition_; 299 300 Quantity capacity_; 301 302 // saving and loading 303 protected: 304 struct Loader : Bob::Loader { 305 306 const Task* get_task(const std::string& name) override; 307 308 void load(FileRead& fr, uint8_t); 309 void load_pointers() override; 310 void load_finish() override; 311 312 private: 313 // Initialize everything to make cppcheck happy. 314 uint32_t lastdock_ = 0U; 315 Serial ware_economy_serial_; 316 Serial worker_economy_serial_; 317 uint32_t destination_; 318 uint32_t capacity_ = 0U; 319 ShipStates ship_state_ = ShipStates::kTransport; 320 std::string shipname_; 321 std::unique_ptr<Expedition> expedition_; 322 std::vector<ShippingItem::Loader> items_; 323 uint8_t packet_version_ = 0; 324 }; 325 326 public: 327 void save(EditorGameBase&, MapObjectSaver&, FileWrite&) override; 328 329 static MapObject::Loader* load(EditorGameBase&, MapObjectLoader&, FileRead&); 330 }; 331 332 } // namespace Widelands 333 334 #endif // end of include guard: WL_LOGIC_MAP_OBJECTS_TRIBES_SHIP_H 335