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_MILITARYSITE_H
21 #define WL_LOGIC_MAP_OBJECTS_TRIBES_MILITARYSITE_H
22 
23 #include <memory>
24 
25 #include "base/macros.h"
26 #include "economy/request.h"
27 #include "logic/map_objects/tribes/building.h"
28 #include "logic/map_objects/tribes/requirements.h"
29 #include "logic/map_objects/tribes/soldiercontrol.h"
30 #include "scripting/lua_table.h"
31 
32 namespace Widelands {
33 
34 // I assume elsewhere, that enum SoldierPreference fits to uint8_t.
35 enum class SoldierPreference : uint8_t {
36 	kRookies,
37 	kHeroes,
38 };
39 
40 class MilitarySiteDescr : public BuildingDescr {
41 public:
42 	MilitarySiteDescr(const std::string& init_descname, const LuaTable& t, const Tribes& tribes);
~MilitarySiteDescr()43 	~MilitarySiteDescr() override {
44 	}
45 
46 	Building& create_object() const override;
47 
get_conquers()48 	uint32_t get_conquers() const override {
49 		return conquer_radius_;
50 	}
get_max_number_of_soldiers()51 	Quantity get_max_number_of_soldiers() const {
52 		return num_soldiers_;
53 	}
get_heal_per_second()54 	uint32_t get_heal_per_second() const {
55 		return heal_per_second_;
56 	}
57 
58 	bool prefers_heroes_at_start_;
59 	std::string occupied_str_;
60 	std::string aggressor_str_;
61 	std::string attack_str_;
62 	std::string defeated_enemy_str_;
63 	std::string defeated_you_str_;
64 
65 private:
66 	uint32_t conquer_radius_;
67 	Quantity num_soldiers_;
68 	uint32_t heal_per_second_;
69 	DISALLOW_COPY_AND_ASSIGN(MilitarySiteDescr);
70 };
71 
72 class MilitarySite : public Building {
73 	friend class MapBuildingdataPacket;
74 	MO_DESCR(MilitarySiteDescr)
75 
76 public:
77 	explicit MilitarySite(const MilitarySiteDescr&);
78 	~MilitarySite() override;
79 
80 	bool init(EditorGameBase&) override;
81 	void cleanup(EditorGameBase&) override;
82 	void act(Game&, uint32_t data) override;
83 	void remove_worker(Worker&) override;
84 
85 	void set_economy(Economy*, WareWorker) override;
86 	bool get_building_work(Game&, Worker&, bool success) override;
87 
88 	/// Launch the given soldier on an attack towards the given
89 	/// target building.
90 	void send_attacker(Soldier&, Building&);
91 
92 	/// This methods are helper for use at configure this site.
93 	void set_requirements(const Requirements&);
94 	void clear_requirements();
get_requirements()95 	const Requirements& get_requirements() const {
96 		return soldier_requirements_;
97 	}
98 
99 	void reinit_after_conqueration(Game&);
100 
101 	void update_soldier_request(bool i = false);
102 
103 	void set_soldier_preference(SoldierPreference);
get_soldier_preference()104 	SoldierPreference get_soldier_preference() const {
105 		return soldier_preference_;
106 	}
107 
108 	const BuildingSettings* create_building_settings() const override;
109 
110 protected:
111 	void conquer_area(EditorGameBase&);
112 
113 private:
114 	void update_statistics_string(std::string*) override;
115 
116 	bool is_present(Soldier&) const;
117 	static void
118 	request_soldier_callback(Game&, Request&, DescriptionIndex, Worker*, PlayerImmovable&);
119 
120 	MapObject* pop_soldier_job(Soldier*, bool* stayhome = nullptr);
121 	bool has_soldier_job(Soldier&);
122 	bool military_presence_kept(Game&);
123 	void notify_player(Game&, bool discovered = false);
124 	bool update_upgrade_requirements();
125 	void update_normal_soldier_request();
126 	void update_upgrade_soldier_request();
127 	bool incorporate_upgraded_soldier(EditorGameBase& game, Soldier& s);
128 	Soldier* find_least_suited_soldier();
129 	bool drop_least_suited_soldier(bool new_has_arrived, Soldier* s);
130 
131 private:
132 	// We can be attacked if we have stationed soldiers.
133 	class AttackTarget : public Widelands::AttackTarget {
134 	public:
AttackTarget(MilitarySite * military_site)135 		explicit AttackTarget(MilitarySite* military_site) : military_site_(military_site) {
136 		}
137 
138 		bool can_be_attacked() const override;
139 		void enemy_soldier_approaches(const Soldier&) const override;
140 		Widelands::AttackTarget::AttackResult attack(Soldier*) const override;
141 
142 	private:
143 		MilitarySite* const military_site_;
144 	};
145 
146 	class SoldierControl : public Widelands::SoldierControl {
147 	public:
SoldierControl(MilitarySite * military_site)148 		explicit SoldierControl(MilitarySite* military_site) : military_site_(military_site) {
149 		}
150 
151 		std::vector<Soldier*> present_soldiers() const override;
152 		std::vector<Soldier*> stationed_soldiers() const override;
153 		Quantity min_soldier_capacity() const override;
154 		Quantity max_soldier_capacity() const override;
155 		Quantity soldier_capacity() const override;
156 		void set_soldier_capacity(Quantity capacity) override;
157 		void drop_soldier(Soldier&) override;
158 		int incorporate_soldier(EditorGameBase& game, Soldier& s) override;
159 
160 	private:
161 		MilitarySite* const military_site_;
162 	};
163 
164 	AttackTarget attack_target_;
165 	SoldierControl soldier_control_;
166 	Requirements soldier_requirements_;  // This is used to grab a bunch of soldiers: Anything goes
167 	RequireAttribute soldier_upgrade_requirements_;     // This is used when exchanging soldiers.
168 	std::unique_ptr<Request> normal_soldier_request_;   // filling the site
169 	std::unique_ptr<Request> upgrade_soldier_request_;  // seeking for better soldiers
170 	bool didconquer_;
171 	Quantity capacity_;
172 
173 	/**
174 	 * Next gametime where we should heal something.
175 	 */
176 	int32_t nexthealtime_;
177 
178 	struct SoldierJob {
179 		Soldier* soldier;
180 		ObjectPointer enemy;
181 		bool stayhome;
182 	};
183 	std::vector<SoldierJob> soldierjobs_;
184 	SoldierPreference soldier_preference_;
185 	int32_t next_swap_soldiers_time_;
186 	bool soldier_upgrade_try_;  // optimization -- if everybody is zero-level, do not downgrade
187 	bool doing_upgrade_request_;
188 };
189 }  // namespace Widelands
190 
191 #endif  // end of include guard: WL_LOGIC_MAP_OBJECTS_TRIBES_MILITARYSITE_H
192