Merge lp:~widelands-dev/widelands/constructionsite_options into lp:widelands
- constructionsite_options
- Merge into trunk
Status: | Merged | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 9157 | ||||||||||||||||
Proposed branch: | lp:~widelands-dev/widelands/constructionsite_options | ||||||||||||||||
Merge into: | lp:widelands | ||||||||||||||||
Diff against target: |
2863 lines (+1576/-202) 38 files modified
src/ai/defaultai_seafaring.cc (+1/-1) src/economy/economy.cc (+5/-5) src/economy/request.cc (+1/-1) src/logic/editor_game_base.cc (+8/-2) src/logic/editor_game_base.h (+3/-1) src/logic/game.cc (+7/-2) src/logic/game.h (+3/-0) src/logic/map_objects/CMakeLists.txt (+2/-0) src/logic/map_objects/tribes/bill_of_materials.h (+0/-23) src/logic/map_objects/tribes/building.cc (+3/-3) src/logic/map_objects/tribes/building.h (+10/-5) src/logic/map_objects/tribes/building_settings.cc (+346/-0) src/logic/map_objects/tribes/building_settings.h (+123/-0) src/logic/map_objects/tribes/constructionsite.cc (+265/-21) src/logic/map_objects/tribes/constructionsite.h (+21/-0) src/logic/map_objects/tribes/militarysite.cc (+7/-0) src/logic/map_objects/tribes/militarysite.h (+2/-0) src/logic/map_objects/tribes/productionsite.cc (+29/-6) src/logic/map_objects/tribes/productionsite.h (+2/-0) src/logic/map_objects/tribes/trainingsite.cc (+7/-0) src/logic/map_objects/tribes/trainingsite.h (+2/-0) src/logic/map_objects/tribes/warehouse.cc (+20/-8) src/logic/map_objects/tribes/warehouse.h (+36/-33) src/logic/player.cc (+2/-1) src/logic/playercommand.cc (+99/-26) src/logic/playercommand.h (+5/-3) src/map_io/map_buildingdata_packet.cc (+24/-4) src/notifications/note_ids.h (+1/-0) src/scripting/lua_map.cc (+15/-15) src/wui/actionconfirm.cc (+22/-10) src/wui/actionconfirm.h (+2/-1) src/wui/buildingwindow.cc (+3/-3) src/wui/buildingwindow.h (+5/-1) src/wui/constructionsitewindow.cc (+340/-1) src/wui/constructionsitewindow.h (+39/-0) src/wui/inputqueuedisplay.cc (+91/-17) src/wui/inputqueuedisplay.h (+17/-1) src/wui/warehousewindow.cc (+8/-8) |
||||||||||||||||
To merge this branch: | bzr merge lp:~widelands-dev/widelands/constructionsite_options | ||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
GunChleoc | Approve | ||
Review via email: mp+367428@code.launchpad.net |
Commit message
Allow players to define settings for and to enhance buildings under construction
Description of the change
bunnybot (widelandsofficial) wrote : | # |
Toni Förster (stonerl) wrote : | # |
I get these compiler warnings a couple of times.
/Users/
struct BuildingSettings {
^
/Users/
struct ProductionsiteS
^
/Users/
struct MilitarysiteSet
^
/Users/
struct TrainingsiteSet
^
/Users/
struct WarehouseSettings : public BuildingSettings {
^
5 warnings generated.
Toni Förster (stonerl) wrote : | # |
Some comments regarding the UI.
I think we should keep the UI consistent. Instead of checkboxes please use the icons/buttons that are used in the building's window. The same applies for the priority settings. We use traffic lights instead of buttons.
Benedikt Straub (nordfriese) wrote : | # |
Fixed the compiler warnings and made the UI design consistent. I did not convert the Stop and Launch Expedition to toggle-buttons though because it is never clear with such buttons whether the icon shows the current state or the action taken by clicking it IMHO.
By the way, when clicking the Enhance button, the window will annoyingly switch to the first tab – this is unrelated to this branch, see bug 1818857.
Toni Förster (stonerl) wrote : | # |
hmm. I would prefer icons but you are completely right. I opened a topic in the forum:
https:/
Toni Förster (stonerl) wrote : | # |
Four warnings left:
src/logic/
src/logic/
src/wui/
src/logic/
Toni Förster (stonerl) wrote : | # |
Your buttons are a little too big. The buttons for in-/decreasing the wares are 24x24 while yours are 25x30.
Also, some wares are covered by the button; see the fish in the tavern (I guess that is because of your buttons being to big)
Toni Förster (stonerl) wrote : | # |
With this branch I get crashes after a while. Not sure if the culprit is this branch or something in trunk, though.
/Users/
==54196==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x7ffee6344650 sp 0x7ffee63445a8 T0)
Benedikt Straub (nordfriese) wrote : | # |
Took care of the warnings and fixed the input queue layout.
> src/graphic/
A backtrace would be helpful…
Did you get this while an (enhanced?) constructionsite was being built, or when a constructionsite was being completed? I got similar crashes before, but I thought I had caught all corner cases now…
Toni Förster (stonerl) wrote : | # |
Assertion failed: (military_
Benedikt Straub (nordfriese) wrote : | # |
Assert fail fixed :)
kaputtnik (franku) wrote : | # |
Looks like this branch breaks savegame compatibility. When trying to load a game which runs fine in trunk i get:
Writing Buildingdata Data ... widelands: /home/kaputtnik
Abgebrochen (Speicherabzug geschrieben)
Benedikt Straub (nordfriese) wrote : | # |
Oops… should be fixed now
Toni Förster (stonerl) wrote : | # |
And another assertion.
Assertion failed: (animation_index < animations.size()), function draw, file /Users/
Benedikt Straub (nordfriese) wrote : | # |
This seems to be the same issue as the crash with animation ID -432781024, but with a more usable file&line number. Will push a fix soonish
Benedikt Straub (nordfriese) wrote : | # |
Since the bug is not reproducible, I can´t be certain, but it should most likely be gone now
Toni Förster (stonerl) wrote : | # |
Seems to be fixed.
kaputtnik (franku) wrote : | # |
Trying to load a savgame from trunk prints now in a window (and console):
Game data error
buildingdata: building 524547: not found
Loading in trunk works fine. Save game: https:/
GunChleoc (gunchleoc) wrote : | # |
I am getting a similar error when loading our homepage reference screenshot savegame Build, so we already have a change to saveloading in trunk where we overlooked having to increase the packet number.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 5003. State: passed. Details: https:/
Appveyor build 4784. State: success. Details: https:/
Toni Förster (stonerl) wrote : | # |
Would it be possible to move the tabs for Warehouses' and Ports' to the top, instead of having to tab rows?
Benedikt Straub (nordfriese) wrote : | # |
OK, will change it like this
GunChleoc (gunchleoc) wrote : | # |
It would be nice if the tab was remembered after using the "enhance" button.
The target of the help button does not get updated when enhancing, e.g. construction site for deeper coal mine will show the coal mine instead.
"Launch expedition" should be "Start an expedition" like on the button for the finished port.
It would be nice if the extra options like "Start an expedition" or "Stop" would have the same UI buttons as the finished sites. I can live with the checkboxes though.
GunChleoc (gunchleoc) wrote : | # |
Also, this:
=======
==6265==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 2744 byte(s) in 49 object(s) allocated from:
#0 0x7ff86f576458 in operator new(unsigned long) (/usr/lib/
#1 0x55643637edfd in Widelands:
#2 0x556435cb4c9b in Widelands:
#3 0x556435cb47a3 in Widelands:
#4 0x5564366afc07 in Widelands:
#5 0x5564366a690e in Widelands:
#6 0x556435c8be44 in Widelands:
#7 0x55643605fe76 in InteractiveBase
#8 0x5564360b3bde in InteractivePlay
#9 0x556435eec265 in UI::Panel:
#10 0x556435ee95ca in UI::Panel::do_run() ../src/
#11 0x556435983b5d in UI::Panel:
#12 0x556435c8b669 in Widelands:
#13 0x55643596f976 in WLApplication:
#14 0x55643596da4a in WLApplication:
#15 0x55643596cb95 in WLApplication:
#16 0x556435963b7b in WLApplication:
#17 0x55643595f8ce in main ../src/main.cc:44
#18 0x7ff86c9a9b96 in __libc_start_main (/lib/x86_
Benedikt Straub (nordfriese) wrote : | # |
> "Launch expedition" should be "Start an expedition" like on the button for the finished port.
> The target of the help button does not get updated when enhancing, e.g. construction site for deeper coal mine will show the coal mine instead.
> ASan
Should all be fixed now
> It would be nice if the tab was remembered after using the "enhance" button.
This is exactly the same as bug 1818857 so it should be fixed independent from this branch. There will likely be one catch-all fix for both flavours of the bug.
> It would be nice if the extra options like "Start an expedition" or "Stop" would have the same UI buttons as the finished sites. I can live with the checkboxes though.
What I could do is to render the appropriate icon next to the checkbox if you like. But unless we change the other UI elements in such a way that they show clearly what the current state is, there is no alternative to the checkboxes IMHO, since the current icons are only acceptable because one can see the active state elsewhere (stats string / expedition tab), which can not happen here.
GunChleoc (gunchleoc) wrote : | # |
OK, let's leave the design as it is :)
This doesn't compile:
ow.cc.o -c ../src/
In file included from ../src/
../src/
../src/
building_
Once that has been fixed, we still need to look at the code.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 5074. State: failed. Details: https:/
Appveyor build 4854. State: failed. Details: https:/
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 5076. State: errored. Details: https:/
Appveyor build 4856. State: failed. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
I finally got around to doing the code review. This branch still has a lot of room for streamlining the code and the performance.
Benedikt Straub (nordfriese) wrote : | # |
Implemented your comments
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 5185. State: passed. Details: https:/
Appveyor build 4965. State: failed. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
The changes look good - there are still some open comments, though. Sorry it took me a while to get back to this.
Benedikt Straub (nordfriese) wrote : | # |
No problem. I have very little time for Widelands at the moment anyway :)
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 5203. State: errored. Details: https:/
Appveyor build 4982. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
LGTM now :)
I'd like to retest this due to the code changes made during review.
GunChleoc (gunchleoc) wrote : | # |
Tested and still working - thanks for this great feature!
@bunnybot merge
bunnybot (widelandsofficial) wrote : | # |
Refusing to merge, since Travis is not green. Use @bunnybot merge force for merging anyways.
Travis build 5203. State: errored. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
inputqueues again
@bunnybot merge force
bunnybot (widelandsofficial) wrote : | # |
Error merging this proposal:
Output:
stdout:
stderr:
Unable to obtain lock held by <email address hidden> on taotie (process #21580), acquired 19 hours, 2 minutes ago.
See "bzr help break-lock" for more.
bzr: ERROR: Could not acquire lock "(remote lock)": bzr+ssh:
GunChleoc (gunchleoc) wrote : | # |
@bunnybot merge force
Preview Diff
1 | === modified file 'src/ai/defaultai_seafaring.cc' |
2 | --- src/ai/defaultai_seafaring.cc 2019-02-23 11:00:49 +0000 |
3 | +++ src/ai/defaultai_seafaring.cc 2019-06-19 09:23:26 +0000 |
4 | @@ -346,7 +346,7 @@ |
5 | if (site->bo->is(BuildingAttribute::kShipyard)) { |
6 | for (uint32_t k = 0; k < site->bo->inputs.size(); ++k) { |
7 | game().send_player_set_ware_priority( |
8 | - *site->site, wwWARE, site->bo->inputs.at(k), HIGH_PRIORITY); |
9 | + *site->site, wwWARE, site->bo->inputs.at(k), kPriorityHigh); |
10 | } |
11 | } |
12 | } |
13 | |
14 | === modified file 'src/economy/economy.cc' |
15 | --- src/economy/economy.cc 2019-04-09 16:43:49 +0000 |
16 | +++ src/economy/economy.cc 2019-06-19 09:23:26 +0000 |
17 | @@ -971,7 +971,7 @@ |
18 | static bool accept_warehouse_if_policy(Warehouse& wh, |
19 | WareWorker type, |
20 | DescriptionIndex ware, |
21 | - Warehouse::StockPolicy policy) { |
22 | + StockPolicy policy) { |
23 | return wh.get_stock_policy(type, ware) == policy; |
24 | } |
25 | |
26 | @@ -1005,8 +1005,8 @@ |
27 | |
28 | for (uint32_t nwh = 0; nwh < warehouses_.size(); ++nwh) { |
29 | Warehouse* wh = warehouses_[nwh]; |
30 | - Warehouse::StockPolicy policy = wh->get_stock_policy(type, ware); |
31 | - if (policy == Warehouse::StockPolicy::kPrefer) { |
32 | + StockPolicy policy = wh->get_stock_policy(type, ware); |
33 | + if (policy == StockPolicy::kPrefer) { |
34 | haveprefer = true; |
35 | |
36 | // Getting count of worker/ware |
37 | @@ -1022,7 +1022,7 @@ |
38 | preferred_wh_stock = current_stock; |
39 | } |
40 | } |
41 | - if (policy == Warehouse::StockPolicy::kNormal) |
42 | + if (policy == StockPolicy::kNormal) |
43 | havenormal = true; |
44 | } |
45 | if (!havenormal && !haveprefer && type == wwWARE) |
46 | @@ -1037,7 +1037,7 @@ |
47 | (!havenormal) ? |
48 | WarehouseAcceptFn() : |
49 | boost::bind(&accept_warehouse_if_policy, _1, type, ware, |
50 | - Warehouse::StockPolicy::kNormal)); |
51 | + StockPolicy::kNormal)); |
52 | } |
53 | if (!wh) { |
54 | log("Warning: Economy::handle_active_supplies " |
55 | |
56 | === modified file 'src/economy/request.cc' |
57 | --- src/economy/request.cc 2019-06-13 17:32:28 +0000 |
58 | +++ src/economy/request.cc 2019-06-19 09:23:26 +0000 |
59 | @@ -266,7 +266,7 @@ |
60 | int32_t Request::get_priority(int32_t cost) const { |
61 | int MAX_IDLE_PRIORITY = 100; |
62 | bool is_construction_site = false; |
63 | - int32_t modifier = DEFAULT_PRIORITY; |
64 | + int32_t modifier = kPriorityNormal; |
65 | |
66 | if (target_building_) { |
67 | modifier = target_building_->get_priority(get_type(), get_index()); |
68 | |
69 | === modified file 'src/logic/editor_game_base.cc' |
70 | --- src/logic/editor_game_base.cc 2019-04-26 05:52:49 +0000 |
71 | +++ src/logic/editor_game_base.cc 2019-06-19 09:23:26 +0000 |
72 | @@ -38,6 +38,7 @@ |
73 | #include "logic/map_objects/map_object.h" |
74 | #include "logic/map_objects/tribes/battle.h" |
75 | #include "logic/map_objects/tribes/building.h" |
76 | +#include "logic/map_objects/tribes/constructionsite.h" |
77 | #include "logic/map_objects/tribes/dismantlesite.h" |
78 | #include "logic/map_objects/tribes/tribe_descr.h" |
79 | #include "logic/map_objects/tribes/tribes.h" |
80 | @@ -349,10 +350,15 @@ |
81 | PlayerNumber const owner, |
82 | DescriptionIndex idx, |
83 | bool loading, |
84 | - Building::FormerBuildings former_buildings) { |
85 | + Building::FormerBuildings former_buildings, |
86 | + const BuildingSettings* settings) { |
87 | Player* plr = get_player(owner); |
88 | const TribeDescr& tribe = plr->tribe(); |
89 | - return tribe.get_building_descr(idx)->create(*this, plr, c, true, loading, former_buildings); |
90 | + Building& b = tribe.get_building_descr(idx)->create(*this, plr, c, true, loading, former_buildings); |
91 | + if (settings) { |
92 | + dynamic_cast<ConstructionSite&>(b).apply_settings(*settings); |
93 | + } |
94 | + return b; |
95 | } |
96 | |
97 | /** |
98 | |
99 | === modified file 'src/logic/editor_game_base.h' |
100 | --- src/logic/editor_game_base.h 2019-02-27 19:00:36 +0000 |
101 | +++ src/logic/editor_game_base.h 2019-06-19 09:23:26 +0000 |
102 | @@ -56,6 +56,7 @@ |
103 | class TribeDescr; |
104 | struct Flag; |
105 | struct AttackController; |
106 | +struct BuildingSettings; |
107 | |
108 | struct NoteFieldPossession { |
109 | CAN_BE_SENT_AS_NOTE(NoteId::FieldPossession) |
110 | @@ -130,7 +131,8 @@ |
111 | PlayerNumber, |
112 | DescriptionIndex, |
113 | bool loading = false, |
114 | - Building::FormerBuildings former_buildings = Building::FormerBuildings()); |
115 | + Building::FormerBuildings former_buildings = Building::FormerBuildings(), |
116 | + const BuildingSettings* settings = nullptr); |
117 | Building& |
118 | warp_dismantlesite(const Coords&, |
119 | PlayerNumber, |
120 | |
121 | === modified file 'src/logic/game.cc' |
122 | --- src/logic/game.cc 2019-05-25 07:36:44 +0000 |
123 | +++ src/logic/game.cc 2019-06-19 09:23:26 +0000 |
124 | @@ -56,6 +56,7 @@ |
125 | #include "logic/map_objects/tribes/soldier.h" |
126 | #include "logic/map_objects/tribes/trainingsite.h" |
127 | #include "logic/map_objects/tribes/tribe_descr.h" |
128 | +#include "logic/map_objects/tribes/warehouse.h" |
129 | #include "logic/player.h" |
130 | #include "logic/playercommand.h" |
131 | #include "logic/replay.h" |
132 | @@ -775,8 +776,7 @@ |
133 | } |
134 | |
135 | void Game::send_player_enhance_building(Building& building, DescriptionIndex const id) { |
136 | - assert(building.owner().tribe().has_building(id)); |
137 | - |
138 | + assert(building.descr().type() == MapObjectType::CONSTRUCTIONSITE || building.owner().tribe().has_building(id)); |
139 | send_player_command( |
140 | new CmdEnhanceBuilding(get_gametime(), building.owner().player_number(), building, id)); |
141 | } |
142 | @@ -858,6 +858,11 @@ |
143 | new CmdProposeTrade(get_gametime(), object->get_owner()->player_number(), trade)); |
144 | } |
145 | |
146 | +void Game::send_player_set_stock_policy(Building& imm, WareWorker ww, DescriptionIndex di, StockPolicy sp) { |
147 | + send_player_command(new CmdSetStockPolicy(get_gametime(), imm.get_owner()->player_number(), |
148 | + imm, ww == wwWORKER, di, sp)); |
149 | +} |
150 | + |
151 | int Game::propose_trade(const Trade& trade) { |
152 | // TODO(sirver,trading): Check if a trade is possible (i.e. if there is a |
153 | // path between the two markets); |
154 | |
155 | === modified file 'src/logic/game.h' |
156 | --- src/logic/game.h 2019-05-25 07:36:44 +0000 |
157 | +++ src/logic/game.h 2019-06-19 09:23:26 +0000 |
158 | @@ -46,6 +46,7 @@ |
159 | // See forester_cache_ |
160 | constexpr int16_t kInvalidForesterEntry = -1; |
161 | |
162 | +class ConstructionSite; |
163 | struct Flag; |
164 | struct Path; |
165 | struct PlayerImmovable; |
166 | @@ -56,6 +57,7 @@ |
167 | struct PlayerEndStatus; |
168 | class TrainingSite; |
169 | class MilitarySite; |
170 | +enum class StockPolicy; |
171 | |
172 | enum { |
173 | gs_notrunning = 0, // game is being prepared |
174 | @@ -262,6 +264,7 @@ |
175 | |
176 | void send_player_enhance_building(Building&, DescriptionIndex); |
177 | void send_player_evict_worker(Worker&); |
178 | + void send_player_set_stock_policy(Building&, WareWorker, DescriptionIndex, StockPolicy); |
179 | void send_player_set_ware_priority(PlayerImmovable&, |
180 | int32_t type, |
181 | DescriptionIndex index, |
182 | |
183 | === modified file 'src/logic/map_objects/CMakeLists.txt' |
184 | --- src/logic/map_objects/CMakeLists.txt 2019-05-12 07:45:59 +0000 |
185 | +++ src/logic/map_objects/CMakeLists.txt 2019-06-19 09:23:26 +0000 |
186 | @@ -49,6 +49,8 @@ |
187 | tribes/bill_of_materials.h |
188 | tribes/building.cc |
189 | tribes/building.h |
190 | + tribes/building_settings.cc |
191 | + tribes/building_settings.h |
192 | tribes/carrier.cc |
193 | tribes/carrier.h |
194 | tribes/constructionsite.cc |
195 | |
196 | === modified file 'src/logic/map_objects/tribes/bill_of_materials.h' |
197 | --- src/logic/map_objects/tribes/bill_of_materials.h 2019-02-23 11:00:49 +0000 |
198 | +++ src/logic/map_objects/tribes/bill_of_materials.h 2019-06-19 09:23:26 +0000 |
199 | @@ -28,29 +28,6 @@ |
200 | using WareAmount = std::pair<DescriptionIndex, Widelands::Quantity>; |
201 | using BillOfMaterials = std::vector<WareAmount>; |
202 | |
203 | -// range structure for iterating ware range with index |
204 | -struct WareRange { |
205 | - explicit WareRange(const BillOfMaterials& range) |
206 | - : i(0), current(range.begin()), end(range.end()) { |
207 | - } |
208 | - WareRange& operator++() { |
209 | - ++i; |
210 | - ++current; |
211 | - return *this; |
212 | - } |
213 | - bool empty() const { |
214 | - return current == end; |
215 | - } |
216 | - operator bool() const { |
217 | - return !empty(); |
218 | - } |
219 | - |
220 | - uint8_t i; |
221 | - BillOfMaterials::const_iterator current; |
222 | - |
223 | -private: |
224 | - BillOfMaterials::const_iterator const end; |
225 | -}; |
226 | } // namespace Widelands |
227 | |
228 | #endif // end of include guard: WL_LOGIC_MAP_OBJECTS_TRIBES_BILL_OF_MATERIALS_H |
229 | |
230 | === modified file 'src/logic/map_objects/tribes/building.cc' |
231 | --- src/logic/map_objects/tribes/building.cc 2019-05-26 17:21:15 +0000 |
232 | +++ src/logic/map_objects/tribes/building.cc 2019-06-19 09:23:26 +0000 |
233 | @@ -638,13 +638,13 @@ |
234 | |
235 | int32_t |
236 | Building::get_priority(WareWorker type, DescriptionIndex const ware_index, bool adjust) const { |
237 | - int32_t priority = DEFAULT_PRIORITY; |
238 | + int32_t priority = kPriorityNormal; |
239 | if (type == wwWARE) { |
240 | // if priority is defined for specific ware, |
241 | // combine base priority and ware priority |
242 | std::map<DescriptionIndex, int32_t>::const_iterator it = ware_priorities_.find(ware_index); |
243 | if (it != ware_priorities_.end()) |
244 | - priority = adjust ? (priority * it->second / DEFAULT_PRIORITY) : it->second; |
245 | + priority = adjust ? (priority * it->second / kPriorityNormal) : it->second; |
246 | } |
247 | |
248 | return priority; |
249 | @@ -660,7 +660,7 @@ |
250 | std::map<DescriptionIndex, int32_t>& ware_priorities = p[wwWARE]; |
251 | std::map<DescriptionIndex, int32_t>::const_iterator it; |
252 | for (it = ware_priorities_.begin(); it != ware_priorities_.end(); ++it) { |
253 | - if (it->second == DEFAULT_PRIORITY) |
254 | + if (it->second == kPriorityNormal) |
255 | continue; |
256 | ware_priorities[it->first] = it->second; |
257 | } |
258 | |
259 | === modified file 'src/logic/map_objects/tribes/building.h' |
260 | --- src/logic/map_objects/tribes/building.h 2019-05-11 12:37:45 +0000 |
261 | +++ src/logic/map_objects/tribes/building.h 2019-06-19 09:23:26 +0000 |
262 | @@ -31,6 +31,7 @@ |
263 | #include "logic/map_objects/buildcost.h" |
264 | #include "logic/map_objects/immovable.h" |
265 | #include "logic/map_objects/tribes/attack_target.h" |
266 | +#include "logic/map_objects/tribes/building_settings.h" |
267 | #include "logic/map_objects/tribes/bill_of_materials.h" |
268 | #include "logic/map_objects/tribes/soldiercontrol.h" |
269 | #include "logic/map_objects/tribes/wareworker.h" |
270 | @@ -51,9 +52,9 @@ |
271 | |
272 | class Building; |
273 | |
274 | -#define LOW_PRIORITY 2 |
275 | -#define DEFAULT_PRIORITY 4 |
276 | -#define HIGH_PRIORITY 8 |
277 | +constexpr int32_t kPriorityLow = 2; |
278 | +constexpr int32_t kPriorityNormal = 4; |
279 | +constexpr int32_t kPriorityHigh = 8; |
280 | |
281 | /* |
282 | * Common to all buildings! |
283 | @@ -266,8 +267,8 @@ |
284 | |
285 | // Get/Set the priority for this waretype for this building. 'type' defines |
286 | // if this is for a worker or a ware, 'index' is the type of worker or ware. |
287 | - // If 'adjust' is false, the three possible states HIGH_PRIORITY, |
288 | - // DEFAULT_PRIORITY and LOW_PRIORITY are returned, otherwise numerical |
289 | + // If 'adjust' is false, the three possible states kPriorityHigh, |
290 | + // kPriorityNormal and kPriorityLow are returned, otherwise numerical |
291 | // values adjusted to the preciousness of the ware in general are returned. |
292 | virtual int32_t get_priority(WareWorker type, DescriptionIndex, bool adjust = true) const; |
293 | void set_priority(int32_t type, DescriptionIndex ware_index, int32_t new_priority); |
294 | @@ -301,6 +302,10 @@ |
295 | void add_worker(Worker&) override; |
296 | void remove_worker(Worker&) override; |
297 | |
298 | + virtual const BuildingSettings* create_building_settings() const { |
299 | + return nullptr; |
300 | + } |
301 | + |
302 | // AttackTarget object associated with this building. If the building can |
303 | // never be attacked (for example productionsites) this will be nullptr. |
304 | const AttackTarget* attack_target() const { |
305 | |
306 | === added file 'src/logic/map_objects/tribes/building_settings.cc' |
307 | --- src/logic/map_objects/tribes/building_settings.cc 1970-01-01 00:00:00 +0000 |
308 | +++ src/logic/map_objects/tribes/building_settings.cc 2019-06-19 09:23:26 +0000 |
309 | @@ -0,0 +1,346 @@ |
310 | +/* |
311 | + * Copyright (C) 2002-2019 by the Widelands Development Team |
312 | + * |
313 | + * This program is free software; you can redistribute it and/or |
314 | + * modify it under the terms of the GNU General Public License |
315 | + * as published by the Free Software Foundation; either version 2 |
316 | + * of the License, or (at your option) any later version. |
317 | + * |
318 | + * This program is distributed in the hope that it will be useful, |
319 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
320 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
321 | + * GNU General Public License for more details. |
322 | + * |
323 | + * You should have received a copy of the GNU General Public License |
324 | + * along with this program; if not, write to the Free Software |
325 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
326 | + * |
327 | + */ |
328 | + |
329 | +#include "logic/map_objects/tribes/building_settings.h" |
330 | + |
331 | +#include "io/fileread.h" |
332 | +#include "io/filewrite.h" |
333 | +#include "logic/game.h" |
334 | +#include "logic/game_data_error.h" |
335 | +#include "logic/map_objects/tribes/militarysite.h" |
336 | +#include "logic/map_objects/tribes/productionsite.h" |
337 | +#include "logic/map_objects/tribes/trainingsite.h" |
338 | +#include "logic/map_objects/tribes/tribe_descr.h" |
339 | +#include "logic/map_objects/tribes/warehouse.h" |
340 | + |
341 | +namespace Widelands { |
342 | + |
343 | +ProductionsiteSettings::ProductionsiteSettings(const ProductionSiteDescr& descr) |
344 | + : BuildingSettings(descr.name()), stopped(false) { |
345 | + for (const auto& pair : descr.input_wares()) { |
346 | + ware_queues.push_back(std::make_pair(pair.first, |
347 | + InputQueueSetting{pair.second, pair.second, kPriorityNormal})); |
348 | + } |
349 | + for (const auto& pair : descr.input_workers()) { |
350 | + worker_queues.push_back(std::make_pair(pair.first, |
351 | + InputQueueSetting{pair.second, pair.second, kPriorityNormal})); |
352 | + } |
353 | +} |
354 | + |
355 | +MilitarysiteSettings::MilitarysiteSettings(const MilitarySiteDescr& descr) |
356 | + : BuildingSettings(descr.name()), |
357 | + max_capacity(descr.get_max_number_of_soldiers()), |
358 | + desired_capacity(descr.get_max_number_of_soldiers()), |
359 | + prefer_heroes(descr.prefers_heroes_at_start_) { |
360 | +} |
361 | + |
362 | +TrainingsiteSettings::TrainingsiteSettings(const TrainingSiteDescr& descr) |
363 | + : ProductionsiteSettings(descr), |
364 | + max_capacity(descr.get_max_number_of_soldiers()), |
365 | + desired_capacity(descr.get_max_number_of_soldiers()) { |
366 | +} |
367 | + |
368 | +WarehouseSettings::WarehouseSettings(const WarehouseDescr& wh, const TribeDescr& tribe) |
369 | + : BuildingSettings(wh.name()), launch_expedition_allowed(wh.get_isport()), launch_expedition(false) { |
370 | + for (const DescriptionIndex di : tribe.wares()) { |
371 | + ware_preferences.emplace(di, StockPolicy::kNormal); |
372 | + } |
373 | + for (const DescriptionIndex di : tribe.workers()) { |
374 | + worker_preferences.emplace(di, StockPolicy::kNormal); |
375 | + } |
376 | + for (const DescriptionIndex di : tribe.worker_types_without_cost()) { |
377 | + worker_preferences.erase(di); |
378 | + } |
379 | +} |
380 | + |
381 | +void ProductionsiteSettings::apply(const BuildingSettings& bs) { |
382 | + BuildingSettings::apply(bs); |
383 | + if (upcast(const ProductionsiteSettings, s, &bs)) { |
384 | + stopped = s->stopped; |
385 | + for (auto& pair : ware_queues) { |
386 | + for (const auto& other : s->ware_queues) { |
387 | + if (pair.first == other.first) { |
388 | + pair.second.priority = other.second.priority; |
389 | + pair.second.desired_fill = std::min(pair.second.max_fill, other.second.desired_fill); |
390 | + break; |
391 | + } |
392 | + } |
393 | + } |
394 | + for (auto& pair : worker_queues) { |
395 | + for (const auto& other : s->worker_queues) { |
396 | + if (pair.first == other.first) { |
397 | + pair.second.priority = other.second.priority; |
398 | + pair.second.desired_fill = std::min(pair.second.max_fill, other.second.desired_fill); |
399 | + break; |
400 | + } |
401 | + } |
402 | + } |
403 | + } |
404 | +} |
405 | + |
406 | +void TrainingsiteSettings::apply(const BuildingSettings& bs) { |
407 | + ProductionsiteSettings::apply(bs); |
408 | + if (upcast(const TrainingsiteSettings, s, &bs)) { |
409 | + desired_capacity = std::min(max_capacity, s->desired_capacity); |
410 | + } |
411 | +} |
412 | + |
413 | +void MilitarysiteSettings::apply(const BuildingSettings& bs) { |
414 | + BuildingSettings::apply(bs); |
415 | + if (upcast(const MilitarysiteSettings, s, &bs)) { |
416 | + desired_capacity = std::min(max_capacity, s->desired_capacity); |
417 | + prefer_heroes = s->prefer_heroes; |
418 | + } |
419 | +} |
420 | + |
421 | +void WarehouseSettings::apply(const BuildingSettings& bs) { |
422 | + BuildingSettings::apply(bs); |
423 | + if (upcast(const WarehouseSettings, s, &bs)) { |
424 | + for (auto& pair : ware_preferences) { |
425 | + const auto it = s->ware_preferences.find(pair.first); |
426 | + if (it != s->ware_preferences.end()) { |
427 | + pair.second = it->second; |
428 | + } |
429 | + } |
430 | + for (auto& pair : worker_preferences) { |
431 | + const auto it = s->worker_preferences.find(pair.first); |
432 | + if (it != s->worker_preferences.end()) { |
433 | + pair.second = it->second; |
434 | + } |
435 | + } |
436 | + launch_expedition = launch_expedition_allowed && s->launch_expedition; |
437 | + } |
438 | +} |
439 | + |
440 | +// Saveloading |
441 | + |
442 | +constexpr uint8_t kCurrentPacketVersion = 1; |
443 | +constexpr uint8_t kCurrentPacketVersionMilitarysite = 1; |
444 | +constexpr uint8_t kCurrentPacketVersionProductionsite = 1; |
445 | +constexpr uint8_t kCurrentPacketVersionTrainingsite = 1; |
446 | +constexpr uint8_t kCurrentPacketVersionWarehouse = 1; |
447 | + |
448 | +enum class BuildingType : uint8_t { |
449 | + kWarehouse = 1, |
450 | + kProductionsite = 2, |
451 | + kTrainingsite = 3, |
452 | + kMilitarysite = 4, |
453 | +}; |
454 | + |
455 | +// static |
456 | +BuildingSettings* BuildingSettings::load(const Game& game, const TribeDescr& tribe, FileRead& fr) { |
457 | + try { |
458 | + const uint8_t packet_version = fr.unsigned_8(); |
459 | + if (packet_version == kCurrentPacketVersion) { |
460 | + const std::string name(fr.c_string()); |
461 | + const DescriptionIndex index = game.tribes().building_index(name); |
462 | + const BuildingType type = static_cast<BuildingType>(fr.unsigned_8()); |
463 | + BuildingSettings* result = nullptr; |
464 | + switch (type) { |
465 | + case BuildingType::kTrainingsite: { |
466 | + result = new TrainingsiteSettings(*dynamic_cast<const TrainingSiteDescr*>( |
467 | + game.tribes().get_building_descr(index))); |
468 | + break; |
469 | + } |
470 | + case BuildingType::kProductionsite: { |
471 | + result = new ProductionsiteSettings(*dynamic_cast<const ProductionSiteDescr*>( |
472 | + game.tribes().get_building_descr(index))); |
473 | + break; |
474 | + } |
475 | + case BuildingType::kMilitarysite: { |
476 | + result = new MilitarysiteSettings(*dynamic_cast<const MilitarySiteDescr*>( |
477 | + game.tribes().get_building_descr(index))); |
478 | + break; |
479 | + } |
480 | + case BuildingType::kWarehouse: { |
481 | + result = new WarehouseSettings(*dynamic_cast<const WarehouseDescr*>( |
482 | + game.tribes().get_building_descr(index)), tribe); |
483 | + break; |
484 | + } |
485 | + } |
486 | + if (!result) { |
487 | + throw wexception("Unknown building category %u (%s)", static_cast<uint8_t>(type), name.c_str()); |
488 | + } |
489 | + result->read(game, fr); |
490 | + return result; |
491 | + } else { |
492 | + throw UnhandledVersionError( |
493 | + "BuildingSettings_load", packet_version, kCurrentPacketVersion); |
494 | + } |
495 | + } catch (const WException& e) { |
496 | + throw GameDataError("BuildingSettings_load: %s", e.what()); |
497 | + } |
498 | + NEVER_HERE(); |
499 | +} |
500 | + |
501 | +void BuildingSettings::read(const Game&, FileRead&) { |
502 | + // Header was peeled away by load() |
503 | +} |
504 | + |
505 | +void BuildingSettings::save(const Game&, FileWrite& fw) const { |
506 | + fw.unsigned_8(kCurrentPacketVersion); |
507 | + fw.c_string(descr_.c_str()); |
508 | +} |
509 | + |
510 | +void MilitarysiteSettings::read(const Game& game, FileRead& fr) { |
511 | + BuildingSettings::read(game, fr); |
512 | + try { |
513 | + const uint8_t packet_version = fr.unsigned_8(); |
514 | + if (packet_version == kCurrentPacketVersionMilitarysite) { |
515 | + desired_capacity = fr.unsigned_32(); |
516 | + prefer_heroes = fr.unsigned_8(); |
517 | + } else { |
518 | + throw UnhandledVersionError( |
519 | + "MilitarysiteSettings", packet_version, kCurrentPacketVersionMilitarysite); |
520 | + } |
521 | + } catch (const WException& e) { |
522 | + throw GameDataError("MilitarysiteSettings: %s", e.what()); |
523 | + } |
524 | +} |
525 | + |
526 | +void MilitarysiteSettings::save(const Game& game, FileWrite& fw) const { |
527 | + BuildingSettings::save(game, fw); |
528 | + fw.unsigned_8(static_cast<uint8_t>(BuildingType::kMilitarysite)); |
529 | + fw.unsigned_8(kCurrentPacketVersionMilitarysite); |
530 | + |
531 | + fw.unsigned_32(desired_capacity); |
532 | + fw.unsigned_8(prefer_heroes ? 1 : 0); |
533 | +} |
534 | + |
535 | +void ProductionsiteSettings::read(const Game& game, FileRead& fr) { |
536 | + BuildingSettings::read(game, fr); |
537 | + try { |
538 | + const uint8_t packet_version = fr.unsigned_8(); |
539 | + if (packet_version == kCurrentPacketVersionProductionsite) { |
540 | + stopped = fr.unsigned_8(); |
541 | + const uint32_t nr_wares = fr.unsigned_32(); |
542 | + const uint32_t nr_workers = fr.unsigned_32(); |
543 | + for (uint32_t i = 0; i < nr_wares; ++i) { |
544 | + const DescriptionIndex di = fr.unsigned_32(); |
545 | + const uint32_t fill = fr.unsigned_32(); |
546 | + const int32_t priority = fr.signed_32(); |
547 | + ware_queues.at(i).first = di; |
548 | + ware_queues.at(i).second.desired_fill = fill; |
549 | + ware_queues.at(i).second.priority = priority; |
550 | + } |
551 | + for (uint32_t i = 0; i < nr_workers; ++i) { |
552 | + const DescriptionIndex di = fr.unsigned_32(); |
553 | + const uint32_t fill = fr.unsigned_32(); |
554 | + const int32_t priority = fr.signed_32(); |
555 | + worker_queues.at(i).first = di; |
556 | + worker_queues.at(i).second.desired_fill = fill; |
557 | + worker_queues.at(i).second.priority = priority; |
558 | + } |
559 | + } else { |
560 | + throw UnhandledVersionError( |
561 | + "ProductionsiteSettings", packet_version, kCurrentPacketVersionProductionsite); |
562 | + } |
563 | + } catch (const WException& e) { |
564 | + throw GameDataError("ProductionsiteSettings: %s", e.what()); |
565 | + } |
566 | +} |
567 | + |
568 | +void ProductionsiteSettings::save(const Game& game, FileWrite& fw) const { |
569 | + BuildingSettings::save(game, fw); |
570 | + fw.unsigned_8(static_cast<uint8_t>(BuildingType::kProductionsite)); |
571 | + fw.unsigned_8(kCurrentPacketVersionProductionsite); |
572 | + |
573 | + fw.unsigned_8(stopped ? 1 : 0); |
574 | + fw.unsigned_32(ware_queues.size()); |
575 | + fw.unsigned_32(worker_queues.size()); |
576 | + for (const auto& pair : ware_queues) { |
577 | + fw.unsigned_32(pair.first); |
578 | + fw.unsigned_32(pair.second.desired_fill); |
579 | + fw.signed_32(pair.second.priority); |
580 | + } |
581 | + for (const auto& pair : worker_queues) { |
582 | + fw.unsigned_32(pair.first); |
583 | + fw.unsigned_32(pair.second.desired_fill); |
584 | + fw.signed_32(pair.second.priority); |
585 | + } |
586 | +} |
587 | + |
588 | +void TrainingsiteSettings::read(const Game& game, FileRead& fr) { |
589 | + ProductionsiteSettings::read(game, fr); |
590 | + try { |
591 | + const uint8_t packet_version = fr.unsigned_8(); |
592 | + if (packet_version == kCurrentPacketVersionTrainingsite) { |
593 | + desired_capacity = fr.unsigned_32(); |
594 | + } else { |
595 | + throw UnhandledVersionError( |
596 | + "TrainingsiteSettings", packet_version, kCurrentPacketVersionTrainingsite); |
597 | + } |
598 | + } catch (const WException& e) { |
599 | + throw GameDataError("TrainingsiteSettings: %s", e.what()); |
600 | + } |
601 | +} |
602 | + |
603 | +void TrainingsiteSettings::save(const Game& game, FileWrite& fw) const { |
604 | + ProductionsiteSettings::save(game, fw); |
605 | + fw.unsigned_8(static_cast<uint8_t>(BuildingType::kTrainingsite)); |
606 | + fw.unsigned_8(kCurrentPacketVersionTrainingsite); |
607 | + fw.unsigned_32(desired_capacity); |
608 | +} |
609 | + |
610 | +void WarehouseSettings::read(const Game& game, FileRead& fr) { |
611 | + BuildingSettings::read(game, fr); |
612 | + try { |
613 | + const uint8_t packet_version = fr.unsigned_8(); |
614 | + if (packet_version == kCurrentPacketVersionWarehouse) { |
615 | + launch_expedition = fr.unsigned_8(); |
616 | + const uint32_t nr_wares = fr.unsigned_32(); |
617 | + const uint32_t nr_workers = fr.unsigned_32(); |
618 | + for (uint32_t i = 0; i < nr_wares; ++i) { |
619 | + const DescriptionIndex di = fr.unsigned_32(); |
620 | + const uint8_t pref = fr.unsigned_8(); |
621 | + ware_preferences[di] = static_cast<StockPolicy>(pref); |
622 | + } |
623 | + for (uint32_t i = 0; i < nr_workers; ++i) { |
624 | + const DescriptionIndex di = fr.unsigned_32(); |
625 | + const uint8_t pref = fr.unsigned_8(); |
626 | + worker_preferences[di] = static_cast<StockPolicy>(pref); |
627 | + } |
628 | + } else { |
629 | + throw UnhandledVersionError( |
630 | + "WarehouseSettings", packet_version, kCurrentPacketVersionWarehouse); |
631 | + } |
632 | + } catch (const WException& e) { |
633 | + throw GameDataError("WarehouseSettings: %s", e.what()); |
634 | + } |
635 | +} |
636 | + |
637 | +void WarehouseSettings::save(const Game& game, FileWrite& fw) const { |
638 | + BuildingSettings::save(game, fw); |
639 | + fw.unsigned_8(static_cast<uint8_t>(BuildingType::kWarehouse)); |
640 | + fw.unsigned_8(kCurrentPacketVersionWarehouse); |
641 | + |
642 | + fw.unsigned_8(launch_expedition ? 1 : 0); |
643 | + fw.unsigned_32(ware_preferences.size()); |
644 | + fw.unsigned_32(worker_preferences.size()); |
645 | + for (const auto& pair : ware_preferences) { |
646 | + fw.unsigned_32(pair.first); |
647 | + fw.unsigned_8(static_cast<uint8_t>(pair.second)); |
648 | + } |
649 | + for (const auto& pair : worker_preferences) { |
650 | + fw.unsigned_32(pair.first); |
651 | + fw.unsigned_8(static_cast<uint8_t>(pair.second)); |
652 | + } |
653 | +} |
654 | + |
655 | +} // namespace Widelands |
656 | |
657 | === added file 'src/logic/map_objects/tribes/building_settings.h' |
658 | --- src/logic/map_objects/tribes/building_settings.h 1970-01-01 00:00:00 +0000 |
659 | +++ src/logic/map_objects/tribes/building_settings.h 2019-06-19 09:23:26 +0000 |
660 | @@ -0,0 +1,123 @@ |
661 | +/* |
662 | + * Copyright (C) 2002-2019 by the Widelands Development Team |
663 | + * |
664 | + * This program is free software; you can redistribute it and/or |
665 | + * modify it under the terms of the GNU General Public License |
666 | + * as published by the Free Software Foundation; either version 2 |
667 | + * of the License, or (at your option) any later version. |
668 | + * |
669 | + * This program is distributed in the hope that it will be useful, |
670 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
671 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
672 | + * GNU General Public License for more details. |
673 | + * |
674 | + * You should have received a copy of the GNU General Public License |
675 | + * along with this program; if not, write to the Free Software |
676 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
677 | + * |
678 | + */ |
679 | + |
680 | +#ifndef WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_SETTINGS_H |
681 | +#define WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_SETTINGS_H |
682 | + |
683 | +#include <map> |
684 | +#include <string> |
685 | +#include <vector> |
686 | + |
687 | +#include "logic/widelands.h" |
688 | + |
689 | +class FileRead; |
690 | +class FileWrite; |
691 | + |
692 | +namespace Widelands { |
693 | + |
694 | +class Game; |
695 | +class MilitarySiteDescr; |
696 | +class ProductionSiteDescr; |
697 | +enum class StockPolicy; |
698 | +class TrainingSiteDescr; |
699 | +class TribeDescr; |
700 | +class WarehouseDescr; |
701 | + |
702 | +struct BuildingSettings { |
703 | + BuildingSettings(const std::string& name) : descr_(name) { |
704 | + } |
705 | + virtual ~BuildingSettings() { |
706 | + } |
707 | + |
708 | + static BuildingSettings* load(const Game&, const TribeDescr&, FileRead&); |
709 | + |
710 | + virtual void save(const Game&, FileWrite&) const; |
711 | + virtual void read(const Game&, FileRead&); |
712 | + |
713 | + virtual void apply(const BuildingSettings&) { |
714 | + } |
715 | + |
716 | +private: |
717 | + const std::string descr_; |
718 | +}; |
719 | + |
720 | +struct ProductionsiteSettings : public BuildingSettings { |
721 | + ProductionsiteSettings(const ProductionSiteDescr& descr); |
722 | + ~ProductionsiteSettings() override { |
723 | + } |
724 | + void apply(const BuildingSettings&) override; |
725 | + |
726 | + void save(const Game&, FileWrite&) const override; |
727 | + void read(const Game&, FileRead&) override; |
728 | + |
729 | + struct InputQueueSetting { |
730 | + const uint32_t max_fill; |
731 | + uint32_t desired_fill; |
732 | + int32_t priority; |
733 | + }; |
734 | + std::vector<std::pair<DescriptionIndex, InputQueueSetting>> ware_queues; |
735 | + std::vector<std::pair<DescriptionIndex, InputQueueSetting>> worker_queues; |
736 | + bool stopped; |
737 | +}; |
738 | + |
739 | +struct MilitarysiteSettings : public BuildingSettings { |
740 | + MilitarysiteSettings(const MilitarySiteDescr&); |
741 | + ~MilitarysiteSettings() override { |
742 | + } |
743 | + void apply(const BuildingSettings&) override; |
744 | + |
745 | + void save(const Game&, FileWrite&) const override; |
746 | + void read(const Game&, FileRead&) override; |
747 | + |
748 | + const uint32_t max_capacity; |
749 | + uint32_t desired_capacity; |
750 | + bool prefer_heroes; |
751 | +}; |
752 | + |
753 | +struct TrainingsiteSettings : public ProductionsiteSettings { |
754 | + TrainingsiteSettings(const TrainingSiteDescr&); |
755 | + ~TrainingsiteSettings() override { |
756 | + } |
757 | + void apply(const BuildingSettings&) override; |
758 | + |
759 | + void save(const Game&, FileWrite&) const override; |
760 | + void read(const Game&, FileRead&) override; |
761 | + |
762 | + const uint32_t max_capacity; |
763 | + uint32_t desired_capacity; |
764 | +}; |
765 | + |
766 | +struct WarehouseSettings : public BuildingSettings { |
767 | + WarehouseSettings(const WarehouseDescr&, const TribeDescr&); |
768 | + ~WarehouseSettings() override { |
769 | + } |
770 | + void apply(const BuildingSettings&) override; |
771 | + |
772 | + void save(const Game&, FileWrite&) const override; |
773 | + void read(const Game&, FileRead&) override; |
774 | + |
775 | + std::map<DescriptionIndex, StockPolicy> ware_preferences; |
776 | + std::map<DescriptionIndex, StockPolicy> worker_preferences; |
777 | + const bool launch_expedition_allowed; |
778 | + bool launch_expedition; |
779 | +}; |
780 | + |
781 | +} // namespace Widelands |
782 | + |
783 | +#endif // end of include guard: WL_LOGIC_MAP_OBJECTS_TRIBES_BUILDING_SETTINGS_H |
784 | |
785 | === modified file 'src/logic/map_objects/tribes/constructionsite.cc' |
786 | --- src/logic/map_objects/tribes/constructionsite.cc 2019-05-26 17:21:15 +0000 |
787 | +++ src/logic/map_objects/tribes/constructionsite.cc 2019-06-19 09:23:26 +0000 |
788 | @@ -32,6 +32,11 @@ |
789 | #include "graphic/rendertarget.h" |
790 | #include "logic/editor_game_base.h" |
791 | #include "logic/game.h" |
792 | +#include "logic/game_data_error.h" |
793 | +#include "logic/map_objects/tribes/militarysite.h" |
794 | +#include "logic/map_objects/tribes/partially_finished_building.h" |
795 | +#include "logic/map_objects/tribes/productionsite.h" |
796 | +#include "logic/map_objects/tribes/trainingsite.h" |
797 | #include "logic/map_objects/tribes/tribe_descr.h" |
798 | #include "logic/map_objects/tribes/worker.h" |
799 | #include "sound/note_sound.h" |
800 | @@ -46,32 +51,61 @@ |
801 | const RGBColor& player_color, |
802 | RenderTarget* dst) const { |
803 | // Draw the construction site marker |
804 | - const uint32_t anim_idx = becomes->is_animation_known("build") ? |
805 | - becomes->get_animation("build", nullptr) : |
806 | - becomes->get_unoccupied_animation(); |
807 | - |
808 | - const Animation& anim = g_gr->animations().get_animation(anim_idx); |
809 | - const size_t nr_frames = anim.nr_frames(); |
810 | - const uint32_t cur_frame = totaltime ? completedtime * nr_frames / totaltime : 0; |
811 | - uint32_t anim_time = cur_frame * FRAME_LENGTH; |
812 | - |
813 | - if (cur_frame) { // not the first pic |
814 | - // Draw the complete prev pic , so we won't run into trouble if images have different sizes |
815 | - dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, anim_idx, |
816 | - anim_time - FRAME_LENGTH, &player_color); |
817 | + std::vector<std::pair<uint32_t, uint32_t>> animations; |
818 | + uint32_t total_frames = 0; |
819 | + auto push_animation = [](const BuildingDescr* d, std::vector<std::pair<uint32_t, uint32_t>>* anims, uint32_t* tf) { |
820 | + const bool known = d->is_animation_known("build"); |
821 | + const uint32_t anim_idx = known ? |
822 | + d->get_animation("build", nullptr) : |
823 | + d->get_unoccupied_animation(); |
824 | + // If there is no build animation, we use only the first frame or we |
825 | + // would get many build steps with almost the same image... |
826 | + const uint32_t nrframes = known ? g_gr->animations().get_animation(anim_idx).nr_frames() : 1; |
827 | + assert(nrframes); |
828 | + *tf += nrframes; |
829 | + anims->push_back(std::make_pair(anim_idx, nrframes)); |
830 | + }; |
831 | + for (const BuildingDescr* d : intermediates) { |
832 | + push_animation(d, &animations, &total_frames); |
833 | + } |
834 | + push_animation(becomes, &animations, &total_frames); |
835 | + |
836 | + uint32_t frame_index = totaltime ? std::min(completedtime * total_frames / totaltime, total_frames - 1) : 0; |
837 | + uint32_t animation_index = 0; |
838 | + while (frame_index >= animations[animation_index].second) { |
839 | + frame_index -= animations[animation_index].second; |
840 | + ++animation_index; |
841 | + assert(animation_index < animations.size()); |
842 | + } |
843 | + const uint32_t anim_time = frame_index * FRAME_LENGTH; |
844 | + |
845 | + if (frame_index > 0) { |
846 | + // Not the first pic within this animation – draw the previous one |
847 | + dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, |
848 | + animations[animation_index].first, anim_time - FRAME_LENGTH, &player_color); |
849 | + } else if (animation_index > 0) { |
850 | + // The first pic, but not the first series of animations – draw the last pic of the previous series |
851 | + dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, |
852 | + animations[animation_index - 1].first, |
853 | + FRAME_LENGTH * (animations[animation_index - 1].second - 1), &player_color); |
854 | } else if (was) { |
855 | - // Is the first picture but there was another building here before, |
856 | - // get its most fitting picture and draw it instead. |
857 | - dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, |
858 | - was->get_unoccupied_animation(), anim_time - FRAME_LENGTH, &player_color); |
859 | + // First pic in first series, but there was another building here before – |
860 | + // get its most fitting picture and draw it instead |
861 | + const uint32_t unocc = was->get_unoccupied_animation(); |
862 | + dst->blit_animation(point_on_dst, Widelands::Coords::null(), scale, unocc, |
863 | + FRAME_LENGTH * (g_gr->animations().get_animation(unocc).nr_frames() - 1), |
864 | + &player_color); |
865 | } |
866 | // Now blit a segment of the current construction phase from the bottom. |
867 | - int percent = 100 * completedtime * nr_frames; |
868 | + int percent = 100 * completedtime * total_frames; |
869 | if (totaltime) { |
870 | percent /= totaltime; |
871 | } |
872 | - percent -= 100 * cur_frame; |
873 | - dst->blit_animation(point_on_dst, coords, scale, anim_idx, anim_time, &player_color, percent); |
874 | + percent -= 100 * frame_index; |
875 | + for (uint32_t i = 0; i < animation_index; ++i) { |
876 | + percent -= 100 * animations[i].second; |
877 | + } |
878 | + dst->blit_animation(point_on_dst, coords, scale, animations[animation_index].first, anim_time, &player_color, percent); |
879 | } |
880 | |
881 | /** |
882 | @@ -104,7 +138,7 @@ |
883 | */ |
884 | |
885 | ConstructionSite::ConstructionSite(const ConstructionSiteDescr& cs_descr) |
886 | - : PartiallyFinishedBuilding(cs_descr), fetchfromflag_(0), builder_idle_(false) { |
887 | + : PartiallyFinishedBuilding(cs_descr), fetchfromflag_(0), builder_idle_(false), settings_(nullptr) { |
888 | } |
889 | |
890 | void ConstructionSite::update_statistics_string(std::string* s) { |
891 | @@ -181,9 +215,30 @@ |
892 | |
893 | work_steps_ += it->second; |
894 | } |
895 | + |
896 | + init_settings(); |
897 | + |
898 | return true; |
899 | } |
900 | |
901 | +void ConstructionSite::init_settings() { |
902 | + assert(building_); |
903 | + assert(!settings_); |
904 | + if (upcast(const WarehouseDescr, wd, building_)) { |
905 | + settings_.reset(new WarehouseSettings(*wd, owner().tribe())); |
906 | + } else if (upcast(const TrainingSiteDescr, td, building_)) { |
907 | + settings_.reset(new TrainingsiteSettings(*td)); |
908 | + } else if (upcast(const ProductionSiteDescr, pd, building_)) { |
909 | + settings_.reset(new ProductionsiteSettings(*pd)); |
910 | + } else if (upcast(const MilitarySiteDescr, md, building_)) { |
911 | + settings_.reset(new MilitarysiteSettings(*md)); |
912 | + } else { |
913 | + // TODO(Nordfriese): Add support for markets when trading is implemented |
914 | + log("WARNING: Created constructionsite for a %s, which is not of any known building type\n", |
915 | + building_->name().c_str()); |
916 | + } |
917 | +} |
918 | + |
919 | /* |
920 | =============== |
921 | Release worker and material (if any is left). |
922 | @@ -207,6 +262,52 @@ |
923 | builder->reset_tasks(dynamic_cast<Game&>(egbase)); |
924 | builder->set_location(&b); |
925 | } |
926 | + |
927 | + // Apply settings |
928 | + if (settings_) { |
929 | + if (upcast(ProductionsiteSettings, ps, settings_.get())) { |
930 | + for (const auto& pair : ps->ware_queues) { |
931 | + b.inputqueue(pair.first, wwWARE).set_max_fill(pair.second.desired_fill); |
932 | + b.set_priority(wwWARE, pair.first, pair.second.priority); |
933 | + } |
934 | + for (const auto& pair : ps->worker_queues) { |
935 | + b.inputqueue(pair.first, wwWORKER).set_max_fill(pair.second.desired_fill); |
936 | + b.set_priority(wwWORKER, pair.first, pair.second.priority); |
937 | + } |
938 | + if (upcast(TrainingsiteSettings, ts, ps)) { |
939 | + assert(b.soldier_control()); |
940 | + assert(ts->desired_capacity >= b.soldier_control()->min_soldier_capacity()); |
941 | + assert(ts->desired_capacity <= b.soldier_control()->max_soldier_capacity()); |
942 | + if (ts->desired_capacity != b.soldier_control()->soldier_capacity()) { |
943 | + b.mutable_soldier_control()->set_soldier_capacity(ts->desired_capacity); |
944 | + } |
945 | + } |
946 | + dynamic_cast<ProductionSite&>(b).set_stopped(ps->stopped); |
947 | + } else if (upcast(MilitarysiteSettings, ms, settings_.get())) { |
948 | + assert(b.soldier_control()); |
949 | + assert(ms->desired_capacity >= b.soldier_control()->min_soldier_capacity()); |
950 | + assert(ms->desired_capacity <= b.soldier_control()->max_soldier_capacity()); |
951 | + if (ms->desired_capacity != b.soldier_control()->soldier_capacity()) { |
952 | + b.mutable_soldier_control()->set_soldier_capacity(ms->desired_capacity); |
953 | + } |
954 | + dynamic_cast<MilitarySite&>(b).set_soldier_preference(ms->prefer_heroes ? |
955 | + SoldierPreference::kHeroes : SoldierPreference::kRookies); |
956 | + } else if (upcast(WarehouseSettings, ws, settings_.get())) { |
957 | + Warehouse& site = dynamic_cast<Warehouse&>(b); |
958 | + for (const auto& pair : ws->ware_preferences) { |
959 | + site.set_ware_policy(pair.first, pair.second); |
960 | + } |
961 | + for (const auto& pair : ws->worker_preferences) { |
962 | + site.set_worker_policy(pair.first, pair.second); |
963 | + } |
964 | + if (ws->launch_expedition) { |
965 | + get_owner()->start_or_cancel_expedition(site); |
966 | + } |
967 | + } else { |
968 | + NEVER_HERE(); |
969 | + } |
970 | + } |
971 | + |
972 | // Open the new building window if needed |
973 | Notifications::publish(NoteBuilding(b.serial(), NoteBuilding::Action::kFinishWarp)); |
974 | } |
975 | @@ -214,6 +315,138 @@ |
976 | |
977 | /* |
978 | =============== |
979 | +Start building the next enhancement even before the base building is completed. |
980 | +=============== |
981 | +*/ |
982 | +void ConstructionSite::enhance(Game&) { |
983 | + assert(building_->enhancement() != INVALID_INDEX); |
984 | + Notifications::publish(NoteImmovable(this, NoteImmovable::Ownership::LOST)); |
985 | + |
986 | + info_.intermediates.push_back(building_); |
987 | + old_buildings_.push_back(owner().tribe().building_index(building_->name())); |
988 | + building_ = owner().tribe().get_building_descr(building_->enhancement()); |
989 | + assert(building_); |
990 | + info_.becomes = building_; |
991 | + |
992 | + const std::map<DescriptionIndex, uint8_t>& buildcost = building_->enhancement_cost(); |
993 | + std::set<DescriptionIndex> new_ware_types; |
994 | + for (const auto& pair : buildcost) { |
995 | + bool found = false; |
996 | + for (const auto& queue : wares_) { |
997 | + if (queue->get_index() == pair.first) { |
998 | + found = true; |
999 | + break; |
1000 | + } |
1001 | + } |
1002 | + if (!found) { |
1003 | + new_ware_types.insert(pair.first); |
1004 | + } |
1005 | + } |
1006 | + |
1007 | + const size_t old_size = wares_.size(); |
1008 | + wares_.resize(old_size + new_ware_types.size()); |
1009 | + |
1010 | + size_t new_index = 0; |
1011 | + for (const auto& pair : buildcost) { |
1012 | + if (new_ware_types.count(pair.first)) { |
1013 | + WaresQueue& wq = *(wares_[old_size + new_index] = new WaresQueue(*this, pair.first, pair.second)); |
1014 | + wq.set_callback(ConstructionSite::wares_queue_callback, this); |
1015 | + wq.set_consume_interval(CONSTRUCTIONSITE_STEP_TIME); |
1016 | + ++new_index; |
1017 | + } else { |
1018 | + for (size_t i = 0; i < old_size; ++i) { |
1019 | + WaresQueue& wq = *wares_[i]; |
1020 | + if (wq.get_index() == pair.first) { |
1021 | + wq.set_max_size(wq.get_max_size() + pair.second); |
1022 | + wq.set_max_fill(wq.get_max_fill() + pair.second); |
1023 | + break; |
1024 | + } |
1025 | + } |
1026 | + } |
1027 | + work_steps_ += pair.second; |
1028 | + } |
1029 | + |
1030 | + BuildingSettings* old_settings = settings_.release(); |
1031 | + if (upcast(const WarehouseDescr, wd, building_)) { |
1032 | + upcast(WarehouseSettings, ws, old_settings); |
1033 | + assert(ws); |
1034 | + WarehouseSettings* new_settings = new WarehouseSettings(*wd, owner().tribe()); |
1035 | + settings_.reset(new_settings); |
1036 | + for (const auto& pair : ws->ware_preferences) { |
1037 | + new_settings->ware_preferences[pair.first] = pair.second; |
1038 | + } |
1039 | + for (const auto& pair : ws->worker_preferences) { |
1040 | + new_settings->worker_preferences[pair.first] = pair.second; |
1041 | + } |
1042 | + new_settings->launch_expedition = ws->launch_expedition && building_->get_isport(); |
1043 | + } else if (upcast(const TrainingSiteDescr, td, building_)) { |
1044 | + upcast(TrainingsiteSettings, ts, old_settings); |
1045 | + assert(ts); |
1046 | + TrainingsiteSettings* new_settings = new TrainingsiteSettings(*td); |
1047 | + settings_.reset(new_settings); |
1048 | + new_settings->stopped = ts->stopped; |
1049 | + for (const auto& pair_old : ts->ware_queues) { |
1050 | + for (auto& pair_new : new_settings->ware_queues) { |
1051 | + if (pair_new.first == pair_old.first) { |
1052 | + pair_new.second.priority = pair_old.second.priority; |
1053 | + pair_new.second.desired_fill = std::min(pair_old.second.desired_fill, pair_new.second.max_fill); |
1054 | + break; |
1055 | + } |
1056 | + } |
1057 | + } |
1058 | + for (const auto& pair_old : ts->worker_queues) { |
1059 | + for (auto& pair_new : new_settings->worker_queues) { |
1060 | + if (pair_new.first == pair_old.first) { |
1061 | + pair_new.second.priority = pair_old.second.priority; |
1062 | + pair_new.second.desired_fill = std::min(pair_old.second.desired_fill, pair_new.second.max_fill); |
1063 | + break; |
1064 | + } |
1065 | + } |
1066 | + } |
1067 | + new_settings->desired_capacity = std::min(new_settings->max_capacity, ts->desired_capacity); |
1068 | + } else if (upcast(const ProductionSiteDescr, pd, building_)) { |
1069 | + upcast(ProductionsiteSettings, ps, old_settings); |
1070 | + assert(ps); |
1071 | + ProductionsiteSettings* new_settings = new ProductionsiteSettings(*pd); |
1072 | + settings_.reset(new_settings); |
1073 | + new_settings->stopped = ps->stopped; |
1074 | + for (const auto& pair_old : ps->ware_queues) { |
1075 | + for (auto& pair_new : new_settings->ware_queues) { |
1076 | + if (pair_new.first == pair_old.first) { |
1077 | + pair_new.second.priority = pair_old.second.priority; |
1078 | + pair_new.second.desired_fill = std::min(pair_old.second.desired_fill, pair_new.second.max_fill); |
1079 | + break; |
1080 | + } |
1081 | + } |
1082 | + } |
1083 | + for (const auto& pair_old : ps->worker_queues) { |
1084 | + for (auto& pair_new : new_settings->worker_queues) { |
1085 | + if (pair_new.first == pair_old.first) { |
1086 | + pair_new.second.priority = pair_old.second.priority; |
1087 | + pair_new.second.desired_fill = std::min(pair_old.second.desired_fill, pair_new.second.max_fill); |
1088 | + break; |
1089 | + } |
1090 | + } |
1091 | + } |
1092 | + } else if (upcast(const MilitarySiteDescr, md, building_)) { |
1093 | + upcast(MilitarysiteSettings, ms, old_settings); |
1094 | + assert(ms); |
1095 | + MilitarysiteSettings* new_settings = new MilitarysiteSettings(*md); |
1096 | + settings_.reset(new_settings); |
1097 | + new_settings->desired_capacity = std::max<uint32_t>(1, std::min<uint32_t>( |
1098 | + new_settings->max_capacity, ms->desired_capacity)); |
1099 | + new_settings->prefer_heroes = ms->prefer_heroes; |
1100 | + } else { |
1101 | + // TODO(Nordfriese): Add support for markets when trading is implemented |
1102 | + log("WARNING: Enhanced constructionsite to a %s, which is not of any known building type\n", |
1103 | + building_->name().c_str()); |
1104 | + } |
1105 | + Notifications::publish(NoteImmovable(this, NoteImmovable::Ownership::GAINED)); |
1106 | + Notifications::publish(NoteBuilding(serial(), NoteBuilding::Action::kChanged)); |
1107 | +} |
1108 | + |
1109 | +/* |
1110 | +=============== |
1111 | Construction sites only burn if some of the work has been completed. |
1112 | =============== |
1113 | */ |
1114 | @@ -343,6 +576,17 @@ |
1115 | |
1116 | /* |
1117 | =============== |
1118 | +Overwrite as many values of the current settings with those of the given settings as possible. |
1119 | +=============== |
1120 | +*/ |
1121 | +void ConstructionSite::apply_settings(const BuildingSettings& cs) { |
1122 | + assert(settings_); |
1123 | + settings_->apply(cs); |
1124 | + delete &cs; |
1125 | +} |
1126 | + |
1127 | +/* |
1128 | +=============== |
1129 | Draw the construction site. |
1130 | =============== |
1131 | */ |
1132 | |
1133 | === modified file 'src/logic/map_objects/tribes/constructionsite.h' |
1134 | --- src/logic/map_objects/tribes/constructionsite.h 2019-05-05 14:05:07 +0000 |
1135 | +++ src/logic/map_objects/tribes/constructionsite.h 2019-06-19 09:23:26 +0000 |
1136 | @@ -20,16 +20,26 @@ |
1137 | #ifndef WL_LOGIC_MAP_OBJECTS_TRIBES_CONSTRUCTIONSITE_H |
1138 | #define WL_LOGIC_MAP_OBJECTS_TRIBES_CONSTRUCTIONSITE_H |
1139 | |
1140 | +#include <memory> |
1141 | #include <vector> |
1142 | |
1143 | #include "base/macros.h" |
1144 | +#include "logic/map_objects/tribes/building_settings.h" |
1145 | #include "logic/map_objects/tribes/partially_finished_building.h" |
1146 | #include "scripting/lua_table.h" |
1147 | |
1148 | +class FileRead; |
1149 | +class FileWrite; |
1150 | + |
1151 | namespace Widelands { |
1152 | |
1153 | class Building; |
1154 | +class MilitarySiteDescr; |
1155 | +class ProductionSiteDescr; |
1156 | class Request; |
1157 | +enum class StockPolicy; |
1158 | +class TrainingSiteDescr; |
1159 | +class WarehouseDescr; |
1160 | class WaresQueue; |
1161 | |
1162 | /// Per-player and per-field constructionsite information |
1163 | @@ -47,6 +57,7 @@ |
1164 | const BuildingDescr* |
1165 | becomes; // Also works as a marker telling whether there is a construction site. |
1166 | const BuildingDescr* was; // only valid if "becomes" is an enhanced building. |
1167 | + std::vector<const BuildingDescr*> intermediates; // If we enhance a building while it's still under construction |
1168 | uint32_t totaltime; |
1169 | uint32_t completedtime; |
1170 | }; |
1171 | @@ -114,6 +125,13 @@ |
1172 | bool fetch_from_flag(Game&) override; |
1173 | bool get_building_work(Game&, Worker&, bool success) override; |
1174 | |
1175 | + BuildingSettings* get_settings() const { |
1176 | + return settings_.get(); |
1177 | + } |
1178 | + void apply_settings(const BuildingSettings&); |
1179 | + |
1180 | + void enhance(Game&); |
1181 | + |
1182 | protected: |
1183 | void update_statistics_string(std::string* statistics_string) override; |
1184 | |
1185 | @@ -135,6 +153,9 @@ |
1186 | |
1187 | bool builder_idle_; // used to determine whether the builder is idle |
1188 | ConstructionsiteInformation info_; // asked for by player point of view for the gameview |
1189 | + |
1190 | + std::unique_ptr<BuildingSettings> settings_; |
1191 | + void init_settings(); |
1192 | }; |
1193 | } // namespace Widelands |
1194 | |
1195 | |
1196 | === modified file 'src/logic/map_objects/tribes/militarysite.cc' |
1197 | --- src/logic/map_objects/tribes/militarysite.cc 2019-05-26 17:21:15 +0000 |
1198 | +++ src/logic/map_objects/tribes/militarysite.cc 2019-06-19 09:23:26 +0000 |
1199 | @@ -982,6 +982,13 @@ |
1200 | return false; |
1201 | } |
1202 | |
1203 | +const BuildingSettings* MilitarySite::create_building_settings() const { |
1204 | + MilitarysiteSettings* settings = new MilitarysiteSettings(descr()); |
1205 | + settings->desired_capacity = std::min(settings->max_capacity, soldier_control_.soldier_capacity()); |
1206 | + settings->prefer_heroes = soldier_preference_ == SoldierPreference::kHeroes; |
1207 | + return settings; |
1208 | +} |
1209 | + |
1210 | // setters |
1211 | |
1212 | void MilitarySite::set_soldier_preference(SoldierPreference p) { |
1213 | |
1214 | === modified file 'src/logic/map_objects/tribes/militarysite.h' |
1215 | --- src/logic/map_objects/tribes/militarysite.h 2019-05-05 14:05:07 +0000 |
1216 | +++ src/logic/map_objects/tribes/militarysite.h 2019-06-19 09:23:26 +0000 |
1217 | @@ -108,6 +108,8 @@ |
1218 | return soldier_preference_; |
1219 | } |
1220 | |
1221 | + const BuildingSettings* create_building_settings() const override; |
1222 | + |
1223 | protected: |
1224 | void conquer_area(EditorGameBase&); |
1225 | |
1226 | |
1227 | === modified file 'src/logic/map_objects/tribes/productionsite.cc' |
1228 | --- src/logic/map_objects/tribes/productionsite.cc 2019-05-29 07:14:00 +0000 |
1229 | +++ src/logic/map_objects/tribes/productionsite.cc 2019-06-19 09:23:26 +0000 |
1230 | @@ -445,13 +445,12 @@ |
1231 | const BillOfMaterials& input_workers = descr().input_workers(); |
1232 | input_queues_.resize(input_wares.size() + input_workers.size()); |
1233 | |
1234 | - for (WareRange i(input_wares); i; ++i) { |
1235 | - input_queues_[i.i] = new WaresQueue(*this, i.current->first, i.current->second); |
1236 | + size_t i = 0; |
1237 | + for (const WareAmount& pair : input_wares) { |
1238 | + input_queues_[i++] = new WaresQueue(*this, pair.first, pair.second); |
1239 | } |
1240 | - |
1241 | - for (WareRange i(input_workers); i; ++i) { |
1242 | - input_queues_[input_wares.size() + i.i] = |
1243 | - new WorkersQueue(*this, i.current->first, i.current->second); |
1244 | + for (const WareAmount& pair : input_workers) { |
1245 | + input_queues_[i++] = new WorkersQueue(*this, pair.first, pair.second); |
1246 | } |
1247 | |
1248 | // Request missing workers. |
1249 | @@ -1020,6 +1019,30 @@ |
1250 | set_production_result(""); |
1251 | } |
1252 | |
1253 | +const BuildingSettings* ProductionSite::create_building_settings() const { |
1254 | + ProductionsiteSettings* settings = new ProductionsiteSettings(descr()); |
1255 | + settings->stopped = is_stopped_; |
1256 | + for (auto& pair : settings->ware_queues) { |
1257 | + pair.second.priority = get_priority(wwWARE, pair.first, false); |
1258 | + for (const auto& queue : input_queues_) { |
1259 | + if (queue->get_type() == wwWARE && queue->get_index() == pair.first) { |
1260 | + pair.second.desired_fill = std::min(pair.second.max_fill, queue->get_max_fill()); |
1261 | + break; |
1262 | + } |
1263 | + } |
1264 | + } |
1265 | + for (auto& pair : settings->worker_queues) { |
1266 | + pair.second.priority = get_priority(wwWORKER, pair.first, false); |
1267 | + for (const auto& queue : input_queues_) { |
1268 | + if (queue->get_type() == wwWORKER && queue->get_index() == pair.first) { |
1269 | + pair.second.desired_fill = std::min(pair.second.max_fill, queue->get_max_fill()); |
1270 | + break; |
1271 | + } |
1272 | + } |
1273 | + } |
1274 | + return settings; |
1275 | +} |
1276 | + |
1277 | /// Changes the default anim string to \li anim |
1278 | void ProductionSite::set_default_anim(std::string anim) { |
1279 | if (default_anim_ == anim) |
1280 | |
1281 | === modified file 'src/logic/map_objects/tribes/productionsite.h' |
1282 | --- src/logic/map_objects/tribes/productionsite.h 2019-05-28 21:04:36 +0000 |
1283 | +++ src/logic/map_objects/tribes/productionsite.h 2019-06-19 09:23:26 +0000 |
1284 | @@ -241,6 +241,8 @@ |
1285 | |
1286 | void set_default_anim(std::string); |
1287 | |
1288 | + const BuildingSettings* create_building_settings() const override; |
1289 | + |
1290 | protected: |
1291 | void update_statistics_string(std::string* statistics) override; |
1292 | |
1293 | |
1294 | === modified file 'src/logic/map_objects/tribes/trainingsite.cc' |
1295 | --- src/logic/map_objects/tribes/trainingsite.cc 2019-05-05 14:05:07 +0000 |
1296 | +++ src/logic/map_objects/tribes/trainingsite.cc 2019-06-19 09:23:26 +0000 |
1297 | @@ -525,6 +525,13 @@ |
1298 | } |
1299 | } |
1300 | |
1301 | +const BuildingSettings* TrainingSite::create_building_settings() const { |
1302 | + TrainingsiteSettings* settings = new TrainingsiteSettings(descr()); |
1303 | + settings->apply(*ProductionSite::create_building_settings()); |
1304 | + settings->desired_capacity = std::min(settings->max_capacity, soldier_control_.soldier_capacity()); |
1305 | + return settings; |
1306 | +} |
1307 | + |
1308 | /** |
1309 | * In addition to advancing the program, update soldier status. |
1310 | */ |
1311 | |
1312 | === modified file 'src/logic/map_objects/tribes/trainingsite.h' |
1313 | --- src/logic/map_objects/tribes/trainingsite.h 2019-05-05 14:05:07 +0000 |
1314 | +++ src/logic/map_objects/tribes/trainingsite.h 2019-06-19 09:23:26 +0000 |
1315 | @@ -199,6 +199,8 @@ |
1316 | void training_successful(TrainingAttribute type, uint32_t level); |
1317 | void training_done(); |
1318 | |
1319 | + const BuildingSettings* create_building_settings() const override; |
1320 | + |
1321 | protected: |
1322 | void program_end(Game&, ProgramResult) override; |
1323 | |
1324 | |
1325 | === modified file 'src/logic/map_objects/tribes/warehouse.cc' |
1326 | --- src/logic/map_objects/tribes/warehouse.cc 2019-03-01 04:19:53 +0000 |
1327 | +++ src/logic/map_objects/tribes/warehouse.cc 2019-06-19 09:23:26 +0000 |
1328 | @@ -1275,17 +1275,17 @@ |
1329 | } |
1330 | } |
1331 | |
1332 | -Warehouse::StockPolicy Warehouse::get_ware_policy(DescriptionIndex ware) const { |
1333 | +StockPolicy Warehouse::get_ware_policy(DescriptionIndex ware) const { |
1334 | assert(ware < static_cast<DescriptionIndex>(ware_policy_.size())); |
1335 | return ware_policy_[ware]; |
1336 | } |
1337 | |
1338 | -Warehouse::StockPolicy Warehouse::get_worker_policy(DescriptionIndex ware) const { |
1339 | +StockPolicy Warehouse::get_worker_policy(DescriptionIndex ware) const { |
1340 | assert(ware < static_cast<DescriptionIndex>(worker_policy_.size())); |
1341 | return worker_policy_[ware]; |
1342 | } |
1343 | |
1344 | -Warehouse::StockPolicy Warehouse::get_stock_policy(WareWorker waretype, |
1345 | +StockPolicy Warehouse::get_stock_policy(WareWorker waretype, |
1346 | DescriptionIndex wareindex) const { |
1347 | if (waretype == wwWORKER) |
1348 | return get_worker_policy(wareindex); |
1349 | @@ -1293,25 +1293,25 @@ |
1350 | return get_ware_policy(wareindex); |
1351 | } |
1352 | |
1353 | -void Warehouse::set_ware_policy(DescriptionIndex ware, Warehouse::StockPolicy policy) { |
1354 | +void Warehouse::set_ware_policy(DescriptionIndex ware, StockPolicy policy) { |
1355 | assert(ware < static_cast<DescriptionIndex>(ware_policy_.size())); |
1356 | ware_policy_[ware] = policy; |
1357 | } |
1358 | |
1359 | -void Warehouse::set_worker_policy(DescriptionIndex ware, Warehouse::StockPolicy policy) { |
1360 | +void Warehouse::set_worker_policy(DescriptionIndex ware, StockPolicy policy) { |
1361 | assert(ware < static_cast<DescriptionIndex>(worker_policy_.size())); |
1362 | worker_policy_[ware] = policy; |
1363 | } |
1364 | |
1365 | /** |
1366 | - * Check if there are remaining wares with \ref Warehouse::StockPolicy::kRemove, |
1367 | + * Check if there are remaining wares with \ref StockPolicy::kRemove, |
1368 | * and remove one of them if appropriate. |
1369 | */ |
1370 | void Warehouse::check_remove_stock(Game& game) { |
1371 | if (base_flag().current_wares() < base_flag().total_capacity() / 2) { |
1372 | for (DescriptionIndex ware = 0; ware < static_cast<DescriptionIndex>(ware_policy_.size()); |
1373 | ++ware) { |
1374 | - if (get_ware_policy(ware) != Warehouse::StockPolicy::kRemove || !get_wares().stock(ware)) |
1375 | + if (get_ware_policy(ware) != StockPolicy::kRemove || !get_wares().stock(ware)) |
1376 | continue; |
1377 | |
1378 | launch_ware(game, ware); |
1379 | @@ -1321,7 +1321,7 @@ |
1380 | |
1381 | for (DescriptionIndex widx = 0; widx < static_cast<DescriptionIndex>(worker_policy_.size()); |
1382 | ++widx) { |
1383 | - if (get_worker_policy(widx) != Warehouse::StockPolicy::kRemove || !get_workers().stock(widx)) |
1384 | + if (get_worker_policy(widx) != StockPolicy::kRemove || !get_workers().stock(widx)) |
1385 | continue; |
1386 | |
1387 | Worker& worker = launch_worker(game, widx, Requirements()); |
1388 | @@ -1337,6 +1337,18 @@ |
1389 | return portdock_->expedition_bootstrap()->inputqueue(index, type); |
1390 | } |
1391 | |
1392 | +const BuildingSettings* Warehouse::create_building_settings() const { |
1393 | + WarehouseSettings* settings = new WarehouseSettings(descr(), owner().tribe()); |
1394 | + for (auto& pair : settings->ware_preferences) { |
1395 | + pair.second = get_ware_policy(pair.first); |
1396 | + } |
1397 | + for (auto& pair : settings->worker_preferences) { |
1398 | + pair.second = get_worker_policy(pair.first); |
1399 | + } |
1400 | + settings->launch_expedition = portdock_ && portdock_->expedition_started(); |
1401 | + return settings; |
1402 | +} |
1403 | + |
1404 | void Warehouse::log_general_info(const EditorGameBase& egbase) const { |
1405 | Building::log_general_info(egbase); |
1406 | |
1407 | |
1408 | === modified file 'src/logic/map_objects/tribes/warehouse.h' |
1409 | --- src/logic/map_objects/tribes/warehouse.h 2019-05-05 14:05:07 +0000 |
1410 | +++ src/logic/map_objects/tribes/warehouse.h 2019-06-19 09:23:26 +0000 |
1411 | @@ -68,6 +68,40 @@ |
1412 | DISALLOW_COPY_AND_ASSIGN(WarehouseDescr); |
1413 | }; |
1414 | |
1415 | +/** |
1416 | + * Each ware and worker type has an associated per-warehouse |
1417 | + * stock policy that defines whether it will be stocked by this |
1418 | + * warehouse. |
1419 | + * |
1420 | + * \note The values of this enum are written directly into savegames, |
1421 | + * so be careful when changing them. |
1422 | + */ |
1423 | +enum class StockPolicy { |
1424 | + /** |
1425 | + * The default policy allows stocking wares without any special priority. |
1426 | + */ |
1427 | + kNormal = 0, |
1428 | + |
1429 | + /** |
1430 | + * As long as there are warehouses with this policy for a ware, all |
1431 | + * available unstocked supplies will be transferred to warehouses |
1432 | + * with this policy. |
1433 | + */ |
1434 | + kPrefer = 1, |
1435 | + |
1436 | + /** |
1437 | + * If a ware has this stock policy, no more of this ware will enter |
1438 | + * the warehouse. |
1439 | + */ |
1440 | + kDontStock = 2, |
1441 | + |
1442 | + /** |
1443 | + * Like \ref kDontStock, but in addition, existing stock of this ware |
1444 | + * will be transported out of the warehouse over time. |
1445 | + */ |
1446 | + kRemove = 3, |
1447 | +}; |
1448 | + |
1449 | class Warehouse : public Building { |
1450 | friend class PortDock; |
1451 | friend class MapBuildingdataPacket; |
1452 | @@ -75,39 +109,6 @@ |
1453 | MO_DESCR(WarehouseDescr) |
1454 | |
1455 | public: |
1456 | - /** |
1457 | - * Each ware and worker type has an associated per-warehouse |
1458 | - * stock policy that defines whether it will be stocked by this |
1459 | - * warehouse. |
1460 | - * |
1461 | - * \note The values of this enum are written directly into savegames, |
1462 | - * so be careful when changing them. |
1463 | - */ |
1464 | - enum class StockPolicy { |
1465 | - /** |
1466 | - * The default policy allows stocking wares without any special priority. |
1467 | - */ |
1468 | - kNormal = 0, |
1469 | - |
1470 | - /** |
1471 | - * As long as there are warehouses with this policy for a ware, all |
1472 | - * available unstocked supplies will be transferred to warehouses |
1473 | - * with this policy. |
1474 | - */ |
1475 | - kPrefer = 1, |
1476 | - |
1477 | - /** |
1478 | - * If a ware has this stock policy, no more of this ware will enter |
1479 | - * the warehouse. |
1480 | - */ |
1481 | - kDontStock = 2, |
1482 | - |
1483 | - /** |
1484 | - * Like \ref kDontStock, but in addition, existing stock of this ware |
1485 | - * will be transported out of the warehouse over time. |
1486 | - */ |
1487 | - kRemove = 3, |
1488 | - }; |
1489 | |
1490 | /** |
1491 | * Whether worker indices in count_workers() have to match exactly. |
1492 | @@ -208,6 +209,8 @@ |
1493 | return portdock_; |
1494 | } |
1495 | |
1496 | + const BuildingSettings* create_building_settings() const override; |
1497 | + |
1498 | // Returns the waresqueue of the expedition if this is a port. |
1499 | // Will throw an exception otherwise. |
1500 | InputQueue& inputqueue(DescriptionIndex, WareWorker) override; |
1501 | |
1502 | === modified file 'src/logic/player.cc' |
1503 | --- src/logic/player.cc 2019-05-26 05:58:14 +0000 |
1504 | +++ src/logic/player.cc 2019-06-19 09:23:26 +0000 |
1505 | @@ -760,6 +760,7 @@ |
1506 | } else { |
1507 | workers = building->get_workers(); |
1508 | } |
1509 | + const BuildingSettings* settings = building->create_building_settings(); |
1510 | |
1511 | if (index_of_new_building != INVALID_INDEX) { |
1512 | // For enhancing, register whether the window was open |
1513 | @@ -770,7 +771,7 @@ |
1514 | // pointer. |
1515 | if (index_of_new_building != INVALID_INDEX) |
1516 | building = &egbase().warp_constructionsite( |
1517 | - position, player_number_, index_of_new_building, false, former_buildings); |
1518 | + position, player_number_, index_of_new_building, false, former_buildings, settings); |
1519 | else |
1520 | building = &egbase().warp_dismantlesite(position, player_number_, false, former_buildings); |
1521 | |
1522 | |
1523 | === modified file 'src/logic/playercommand.cc' |
1524 | --- src/logic/playercommand.cc 2019-05-25 10:54:30 +0000 |
1525 | +++ src/logic/playercommand.cc 2019-06-19 09:23:26 +0000 |
1526 | @@ -486,8 +486,14 @@ |
1527 | } |
1528 | |
1529 | void CmdStartStopBuilding::execute(Game& game) { |
1530 | - if (upcast(Building, building, game.objects().get_object(serial))) |
1531 | + MapObject* mo = game.objects().get_object(serial); |
1532 | + if (upcast(ConstructionSite, cs, mo)) { |
1533 | + if (upcast(ProductionsiteSettings, s, cs->get_settings())) { |
1534 | + s->stopped = !s->stopped; |
1535 | + } |
1536 | + } else if (upcast(Building, building, mo)) { |
1537 | game.get_player(sender())->start_stop_building(*building); |
1538 | + } |
1539 | } |
1540 | |
1541 | void CmdStartStopBuilding::serialize(StreamWrite& ser) { |
1542 | @@ -536,8 +542,14 @@ |
1543 | } |
1544 | |
1545 | void CmdMilitarySiteSetSoldierPreference::execute(Game& game) { |
1546 | - if (upcast(MilitarySite, building, game.objects().get_object(serial))) |
1547 | + MapObject* mo = game.objects().get_object(serial); |
1548 | + if (upcast(ConstructionSite, cs, mo)) { |
1549 | + if (upcast(MilitarysiteSettings, s, cs->get_settings())) { |
1550 | + s->prefer_heroes = preference == SoldierPreference::kHeroes; |
1551 | + } |
1552 | + } else if (upcast(MilitarySite, building, mo)) { |
1553 | game.get_player(sender())->military_site_set_soldier_preference(*building, preference); |
1554 | + } |
1555 | } |
1556 | |
1557 | constexpr uint16_t kCurrentPacketVersionSoldierPreference = 1; |
1558 | @@ -582,8 +594,14 @@ |
1559 | } |
1560 | |
1561 | void CmdStartOrCancelExpedition::execute(Game& game) { |
1562 | - if (upcast(Warehouse, warehouse, game.objects().get_object(serial))) |
1563 | + MapObject* mo = game.objects().get_object(serial); |
1564 | + if (upcast(ConstructionSite, cs, mo)) { |
1565 | + if (upcast(WarehouseSettings, s, cs->get_settings())) { |
1566 | + s->launch_expedition = !s->launch_expedition; |
1567 | + } |
1568 | + } else if (upcast(Warehouse, warehouse, game.objects().get_object(serial))) { |
1569 | game.get_player(sender())->start_or_cancel_expedition(*warehouse); |
1570 | + } |
1571 | } |
1572 | |
1573 | void CmdStartOrCancelExpedition::serialize(StreamWrite& ser) { |
1574 | @@ -626,8 +644,12 @@ |
1575 | } |
1576 | |
1577 | void CmdEnhanceBuilding::execute(Game& game) { |
1578 | - if (upcast(Building, building, game.objects().get_object(serial))) |
1579 | + MapObject* mo = game.objects().get_object(serial); |
1580 | + if (upcast(ConstructionSite, cs, mo)) { |
1581 | + cs->enhance(game); |
1582 | + } else if (upcast(Building, building, mo)) { |
1583 | game.get_player(sender())->enhance_building(building, bi); |
1584 | + } |
1585 | } |
1586 | |
1587 | void CmdEnhanceBuilding::serialize(StreamWrite& ser) { |
1588 | @@ -1036,14 +1058,22 @@ |
1589 | } |
1590 | |
1591 | void CmdSetWarePriority::execute(Game& game) { |
1592 | - upcast(Building, psite, game.objects().get_object(serial_)); |
1593 | - |
1594 | - if (!psite) |
1595 | - return; |
1596 | - if (psite->owner().player_number() != sender()) |
1597 | - return; |
1598 | - |
1599 | - psite->set_priority(type_, index_, priority_); |
1600 | + MapObject* mo = game.objects().get_object(serial_); |
1601 | + if (upcast(ConstructionSite, cs, mo)) { |
1602 | + if (upcast(ProductionsiteSettings, s, cs->get_settings())) { |
1603 | + for (auto& pair : s->ware_queues) { |
1604 | + if (pair.first == index_) { |
1605 | + pair.second.priority = priority_; |
1606 | + return; |
1607 | + } |
1608 | + } |
1609 | + NEVER_HERE(); |
1610 | + } |
1611 | + } else if (upcast(Building, psite, mo)) { |
1612 | + if (psite->owner().player_number() == sender()) { |
1613 | + psite->set_priority(type_, index_, priority_); |
1614 | + } |
1615 | + } |
1616 | } |
1617 | |
1618 | constexpr uint16_t kCurrentPacketVersionCmdSetWarePriority = 1; |
1619 | @@ -1110,14 +1140,36 @@ |
1620 | } |
1621 | |
1622 | void CmdSetInputMaxFill::execute(Game& game) { |
1623 | - upcast(Building, b, game.objects().get_object(serial_)); |
1624 | - |
1625 | - if (!b) |
1626 | - return; |
1627 | - if (b->owner().player_number() != sender()) |
1628 | - return; |
1629 | - |
1630 | - b->inputqueue(index_, type_).set_max_fill(max_fill_); |
1631 | + MapObject* mo = game.objects().get_object(serial_); |
1632 | + if (upcast(ConstructionSite, cs, mo)) { |
1633 | + if (upcast(ProductionsiteSettings, s, cs->get_settings())) { |
1634 | + switch (type_) { |
1635 | + case wwWARE: |
1636 | + for (auto& pair : s->ware_queues) { |
1637 | + if (pair.first == index_) { |
1638 | + assert(pair.second.max_fill >= max_fill_); |
1639 | + pair.second.desired_fill = max_fill_; |
1640 | + return; |
1641 | + } |
1642 | + } |
1643 | + NEVER_HERE(); |
1644 | + case wwWORKER: |
1645 | + for (auto& pair : s->worker_queues) { |
1646 | + if (pair.first == index_) { |
1647 | + assert(pair.second.max_fill >= max_fill_); |
1648 | + pair.second.desired_fill = max_fill_; |
1649 | + return; |
1650 | + } |
1651 | + } |
1652 | + NEVER_HERE(); |
1653 | + } |
1654 | + NEVER_HERE(); |
1655 | + } |
1656 | + } else if (upcast(Building, b, mo)) { |
1657 | + if (b->owner().player_number() == sender()) { |
1658 | + b->inputqueue(index_, type_).set_max_fill(max_fill_); |
1659 | + } |
1660 | + } |
1661 | } |
1662 | |
1663 | constexpr uint16_t kCurrentPacketVersionCmdSetInputMaxFill = 2; |
1664 | @@ -1528,7 +1580,18 @@ |
1665 | } |
1666 | |
1667 | void CmdChangeSoldierCapacity::execute(Game& game) { |
1668 | - if (upcast(Building, building, game.objects().get_object(serial))) { |
1669 | + MapObject* mo = game.objects().get_object(serial); |
1670 | + if (upcast(ConstructionSite, cs, mo)) { |
1671 | + assert(val >= 0); |
1672 | + uint32_t capacity = static_cast<uint32_t>(val); |
1673 | + if (upcast(MilitarysiteSettings, ms, cs->get_settings())) { |
1674 | + assert(ms->max_capacity >= capacity); |
1675 | + ms->desired_capacity = capacity; |
1676 | + } else if (upcast(TrainingsiteSettings, ts, cs->get_settings())) { |
1677 | + assert(ts->max_capacity >= capacity); |
1678 | + ts->desired_capacity = capacity; |
1679 | + } |
1680 | + } else if (upcast(Building, building, mo)) { |
1681 | if (building->get_owner() == game.get_player(sender()) && |
1682 | building->soldier_control() != nullptr) { |
1683 | SoldierControl* soldier_control = building->mutable_soldier_control(); |
1684 | @@ -1750,10 +1813,10 @@ |
1685 | /*** struct Cmd_SetStockPolicy ***/ |
1686 | CmdSetStockPolicy::CmdSetStockPolicy(uint32_t time, |
1687 | PlayerNumber p, |
1688 | - Warehouse& wh, |
1689 | + Building& wh, |
1690 | bool isworker, |
1691 | DescriptionIndex ware, |
1692 | - Warehouse::StockPolicy policy) |
1693 | + StockPolicy policy) |
1694 | : PlayerCommand(time, p) { |
1695 | warehouse_ = wh.serial(); |
1696 | isworker_ = isworker; |
1697 | @@ -1768,7 +1831,16 @@ |
1698 | void CmdSetStockPolicy::execute(Game& game) { |
1699 | // Sanitize data that could have come from the network |
1700 | if (Player* plr = game.get_player(sender())) { |
1701 | - if (upcast(Warehouse, warehouse, game.objects().get_object(warehouse_))) { |
1702 | + MapObject* mo = game.objects().get_object(warehouse_); |
1703 | + if (upcast(ConstructionSite, cs, mo)) { |
1704 | + if (upcast(WarehouseSettings, s, cs->get_settings())) { |
1705 | + if (isworker_) { |
1706 | + s->worker_preferences[ware_] = policy_; |
1707 | + } else { |
1708 | + s->ware_preferences[ware_] = policy_; |
1709 | + } |
1710 | + } |
1711 | + } else if (upcast(Warehouse, warehouse, mo)) { |
1712 | if (warehouse->get_owner() != plr) { |
1713 | log("Cmd_SetStockPolicy: sender %u, but warehouse owner %u\n", sender(), |
1714 | warehouse->owner().player_number()); |
1715 | @@ -1796,7 +1868,7 @@ |
1716 | warehouse_ = des.unsigned_32(); |
1717 | isworker_ = des.unsigned_8(); |
1718 | ware_ = DescriptionIndex(des.unsigned_8()); |
1719 | - policy_ = static_cast<Warehouse::StockPolicy>(des.unsigned_8()); |
1720 | + policy_ = static_cast<StockPolicy>(des.unsigned_8()); |
1721 | } |
1722 | |
1723 | void CmdSetStockPolicy::serialize(StreamWrite& ser) { |
1724 | @@ -1818,7 +1890,7 @@ |
1725 | warehouse_ = fr.unsigned_32(); |
1726 | isworker_ = fr.unsigned_8(); |
1727 | ware_ = DescriptionIndex(fr.unsigned_8()); |
1728 | - policy_ = static_cast<Warehouse::StockPolicy>(fr.unsigned_8()); |
1729 | + policy_ = static_cast<StockPolicy>(fr.unsigned_8()); |
1730 | } else { |
1731 | throw UnhandledVersionError( |
1732 | "CmdSetStockPolicy", packet_version, kCurrentPacketVersionCmdSetStockPolicy); |
1733 | @@ -1906,4 +1978,5 @@ |
1734 | // TODO(sirver,trading): Implement this. |
1735 | NEVER_HERE(); |
1736 | } |
1737 | + |
1738 | } // namespace Widelands |
1739 | |
1740 | === modified file 'src/logic/playercommand.h' |
1741 | --- src/logic/playercommand.h 2019-05-29 16:59:16 +0000 |
1742 | +++ src/logic/playercommand.h 2019-06-19 09:23:26 +0000 |
1743 | @@ -24,6 +24,7 @@ |
1744 | |
1745 | #include "economy/flag.h" |
1746 | #include "logic/cmd_queue.h" |
1747 | +#include "logic/map_objects/tribes/constructionsite.h" |
1748 | #include "logic/map_objects/tribes/militarysite.h" |
1749 | #include "logic/map_objects/tribes/ship.h" |
1750 | #include "logic/map_objects/tribes/trainingsite.h" |
1751 | @@ -824,10 +825,10 @@ |
1752 | struct CmdSetStockPolicy : PlayerCommand { |
1753 | CmdSetStockPolicy(uint32_t time, |
1754 | PlayerNumber p, |
1755 | - Warehouse& wh, |
1756 | + Building& wh, |
1757 | bool isworker, |
1758 | DescriptionIndex ware, |
1759 | - Warehouse::StockPolicy policy); |
1760 | + StockPolicy policy); |
1761 | |
1762 | QueueCommandTypes id() const override { |
1763 | return QueueCommandTypes::kSetStockPolicy; |
1764 | @@ -848,7 +849,7 @@ |
1765 | Serial warehouse_; |
1766 | bool isworker_; |
1767 | DescriptionIndex ware_; |
1768 | - Warehouse::StockPolicy policy_; |
1769 | + StockPolicy policy_; |
1770 | }; |
1771 | |
1772 | struct CmdProposeTrade : PlayerCommand { |
1773 | @@ -872,6 +873,7 @@ |
1774 | private: |
1775 | Trade trade_; |
1776 | }; |
1777 | + |
1778 | } // namespace Widelands |
1779 | |
1780 | #endif // end of include guard: WL_LOGIC_PLAYERCOMMAND_H |
1781 | |
1782 | === modified file 'src/map_io/map_buildingdata_packet.cc' |
1783 | --- src/map_io/map_buildingdata_packet.cc 2019-06-13 17:32:28 +0000 |
1784 | +++ src/map_io/map_buildingdata_packet.cc 2019-06-19 09:23:26 +0000 |
1785 | @@ -60,7 +60,7 @@ |
1786 | |
1787 | // Building type package versions |
1788 | constexpr uint16_t kCurrentPacketVersionDismantlesite = 1; |
1789 | -constexpr uint16_t kCurrentPacketVersionConstructionsite = 3; |
1790 | +constexpr uint16_t kCurrentPacketVersionConstructionsite = 4; |
1791 | constexpr uint16_t kCurrentPacketPFBuilding = 1; |
1792 | // Responsible for warehouses and expedition bootstraps |
1793 | constexpr uint16_t kCurrentPacketVersionWarehouse = 7; |
1794 | @@ -274,7 +274,7 @@ |
1795 | const TribesLegacyLookupTable& tribes_lookup_table) { |
1796 | try { |
1797 | uint16_t const packet_version = fr.unsigned_16(); |
1798 | - if (packet_version >= kCurrentPacketVersionConstructionsite) { |
1799 | + if (packet_version >= 3) { |
1800 | read_partially_finished_building(constructionsite, fr, game, mol, tribes_lookup_table); |
1801 | |
1802 | for (ConstructionSite::Wares::iterator wares_iter = constructionsite.wares_.begin(); |
1803 | @@ -284,6 +284,18 @@ |
1804 | } |
1805 | |
1806 | constructionsite.fetchfromflag_ = fr.signed_32(); |
1807 | + |
1808 | + if (packet_version >= 4) { |
1809 | + const uint32_t intermediates = fr.unsigned_32(); |
1810 | + for (uint32_t i = 0; i < intermediates; ++i) { |
1811 | + constructionsite.info_.intermediates.push_back(game.tribes().get_building_descr( |
1812 | + game.tribes().building_index(fr.c_string()))); |
1813 | + } |
1814 | + constructionsite.settings_.reset(BuildingSettings::load(game, |
1815 | + constructionsite.owner().tribe(), fr)); |
1816 | + } else { |
1817 | + constructionsite.init_settings(); |
1818 | + } |
1819 | } else { |
1820 | throw UnhandledVersionError("MapBuildingdataPacket - Constructionsite", packet_version, |
1821 | kCurrentPacketVersionConstructionsite); |
1822 | @@ -329,7 +341,7 @@ |
1823 | const DescriptionIndex& id = |
1824 | tribe.ware_index(tribes_lookup_table.lookup_ware(fr.c_string())); |
1825 | Quantity amount = fr.unsigned_32(); |
1826 | - Warehouse::StockPolicy policy = static_cast<Warehouse::StockPolicy>(fr.unsigned_8()); |
1827 | + StockPolicy policy = static_cast<StockPolicy>(fr.unsigned_8()); |
1828 | |
1829 | if (game.tribes().ware_exists(id)) { |
1830 | warehouse.insert_wares(id, amount); |
1831 | @@ -340,7 +352,7 @@ |
1832 | const DescriptionIndex& id = |
1833 | tribe.worker_index(tribes_lookup_table.lookup_worker(fr.c_string())); |
1834 | uint32_t amount = fr.unsigned_32(); |
1835 | - Warehouse::StockPolicy policy = static_cast<Warehouse::StockPolicy>(fr.unsigned_8()); |
1836 | + StockPolicy policy = static_cast<StockPolicy>(fr.unsigned_8()); |
1837 | |
1838 | if (game.tribes().worker_exists(id)) { |
1839 | warehouse.insert_workers(id, amount); |
1840 | @@ -978,6 +990,14 @@ |
1841 | write_partially_finished_building(constructionsite, fw, game, mos); |
1842 | |
1843 | fw.signed_32(constructionsite.fetchfromflag_); |
1844 | + |
1845 | + fw.unsigned_32(constructionsite.info_.intermediates.size()); |
1846 | + for (const BuildingDescr* d : constructionsite.info_.intermediates) { |
1847 | + fw.c_string(d->name().c_str()); |
1848 | + } |
1849 | + |
1850 | + assert(constructionsite.settings_); |
1851 | + constructionsite.settings_->save(game, fw); |
1852 | } |
1853 | |
1854 | void MapBuildingdataPacket::write_dismantlesite(const DismantleSite& dms, |
1855 | |
1856 | === modified file 'src/notifications/note_ids.h' |
1857 | --- src/notifications/note_ids.h 2019-05-10 17:43:19 +0000 |
1858 | +++ src/notifications/note_ids.h 2019-06-19 09:23:26 +0000 |
1859 | @@ -29,6 +29,7 @@ |
1860 | ChatMessage, |
1861 | LogMessage, |
1862 | Immovable, |
1863 | + ConstructionsiteEnhanced, |
1864 | FieldPossession, |
1865 | FieldTerrainChanged, |
1866 | ProductionSiteOutOfResources, |
1867 | |
1868 | === modified file 'src/scripting/lua_map.cc' |
1869 | --- src/scripting/lua_map.cc 2019-05-04 10:47:44 +0000 |
1870 | +++ src/scripting/lua_map.cc 2019-06-19 09:23:26 +0000 |
1871 | @@ -4871,39 +4871,39 @@ |
1872 | } |
1873 | |
1874 | // Transforms the given warehouse policy to a string which is used by the lua code |
1875 | -inline void wh_policy_to_string(lua_State* L, Warehouse::StockPolicy p) { |
1876 | +inline void wh_policy_to_string(lua_State* L, StockPolicy p) { |
1877 | switch (p) { |
1878 | - case Warehouse::StockPolicy::kNormal: |
1879 | + case StockPolicy::kNormal: |
1880 | lua_pushstring(L, "normal"); |
1881 | break; |
1882 | - case Warehouse::StockPolicy::kPrefer: |
1883 | + case StockPolicy::kPrefer: |
1884 | lua_pushstring(L, "prefer"); |
1885 | break; |
1886 | - case Warehouse::StockPolicy::kDontStock: |
1887 | + case StockPolicy::kDontStock: |
1888 | lua_pushstring(L, "dontstock"); |
1889 | break; |
1890 | - case Warehouse::StockPolicy::kRemove: |
1891 | + case StockPolicy::kRemove: |
1892 | lua_pushstring(L, "remove"); |
1893 | break; |
1894 | } |
1895 | } |
1896 | // Transforms the given string from the lua code to a warehouse policy |
1897 | -inline Warehouse::StockPolicy string_to_wh_policy(lua_State* L, uint32_t index) { |
1898 | +inline StockPolicy string_to_wh_policy(lua_State* L, uint32_t index) { |
1899 | std::string str = luaL_checkstring(L, index); |
1900 | if (str == "normal") |
1901 | - return Warehouse::StockPolicy::kNormal; |
1902 | + return StockPolicy::kNormal; |
1903 | else if (str == "prefer") |
1904 | - return Warehouse::StockPolicy::kPrefer; |
1905 | + return StockPolicy::kPrefer; |
1906 | else if (str == "dontstock") |
1907 | - return Warehouse::StockPolicy::kDontStock; |
1908 | + return StockPolicy::kDontStock; |
1909 | else if (str == "remove") |
1910 | - return Warehouse::StockPolicy::kRemove; |
1911 | + return StockPolicy::kRemove; |
1912 | else |
1913 | report_error(L, "<%s> is no valid warehouse policy!", str.c_str()); |
1914 | } |
1915 | |
1916 | inline bool |
1917 | -do_set_ware_policy(Warehouse* wh, const DescriptionIndex idx, const Warehouse::StockPolicy p) { |
1918 | +do_set_ware_policy(Warehouse* wh, const DescriptionIndex idx, const StockPolicy p) { |
1919 | wh->set_ware_policy(idx, p); |
1920 | return true; |
1921 | } |
1922 | @@ -4913,7 +4913,7 @@ |
1923 | * If the no ware with the given name exists for the tribe of the warehouse, return false. |
1924 | */ |
1925 | inline bool |
1926 | -do_set_ware_policy(Warehouse* wh, const std::string& name, const Warehouse::StockPolicy p) { |
1927 | +do_set_ware_policy(Warehouse* wh, const std::string& name, const StockPolicy p) { |
1928 | const TribeDescr& tribe = wh->owner().tribe(); |
1929 | DescriptionIndex idx = tribe.ware_index(name); |
1930 | if (!tribe.has_ware(idx)) { |
1931 | @@ -4923,7 +4923,7 @@ |
1932 | } |
1933 | |
1934 | inline bool |
1935 | -do_set_worker_policy(Warehouse* wh, const DescriptionIndex idx, const Warehouse::StockPolicy p) { |
1936 | +do_set_worker_policy(Warehouse* wh, const DescriptionIndex idx, const StockPolicy p) { |
1937 | const TribeDescr& tribe = wh->owner().tribe(); |
1938 | // If the worker does not cost anything, ignore it |
1939 | // Otherwise, an unlimited stream of carriers might leave the warehouse |
1940 | @@ -4942,7 +4942,7 @@ |
1941 | * If no worker with the given name exists for the tribe of the warehouse, return false. |
1942 | */ |
1943 | inline bool |
1944 | -do_set_worker_policy(Warehouse* wh, const std::string& name, const Warehouse::StockPolicy p) { |
1945 | +do_set_worker_policy(Warehouse* wh, const std::string& name, const StockPolicy p) { |
1946 | const TribeDescr& tribe = wh->owner().tribe(); |
1947 | DescriptionIndex idx = tribe.worker_index(name); |
1948 | if (!tribe.has_worker(idx)) { |
1949 | @@ -4972,7 +4972,7 @@ |
1950 | report_error(L, "Wrong number of arguments to set_warehouse_policies!"); |
1951 | |
1952 | Warehouse* wh = get(L, get_egbase(L)); |
1953 | - Warehouse::StockPolicy p = string_to_wh_policy(L, -1); |
1954 | + StockPolicy p = string_to_wh_policy(L, -1); |
1955 | lua_pop(L, 1); |
1956 | const TribeDescr& tribe = wh->owner().tribe(); |
1957 | |
1958 | |
1959 | === modified file 'src/wui/actionconfirm.cc' |
1960 | --- src/wui/actionconfirm.cc 2019-04-28 16:53:20 +0000 |
1961 | +++ src/wui/actionconfirm.cc 2019-06-19 09:23:26 +0000 |
1962 | @@ -92,7 +92,8 @@ |
1963 | struct EnhanceConfirm : public ActionConfirm { |
1964 | EnhanceConfirm(InteractivePlayer& parent, |
1965 | Widelands::Building& building, |
1966 | - const Widelands::DescriptionIndex& id); |
1967 | + const Widelands::DescriptionIndex& id, |
1968 | + bool still_under_construction); |
1969 | |
1970 | void think() override; |
1971 | void ok() override; |
1972 | @@ -100,6 +101,7 @@ |
1973 | private: |
1974 | // Do not make this a reference - it is a stack variable in the caller |
1975 | const Widelands::DescriptionIndex id_; |
1976 | + bool still_under_construction_; |
1977 | }; |
1978 | |
1979 | /** |
1980 | @@ -259,7 +261,8 @@ |
1981 | */ |
1982 | EnhanceConfirm::EnhanceConfirm(InteractivePlayer& parent, |
1983 | Widelands::Building& building, |
1984 | - const Widelands::DescriptionIndex& id) |
1985 | + const Widelands::DescriptionIndex& id, |
1986 | + bool still_under_construction) |
1987 | : ActionConfirm( |
1988 | parent, |
1989 | _("Enhance building?"), |
1990 | @@ -270,7 +273,8 @@ |
1991 | .str() : |
1992 | _("Do you really want to enhance this building?"), |
1993 | building), |
1994 | - id_(id) { |
1995 | + id_(id), |
1996 | + still_under_construction_(still_under_construction) { |
1997 | // Nothing special to do |
1998 | } |
1999 | |
2000 | @@ -284,7 +288,7 @@ |
2001 | upcast(Widelands::Building, building, object_.get(egbase)); |
2002 | |
2003 | if (!building || !iaplayer().can_act(building->owner().player_number()) || |
2004 | - !(building->get_playercaps() & Widelands::Building::PCap_Enhancable)) |
2005 | + !(still_under_construction_ || (building->get_playercaps() & Widelands::Building::PCap_Enhancable))) |
2006 | die(); |
2007 | } |
2008 | |
2009 | @@ -293,11 +297,18 @@ |
2010 | */ |
2011 | void EnhanceConfirm::ok() { |
2012 | Widelands::Game& game = iaplayer().game(); |
2013 | - upcast(Widelands::Building, building, object_.get(game)); |
2014 | |
2015 | - if (building && iaplayer().can_act(building->owner().player_number()) && |
2016 | - (building->get_playercaps() & Widelands::Building::PCap_Enhancable)) { |
2017 | - game.send_player_enhance_building(*building, id_); |
2018 | + if (still_under_construction_) { |
2019 | + upcast(Widelands::ConstructionSite, cs, object_.get(game)); |
2020 | + if (cs && iaplayer().can_act(cs->owner().player_number())) { |
2021 | + game.send_player_enhance_building(*cs, Widelands::INVALID_INDEX); |
2022 | + } |
2023 | + } else { |
2024 | + upcast(Widelands::Building, building, object_.get(game)); |
2025 | + if (building && iaplayer().can_act(building->owner().player_number()) && |
2026 | + (building->get_playercaps() & Widelands::Building::PCap_Enhancable)) { |
2027 | + game.send_player_enhance_building(*building, id_); |
2028 | + } |
2029 | } |
2030 | |
2031 | die(); |
2032 | @@ -419,8 +430,9 @@ |
2033 | */ |
2034 | void show_enhance_confirm(InteractivePlayer& player, |
2035 | Widelands::Building& building, |
2036 | - const Widelands::DescriptionIndex& id) { |
2037 | - new EnhanceConfirm(player, building, id); |
2038 | + const Widelands::DescriptionIndex& id, |
2039 | + bool constructionsite) { |
2040 | + new EnhanceConfirm(player, building, id, constructionsite); |
2041 | } |
2042 | |
2043 | /** |
2044 | |
2045 | === modified file 'src/wui/actionconfirm.h' |
2046 | --- src/wui/actionconfirm.h 2019-02-23 11:00:49 +0000 |
2047 | +++ src/wui/actionconfirm.h 2019-06-19 09:23:26 +0000 |
2048 | @@ -39,7 +39,8 @@ |
2049 | |
2050 | void show_enhance_confirm(InteractivePlayer& player, |
2051 | Widelands::Building& building, |
2052 | - const Widelands::DescriptionIndex& id); |
2053 | + const Widelands::DescriptionIndex& id, |
2054 | + bool still_under_construction = false); |
2055 | |
2056 | // Ship confirm windows |
2057 | void show_ship_sink_confirm(InteractivePlayer& player, Widelands::Ship& ship); |
2058 | |
2059 | === modified file 'src/wui/buildingwindow.cc' |
2060 | --- src/wui/buildingwindow.cc 2019-05-26 17:21:15 +0000 |
2061 | +++ src/wui/buildingwindow.cc 2019-06-19 09:23:26 +0000 |
2062 | @@ -54,7 +54,7 @@ |
2063 | is_dying_(false), |
2064 | parent_(&parent), |
2065 | building_(&b), |
2066 | - building_descr_for_help_(descr), |
2067 | + building_descr_for_help_(&descr), |
2068 | building_position_(b.get_position()), |
2069 | showing_workarea_(false), |
2070 | avoid_fastclick_(avoid_fastclick), |
2071 | @@ -363,14 +363,14 @@ |
2072 | g_gr->images().get("images/ui_basic/menu_help.png"), _("Help")); |
2073 | |
2074 | UI::UniqueWindow::Registry& registry = |
2075 | - igbase()->unique_windows().get_registry(building_descr_for_help_.name() + "_help"); |
2076 | + igbase()->unique_windows().get_registry(building_descr_for_help_->name() + "_help"); |
2077 | registry.open_window = [this, ®istry] { |
2078 | if (parent_ != nullptr) { |
2079 | Widelands::Building* building_in_lambda = building_.get(parent_->egbase()); |
2080 | if (building_in_lambda == nullptr) { |
2081 | return; |
2082 | } |
2083 | - new UI::BuildingHelpWindow(igbase(), registry, building_descr_for_help_, |
2084 | + new UI::BuildingHelpWindow(igbase(), registry, *building_descr_for_help_, |
2085 | building_in_lambda->owner().tribe(), |
2086 | &parent_->egbase().lua()); |
2087 | } |
2088 | |
2089 | === modified file 'src/wui/buildingwindow.h' |
2090 | --- src/wui/buildingwindow.h 2019-02-23 11:00:49 +0000 |
2091 | +++ src/wui/buildingwindow.h 2019-06-19 09:23:26 +0000 |
2092 | @@ -95,6 +95,10 @@ |
2093 | |
2094 | bool is_dying_; |
2095 | |
2096 | + void set_building_descr_for_help(const Widelands::BuildingDescr* d) { |
2097 | + building_descr_for_help_ = d; |
2098 | + } |
2099 | + |
2100 | private: |
2101 | void create_capsbuttons(UI::Box* buttons, Widelands::Building* building); |
2102 | |
2103 | @@ -110,7 +114,7 @@ |
2104 | Widelands::OPtr<Widelands::Building> building_; |
2105 | |
2106 | // The building description that will be used for the help button |
2107 | - const Widelands::BuildingDescr& building_descr_for_help_; |
2108 | + const Widelands::BuildingDescr* building_descr_for_help_; |
2109 | |
2110 | // We require this to unregister overlays when we are closed. Since the |
2111 | // building might have been destroyed by then we have to keep a copy of its |
2112 | |
2113 | === modified file 'src/wui/constructionsitewindow.cc' |
2114 | --- src/wui/constructionsitewindow.cc 2019-02-23 11:00:49 +0000 |
2115 | +++ src/wui/constructionsitewindow.cc 2019-06-19 09:23:26 +0000 |
2116 | @@ -22,9 +22,67 @@ |
2117 | #include <boost/format.hpp> |
2118 | |
2119 | #include "graphic/graphic.h" |
2120 | +#include "wui/actionconfirm.h" |
2121 | #include "wui/inputqueuedisplay.h" |
2122 | +#include "wui/interactive_player.h" |
2123 | |
2124 | static const char pic_tab_wares[] = "images/wui/buildings/menu_tab_wares.png"; |
2125 | +static const char pic_tab_settings[] = "images/wui/menus/menu_stock.png"; |
2126 | +static const char pic_tab_settings_wares[] = "images/wui/stats/menu_tab_wares_warehouse.png"; |
2127 | +static const char pic_tab_settings_workers[] = "images/wui/stats/menu_tab_workers_warehouse.png"; |
2128 | +static const char pic_max_fill_indicator[] = "images/wui/buildings/max_fill_indicator.png"; |
2129 | +static const char pic_priority_low[] = "images/wui/buildings/low_priority_button.png"; |
2130 | +static const char pic_priority_normal[] = "images/wui/buildings/normal_priority_button.png"; |
2131 | +static const char pic_priority_high[] = "images/wui/buildings/high_priority_button.png"; |
2132 | +static const char pic_stock_policy_prefer[] = "images/wui/buildings/stock_policy_prefer.png"; |
2133 | +static const char pic_stock_policy_dontstock[] = "images/wui/buildings/stock_policy_dontstock.png"; |
2134 | +static const char pic_stock_policy_remove[] = "images/wui/buildings/stock_policy_remove.png"; |
2135 | +static const char pic_stock_policy_button_normal[] = "images/wui/buildings/stock_policy_button_normal.png"; |
2136 | +static const char pic_stock_policy_button_prefer[] = "images/wui/buildings/stock_policy_button_prefer.png"; |
2137 | +static const char pic_stock_policy_button_dontstock[] = "images/wui/buildings/stock_policy_button_dontstock.png"; |
2138 | +static const char pic_stock_policy_button_remove[] = "images/wui/buildings/stock_policy_button_remove.png"; |
2139 | +static const char pic_decrease_capacity[] = "images/wui/buildings/menu_down_train.png"; |
2140 | +static const char pic_increase_capacity[] = "images/wui/buildings/menu_up_train.png"; |
2141 | + |
2142 | +ConstructionSiteWindow::FakeWaresDisplay::FakeWaresDisplay(UI::Panel* parent, |
2143 | + bool can_act, |
2144 | + Widelands::ConstructionSite& cs, |
2145 | + Widelands::WareWorker type) |
2146 | + : WaresDisplay(parent, 0, 0, cs.owner().tribe(), type, can_act), |
2147 | + settings_(*dynamic_cast<Widelands::WarehouseSettings*>(cs.get_settings())), |
2148 | + tribe_(cs.owner().tribe()) { |
2149 | +} |
2150 | + |
2151 | +void ConstructionSiteWindow::FakeWaresDisplay::draw_ware(RenderTarget& dst, Widelands::DescriptionIndex ware) { |
2152 | + if (get_type() == Widelands::wwWORKER && std::find(tribe_.worker_types_without_cost().begin(), |
2153 | + tribe_.worker_types_without_cost().end(), ware) != tribe_.worker_types_without_cost().end()) { |
2154 | + return; |
2155 | + } |
2156 | + WaresDisplay::draw_ware(dst, ware); |
2157 | + |
2158 | + const auto& map = get_type() == Widelands::wwWARE ? settings_.ware_preferences : settings_.worker_preferences; |
2159 | + const auto it = map.find(ware); |
2160 | + if (it == map.end()) { |
2161 | + return; |
2162 | + } |
2163 | + const Image* pic = nullptr; |
2164 | + switch (it->second) { |
2165 | + case Widelands::StockPolicy::kPrefer: |
2166 | + pic = g_gr->images().get(pic_stock_policy_prefer); |
2167 | + break; |
2168 | + case Widelands::StockPolicy::kDontStock: |
2169 | + pic = g_gr->images().get(pic_stock_policy_dontstock); |
2170 | + break; |
2171 | + case Widelands::StockPolicy::kRemove: |
2172 | + pic = g_gr->images().get(pic_stock_policy_remove); |
2173 | + break; |
2174 | + case Widelands::StockPolicy::kNormal: |
2175 | + // No icon for the normal policy |
2176 | + return; |
2177 | + } |
2178 | + assert(pic); |
2179 | + dst.blit(ware_position(ware), pic); |
2180 | +} |
2181 | |
2182 | ConstructionSiteWindow::ConstructionSiteWindow(InteractiveGameBase& parent, |
2183 | UI::UniqueWindow::Registry& reg, |
2184 | @@ -33,13 +91,23 @@ |
2185 | bool workarea_preview_wanted) |
2186 | : BuildingWindow(parent, reg, cs, cs.building(), avoid_fastclick), |
2187 | construction_site_(&cs), |
2188 | - progress_(nullptr) { |
2189 | + progress_(nullptr), |
2190 | + cs_enhance_(nullptr), |
2191 | + cs_launch_expedition_(nullptr), |
2192 | + cs_prefer_heroes_rookies_(nullptr), |
2193 | + cs_soldier_capacity_decrease_(nullptr), |
2194 | + cs_soldier_capacity_increase_(nullptr), |
2195 | + cs_soldier_capacity_display_(nullptr), |
2196 | + cs_stopped_(nullptr), |
2197 | + cs_warehouse_wares_(nullptr), |
2198 | + cs_warehouse_workers_(nullptr) { |
2199 | init(avoid_fastclick, workarea_preview_wanted); |
2200 | } |
2201 | |
2202 | void ConstructionSiteWindow::init(bool avoid_fastclick, bool workarea_preview_wanted) { |
2203 | Widelands::ConstructionSite* construction_site = construction_site_.get(igbase()->egbase()); |
2204 | assert(construction_site != nullptr); |
2205 | + set_building_descr_for_help(&construction_site->building()); |
2206 | |
2207 | BuildingWindow::init(avoid_fastclick, workarea_preview_wanted); |
2208 | UI::Box& box = *new UI::Box(get_tabs(), 0, 0, UI::Box::Vertical); |
2209 | @@ -59,10 +127,245 @@ |
2210 | |
2211 | get_tabs()->add("wares", g_gr->images().get(pic_tab_wares), &box, _("Building materials")); |
2212 | |
2213 | + if (construction_site->get_settings()) { |
2214 | + const bool can_act = igbase()->can_act(construction_site->owner().player_number()); |
2215 | + // Create the settings. Since we don't access an actual building, we create |
2216 | + // a simplified faksimile of the later building window that contains only |
2217 | + // the relevant options. |
2218 | + bool nothing_added = false; |
2219 | + UI::Box& settings_box = *new UI::Box(get_tabs(), 0, 0, UI::Box::Vertical); |
2220 | + if (upcast(Widelands::ProductionsiteSettings, ps, construction_site->get_settings())) { |
2221 | + for (const auto& pair : ps->ware_queues) { |
2222 | + InputQueueDisplay* queue = new InputQueueDisplay(&settings_box, 0, 0, *igbase(), |
2223 | + *construction_site, Widelands::wwWARE, pair.first); |
2224 | + settings_box.add(queue); |
2225 | + settings_box.add_space(8); |
2226 | + cs_ware_queues_.push_back(queue); |
2227 | + } |
2228 | + for (const auto& pair : ps->worker_queues) { |
2229 | + InputQueueDisplay* queue = new InputQueueDisplay(&settings_box, 0, 0, *igbase(), |
2230 | + *construction_site, Widelands::wwWORKER, pair.first); |
2231 | + settings_box.add(queue); |
2232 | + settings_box.add_space(8); |
2233 | + cs_ware_queues_.push_back(queue); |
2234 | + } |
2235 | + if (upcast(Widelands::TrainingsiteSettings, ts, ps)) { |
2236 | + UI::Box& soldier_capacity_box = *new UI::Box(&settings_box, 0, 0, UI::Box::Horizontal); |
2237 | + settings_box.add(&soldier_capacity_box, UI::Box::Resizing::kAlign, UI::Align::kCenter); |
2238 | + cs_soldier_capacity_decrease_ = new UI::Button(&soldier_capacity_box, |
2239 | + "decrease", 0, 0, 32, 32, UI::ButtonStyle::kWuiMenu, |
2240 | + g_gr->images().get(pic_decrease_capacity), |
2241 | + _("Decrease capacity. Hold down Ctrl to set the capacity to the lowest value")); |
2242 | + cs_soldier_capacity_increase_ = new UI::Button(&soldier_capacity_box, |
2243 | + "increase", 0, 0, 32, 32, UI::ButtonStyle::kWuiMenu, |
2244 | + g_gr->images().get(pic_increase_capacity), |
2245 | + _("Increase capacity. Hold down Ctrl to set the capacity to the highest value")); |
2246 | + cs_soldier_capacity_display_ = new UI::Textarea(&soldier_capacity_box, |
2247 | + "", UI::Align::kCenter); |
2248 | + cs_soldier_capacity_decrease_->set_enabled(can_act); |
2249 | + cs_soldier_capacity_increase_->set_enabled(can_act); |
2250 | + cs_soldier_capacity_decrease_->sigclicked.connect([this, ts]() { |
2251 | + igbase()->game().send_player_change_soldier_capacity( |
2252 | + *construction_site_.get(igbase()->egbase()), |
2253 | + SDL_GetModState() & KMOD_CTRL ? 0 : ts->desired_capacity - 1); |
2254 | + }); |
2255 | + cs_soldier_capacity_increase_->sigclicked.connect([this, ts]() { |
2256 | + igbase()->game().send_player_change_soldier_capacity( |
2257 | + *construction_site_.get(igbase()->egbase()), |
2258 | + SDL_GetModState() & KMOD_CTRL ? ts->max_capacity : ts->desired_capacity + 1); |
2259 | + }); |
2260 | + soldier_capacity_box.add(cs_soldier_capacity_decrease_); |
2261 | + soldier_capacity_box.add_space(8); |
2262 | + soldier_capacity_box.add(cs_soldier_capacity_display_, UI::Box::Resizing::kAlign, UI::Align::kCenter); |
2263 | + soldier_capacity_box.add_space(8); |
2264 | + soldier_capacity_box.add(cs_soldier_capacity_increase_); |
2265 | + settings_box.add_space(8); |
2266 | + } |
2267 | + cs_stopped_ = new UI::Checkbox(&settings_box, Vector2i::zero(), |
2268 | + _("Stopped"), |
2269 | + _("Stop this building’s work after completion")); |
2270 | + cs_stopped_->clickedto.connect([this, ps](bool stop) { |
2271 | + if (stop != ps->stopped) { |
2272 | + igbase()->game().send_player_start_stop_building(*construction_site_.get(igbase()->egbase())); |
2273 | + } |
2274 | + }); |
2275 | + settings_box.add(cs_stopped_, UI::Box::Resizing::kFullSize); |
2276 | + settings_box.add_space(8); |
2277 | + cs_stopped_->set_enabled(can_act); |
2278 | + } else if (upcast(Widelands::MilitarysiteSettings, ms, construction_site->get_settings())) { |
2279 | + UI::Box& soldier_capacity_box = *new UI::Box(&settings_box, 0, 0, UI::Box::Horizontal); |
2280 | + settings_box.add(&soldier_capacity_box, UI::Box::Resizing::kAlign, UI::Align::kCenter); |
2281 | + cs_soldier_capacity_decrease_ = new UI::Button(&soldier_capacity_box, |
2282 | + "decrease", 0, 0, 32, 32, UI::ButtonStyle::kWuiMenu, |
2283 | + g_gr->images().get(pic_decrease_capacity), |
2284 | + _("Decrease capacity. Hold down Ctrl to set the capacity to the lowest value")); |
2285 | + cs_soldier_capacity_increase_ = new UI::Button(&soldier_capacity_box, |
2286 | + "increase", 0, 0, 32, 32, UI::ButtonStyle::kWuiMenu, |
2287 | + g_gr->images().get(pic_increase_capacity), |
2288 | + _("Increase capacity. Hold down Ctrl to set the capacity to the highest value")); |
2289 | + cs_soldier_capacity_display_ = new UI::Textarea(&soldier_capacity_box, |
2290 | + "", UI::Align::kCenter); |
2291 | + cs_soldier_capacity_decrease_->set_enabled(can_act); |
2292 | + cs_soldier_capacity_increase_->set_enabled(can_act); |
2293 | + cs_soldier_capacity_decrease_->sigclicked.connect([this, ms]() { |
2294 | + igbase()->game().send_player_change_soldier_capacity( |
2295 | + *construction_site_.get(igbase()->egbase()), |
2296 | + SDL_GetModState() & KMOD_CTRL ? 0 : ms->desired_capacity - 1); |
2297 | + }); |
2298 | + cs_soldier_capacity_increase_->sigclicked.connect([this, ms]() { |
2299 | + igbase()->game().send_player_change_soldier_capacity( |
2300 | + *construction_site_.get(igbase()->egbase()), |
2301 | + SDL_GetModState() & KMOD_CTRL ? ms->max_capacity : ms->desired_capacity + 1); |
2302 | + }); |
2303 | + soldier_capacity_box.add(cs_soldier_capacity_decrease_); |
2304 | + soldier_capacity_box.add_space(8); |
2305 | + soldier_capacity_box.add(cs_soldier_capacity_display_, UI::Box::Resizing::kAlign, UI::Align::kCenter); |
2306 | + soldier_capacity_box.add_space(8); |
2307 | + soldier_capacity_box.add(cs_soldier_capacity_increase_); |
2308 | + settings_box.add_space(8); |
2309 | + |
2310 | + UI::Box& soldier_preference_box = *new UI::Box(&settings_box, 0, 0, UI::Box::Horizontal); |
2311 | + settings_box.add(&soldier_preference_box, UI::Box::Resizing::kAlign, UI::Align::kCenter); |
2312 | + UI::Panel& soldier_preference_panel = *new UI::Panel(&soldier_preference_box, 0, 0, 64, 32); |
2313 | + soldier_preference_box.add(&soldier_preference_panel); |
2314 | + cs_prefer_heroes_rookies_.reset(new UI::Radiogroup()); |
2315 | + cs_prefer_heroes_rookies_->add_button(&soldier_preference_panel, Vector2i::zero(), |
2316 | + g_gr->images().get("images/wui/buildings/prefer_rookies.png"), |
2317 | + _("Prefer rookies")); |
2318 | + cs_prefer_heroes_rookies_->add_button(&soldier_preference_panel, Vector2i(32, 0), |
2319 | + g_gr->images().get("images/wui/buildings/prefer_heroes.png"), |
2320 | + _("Prefer heroes")); |
2321 | + if (can_act) { |
2322 | + cs_prefer_heroes_rookies_->changedto.connect([this](int32_t state) { |
2323 | + igbase()->game().send_player_militarysite_set_soldier_preference( |
2324 | + *construction_site_.get(igbase()->egbase()), |
2325 | + state ? Widelands::SoldierPreference::kHeroes : Widelands::SoldierPreference::kRookies); |
2326 | + }); |
2327 | + } |
2328 | + settings_box.add_space(8); |
2329 | + } else if (upcast(Widelands::WarehouseSettings, ws, construction_site->get_settings())) { |
2330 | + auto add_tab = [this, construction_site, can_act](Widelands::WareWorker ww, FakeWaresDisplay** display) { |
2331 | + UI::Box& mainbox = *new UI::Box(get_tabs(), 0, 0, UI::Box::Vertical); |
2332 | + *display = new FakeWaresDisplay(&mainbox, can_act, *construction_site, ww); |
2333 | + mainbox.add(*display, UI::Box::Resizing::kFullSize); |
2334 | + mainbox.add_space(8); |
2335 | + UI::Box& buttonsbox = *new UI::Box(&mainbox, 0, 0, UI::Box::Horizontal); |
2336 | + mainbox.add(&buttonsbox, UI::Box::Resizing::kAlign, UI::Align::kCenter); |
2337 | + mainbox.add_space(8); |
2338 | + UI::Button& sp_normal = *new UI::Button(&buttonsbox, "stock_policy_normal", 0, 0, 34, 34, |
2339 | + UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_stock_policy_button_normal), |
2340 | + _("Normal policy")); |
2341 | + UI::Button& sp_prefer = *new UI::Button(&buttonsbox, "stock_policy_prefer", 0, 0, 34, 34, |
2342 | + UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_stock_policy_button_prefer), |
2343 | + _("Preferably store selected wares here")); |
2344 | + UI::Button& sp_dont = *new UI::Button(&buttonsbox, "stock_policy_dontstock", 0, 0, 34, 34, |
2345 | + UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_stock_policy_button_dontstock), |
2346 | + _("Do not store selected wares here")); |
2347 | + UI::Button& sp_remove = *new UI::Button(&buttonsbox, "stock_policy_remove", 0, 0, 34, 34, |
2348 | + UI::ButtonStyle::kWuiMenu, g_gr->images().get(pic_stock_policy_button_remove), |
2349 | + _("Remove selected wares from here")); |
2350 | + sp_remove.sigclicked.connect( |
2351 | + boost::bind(&ConstructionSiteWindow::change_policy, this, ww, Widelands::StockPolicy::kRemove)); |
2352 | + sp_dont.sigclicked.connect( |
2353 | + boost::bind(&ConstructionSiteWindow::change_policy, this, ww, Widelands::StockPolicy::kDontStock)); |
2354 | + sp_prefer.sigclicked.connect( |
2355 | + boost::bind(&ConstructionSiteWindow::change_policy, this, ww, Widelands::StockPolicy::kPrefer)); |
2356 | + sp_normal.sigclicked.connect( |
2357 | + boost::bind(&ConstructionSiteWindow::change_policy, this, ww, Widelands::StockPolicy::kNormal)); |
2358 | + sp_normal.set_enabled(can_act); |
2359 | + sp_dont.set_enabled(can_act); |
2360 | + sp_remove.set_enabled(can_act); |
2361 | + sp_prefer.set_enabled(can_act); |
2362 | + buttonsbox.add(&sp_normal); |
2363 | + buttonsbox.add_space(8); |
2364 | + buttonsbox.add(&sp_prefer); |
2365 | + buttonsbox.add_space(8); |
2366 | + buttonsbox.add(&sp_dont); |
2367 | + buttonsbox.add_space(8); |
2368 | + buttonsbox.add(&sp_remove); |
2369 | + if (ww == Widelands::wwWARE) { |
2370 | + get_tabs()->add("warehouse_wares", g_gr->images().get(pic_tab_settings_wares), |
2371 | + &mainbox, _("Ware settings to apply after construction")); |
2372 | + } else { |
2373 | + get_tabs()->add("warehouse_workers", g_gr->images().get(pic_tab_settings_workers), |
2374 | + &mainbox, _("Worker settings to apply after construction")); |
2375 | + } |
2376 | + }; |
2377 | + add_tab(Widelands::wwWARE, &cs_warehouse_wares_); |
2378 | + add_tab(Widelands::wwWORKER, &cs_warehouse_workers_); |
2379 | + if (construction_site->get_info().becomes->get_isport()) { |
2380 | + cs_launch_expedition_ = new UI::Checkbox(&settings_box, Vector2i::zero(), |
2381 | + _("Start an expedition"), |
2382 | + _("Start an expedition from this port after completion")); |
2383 | + cs_launch_expedition_->clickedto.connect([this, ws](bool launch) { |
2384 | + if (launch != ws->launch_expedition) { |
2385 | + igbase()->game().send_player_start_or_cancel_expedition( |
2386 | + *construction_site_.get(igbase()->egbase())); |
2387 | + } |
2388 | + }); |
2389 | + settings_box.add(cs_launch_expedition_, UI::Box::Resizing::kFullSize); |
2390 | + settings_box.add_space(8); |
2391 | + cs_launch_expedition_->set_enabled(can_act); |
2392 | + } else { |
2393 | + nothing_added = true; |
2394 | + } |
2395 | + } else { |
2396 | + NEVER_HERE(); |
2397 | + } |
2398 | + |
2399 | + if (can_act && construction_site->get_info().becomes->enhancement() != Widelands::INVALID_INDEX) { |
2400 | + const Widelands::BuildingDescr& building_descr = *igbase()->egbase().tribes().get_building_descr( |
2401 | + construction_site->get_info().becomes->enhancement()); |
2402 | + std::string enhance_tooltip = |
2403 | + (boost::format(_("Enhance to %s")) % building_descr.descname().c_str()).str() + |
2404 | + "<br><font size=11>" + _("Construction costs:") + "</font><br>" + |
2405 | + waremap_to_richtext(construction_site->owner().tribe(), building_descr.enhancement_cost()); |
2406 | + cs_enhance_ = new UI::Button(&settings_box, "enhance", 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu, |
2407 | + building_descr.icon(), enhance_tooltip); |
2408 | + cs_enhance_->sigclicked.connect([this, construction_site] { |
2409 | + if (SDL_GetModState() & KMOD_CTRL) { |
2410 | + igbase()->game().send_player_enhance_building(*construction_site, Widelands::INVALID_INDEX); |
2411 | + } else { |
2412 | + show_enhance_confirm(dynamic_cast<InteractivePlayer&>(*igbase()), |
2413 | + *construction_site, construction_site->get_info().becomes->enhancement(), true); |
2414 | + } |
2415 | + }); |
2416 | + settings_box.add(cs_enhance_, UI::Box::Resizing::kAlign, UI::Align::kCenter); |
2417 | + settings_box.add_space(8); |
2418 | + nothing_added = false; |
2419 | + } |
2420 | + if (!nothing_added) { |
2421 | + get_tabs()->add("settings", g_gr->images().get(pic_tab_settings), |
2422 | + &settings_box, _("Settings to apply after construction")); |
2423 | + } |
2424 | + } |
2425 | + |
2426 | set_title((boost::format("(%s)") % construction_site->building().descname()).str()); |
2427 | think(); |
2428 | } |
2429 | |
2430 | +void ConstructionSiteWindow::change_policy(Widelands::WareWorker ww, Widelands::StockPolicy p) { |
2431 | + Widelands::ConstructionSite* construction_site = construction_site_.get(igbase()->egbase()); |
2432 | + assert(construction_site); |
2433 | + upcast(Widelands::WarehouseSettings, ws, construction_site->get_settings()); |
2434 | + assert(ws); |
2435 | + if (ww == Widelands::wwWARE) { |
2436 | + for (const auto& pair : ws->ware_preferences) { |
2437 | + if (cs_warehouse_wares_->ware_selected(pair.first)) { |
2438 | + igbase()->game().send_player_set_stock_policy(*construction_site, |
2439 | + Widelands::wwWARE, pair.first, p); |
2440 | + } |
2441 | + } |
2442 | + } else { |
2443 | + for (const auto& pair : ws->worker_preferences) { |
2444 | + if (cs_warehouse_workers_->ware_selected(pair.first)) { |
2445 | + igbase()->game().send_player_set_stock_policy(*construction_site, |
2446 | + Widelands::wwWORKER, pair.first, p); |
2447 | + } |
2448 | + } |
2449 | + } |
2450 | +} |
2451 | + |
2452 | /* |
2453 | =============== |
2454 | Make sure the window is redrawn when necessary. |
2455 | @@ -77,5 +380,41 @@ |
2456 | if (construction_site == nullptr) { |
2457 | return; |
2458 | } |
2459 | + |
2460 | progress_->set_state(construction_site->get_built_per64k()); |
2461 | + |
2462 | + const bool can_act = igbase()->can_act(construction_site->owner().player_number()); |
2463 | + // InputQueueDisplay and FakeWaresDisplay update themselves – we need to refresh the other settings |
2464 | + if (upcast(Widelands::ProductionsiteSettings, ps, construction_site->get_settings())) { |
2465 | + assert(cs_stopped_); |
2466 | + cs_stopped_->set_state(ps->stopped); |
2467 | + } |
2468 | + if (upcast(Widelands::TrainingsiteSettings, ts, construction_site->get_settings())) { |
2469 | + assert(cs_soldier_capacity_decrease_); |
2470 | + assert(cs_soldier_capacity_increase_); |
2471 | + assert(cs_soldier_capacity_display_); |
2472 | + cs_soldier_capacity_display_->set_text((boost::format(ngettext("%u soldier", "%u soldiers", |
2473 | + ts->desired_capacity)) % ts->desired_capacity).str()); |
2474 | + cs_soldier_capacity_decrease_->set_enabled(can_act && ts->desired_capacity > 0); |
2475 | + cs_soldier_capacity_increase_->set_enabled(can_act && ts->desired_capacity < ts->max_capacity); |
2476 | + } else if (upcast(Widelands::MilitarysiteSettings, ms, construction_site->get_settings())) { |
2477 | + assert(cs_soldier_capacity_decrease_); |
2478 | + assert(cs_soldier_capacity_increase_); |
2479 | + assert(cs_soldier_capacity_display_); |
2480 | + assert(cs_prefer_heroes_rookies_); |
2481 | + cs_soldier_capacity_display_->set_text((boost::format(ngettext("%u soldier", "%u soldiers", |
2482 | + ms->desired_capacity)) % ms->desired_capacity).str()); |
2483 | + cs_soldier_capacity_decrease_->set_enabled(can_act && ms->desired_capacity > 1); |
2484 | + cs_soldier_capacity_increase_->set_enabled(can_act && ms->desired_capacity < ms->max_capacity); |
2485 | + cs_prefer_heroes_rookies_->set_state(ms->prefer_heroes ? 1 : 0); |
2486 | + } else if (upcast(Widelands::WarehouseSettings, ws, construction_site->get_settings())) { |
2487 | + if (cs_launch_expedition_) { |
2488 | + cs_launch_expedition_->set_state(ws->launch_expedition); |
2489 | + } |
2490 | +#ifndef NDEBUG |
2491 | + else { |
2492 | + assert(!ws->launch_expedition); |
2493 | + } |
2494 | +#endif |
2495 | + } |
2496 | } |
2497 | |
2498 | === modified file 'src/wui/constructionsitewindow.h' |
2499 | --- src/wui/constructionsitewindow.h 2019-02-23 11:00:49 +0000 |
2500 | +++ src/wui/constructionsitewindow.h 2019-06-19 09:23:26 +0000 |
2501 | @@ -20,9 +20,18 @@ |
2502 | #ifndef WL_WUI_CONSTRUCTIONSITEWINDOW_H |
2503 | #define WL_WUI_CONSTRUCTIONSITEWINDOW_H |
2504 | |
2505 | +#include <memory> |
2506 | +#include <vector> |
2507 | + |
2508 | #include "logic/map_objects/tribes/constructionsite.h" |
2509 | +#include "ui_basic/button.h" |
2510 | +#include "ui_basic/checkbox.h" |
2511 | #include "ui_basic/progressbar.h" |
2512 | +#include "ui_basic/radiobutton.h" |
2513 | +#include "ui_basic/tabpanel.h" |
2514 | +#include "ui_basic/textarea.h" |
2515 | #include "wui/buildingwindow.h" |
2516 | +#include "wui/inputqueuedisplay.h" |
2517 | |
2518 | /** |
2519 | * Status window for construction sites. |
2520 | @@ -40,8 +49,38 @@ |
2521 | void init(bool avoid_fastclick, bool workarea_preview_wanted) override; |
2522 | |
2523 | private: |
2524 | + class FakeWaresDisplay : public WaresDisplay { |
2525 | + public: |
2526 | + FakeWaresDisplay(UI::Panel* parent, |
2527 | + bool can_act, |
2528 | + Widelands::ConstructionSite& cs, |
2529 | + Widelands::WareWorker type); |
2530 | + |
2531 | + protected: |
2532 | + void draw_ware(RenderTarget& dst, Widelands::DescriptionIndex ware) override; |
2533 | + |
2534 | + private: |
2535 | + Widelands::WarehouseSettings& settings_; |
2536 | + const Widelands::TribeDescr& tribe_; |
2537 | + }; |
2538 | + |
2539 | Widelands::OPtr<Widelands::ConstructionSite> construction_site_; |
2540 | UI::ProgressBar* progress_; |
2541 | + |
2542 | + // BuildingSettings-related UI elements |
2543 | + UI::Button* cs_enhance_; |
2544 | + UI::Checkbox* cs_launch_expedition_; |
2545 | + std::unique_ptr<UI::Radiogroup> cs_prefer_heroes_rookies_; |
2546 | + UI::Button* cs_soldier_capacity_decrease_; |
2547 | + UI::Button* cs_soldier_capacity_increase_; |
2548 | + UI::Textarea* cs_soldier_capacity_display_; |
2549 | + std::vector<InputQueueDisplay*> cs_ware_queues_; |
2550 | + std::vector<InputQueueDisplay*> cs_worker_queues_; |
2551 | + UI::Checkbox* cs_stopped_; |
2552 | + FakeWaresDisplay* cs_warehouse_wares_; |
2553 | + FakeWaresDisplay* cs_warehouse_workers_; |
2554 | + void change_policy(Widelands::WareWorker, Widelands::StockPolicy); |
2555 | + |
2556 | DISALLOW_COPY_AND_ASSIGN(ConstructionSiteWindow); |
2557 | }; |
2558 | |
2559 | |
2560 | === modified file 'src/wui/inputqueuedisplay.cc' |
2561 | --- src/wui/inputqueuedisplay.cc 2019-05-29 06:24:42 +0000 |
2562 | +++ src/wui/inputqueuedisplay.cc 2019-06-19 09:23:26 +0000 |
2563 | @@ -46,7 +46,8 @@ |
2564 | : UI::Panel(parent, x, y, 0, 28), |
2565 | igb_(igb), |
2566 | building_(building), |
2567 | - queue_(queue), |
2568 | + queue_(&queue), |
2569 | + settings_(nullptr), |
2570 | priority_radiogroup_(nullptr), |
2571 | increase_max_fill_(nullptr), |
2572 | decrease_max_fill_(nullptr), |
2573 | @@ -58,12 +59,58 @@ |
2574 | total_height_(0), |
2575 | show_only_(show_only) { |
2576 | if (type_ == Widelands::wwWARE) { |
2577 | - const Widelands::WareDescr& ware = *queue.owner().tribe().get_ware_descr(queue_.get_index()); |
2578 | + const Widelands::WareDescr& ware = *queue.owner().tribe().get_ware_descr(queue_->get_index()); |
2579 | set_tooltip(ware.descname().c_str()); |
2580 | icon_ = ware.icon(); |
2581 | } else { |
2582 | const Widelands::WorkerDescr& worker = |
2583 | - *queue.owner().tribe().get_worker_descr(queue_.get_index()); |
2584 | + *queue.owner().tribe().get_worker_descr(queue_->get_index()); |
2585 | + set_tooltip(worker.descname().c_str()); |
2586 | + icon_ = worker.icon(); |
2587 | + } |
2588 | + |
2589 | + uint16_t ph = max_fill_indicator_->height(); |
2590 | + |
2591 | + uint32_t priority_button_height = show_only ? 0 : 3 * PriorityButtonSize; |
2592 | + uint32_t image_height = |
2593 | + show_only ? kWareMenuPicHeight : std::max<int32_t>(kWareMenuPicHeight, ph); |
2594 | + |
2595 | + total_height_ = std::max(priority_button_height, image_height) + 2 * Border; |
2596 | + |
2597 | + max_size_changed(); |
2598 | + |
2599 | + set_thinks(true); |
2600 | +} |
2601 | + |
2602 | +InputQueueDisplay::InputQueueDisplay(UI::Panel* const parent, |
2603 | + int32_t const x, |
2604 | + int32_t const y, |
2605 | + InteractiveGameBase& igb, |
2606 | + Widelands::ConstructionSite& building, |
2607 | + Widelands::WareWorker ww, |
2608 | + Widelands::DescriptionIndex di, |
2609 | + bool show_only) |
2610 | + : UI::Panel(parent, x, y, 0, 28), |
2611 | + igb_(igb), |
2612 | + building_(building), |
2613 | + queue_(nullptr), |
2614 | + settings_(dynamic_cast<const Widelands::ProductionsiteSettings*>(building.get_settings())), |
2615 | + priority_radiogroup_(nullptr), |
2616 | + increase_max_fill_(nullptr), |
2617 | + decrease_max_fill_(nullptr), |
2618 | + index_(di), |
2619 | + type_(ww), |
2620 | + max_fill_indicator_(g_gr->images().get(pic_max_fill_indicator)), |
2621 | + total_height_(0), |
2622 | + show_only_(show_only) { |
2623 | + cache_size_ = check_max_size(); |
2624 | + cache_max_fill_ = check_max_fill(); |
2625 | + if (type_ == Widelands::wwWARE) { |
2626 | + const Widelands::WareDescr& ware = *building.owner().tribe().get_ware_descr(index_); |
2627 | + set_tooltip(ware.descname().c_str()); |
2628 | + icon_ = ware.icon(); |
2629 | + } else { |
2630 | + const Widelands::WorkerDescr& worker = *building.owner().tribe().get_worker_descr(index_); |
2631 | set_tooltip(worker.descname().c_str()); |
2632 | icon_ = worker.icon(); |
2633 | } |
2634 | @@ -85,6 +132,32 @@ |
2635 | delete priority_radiogroup_; |
2636 | } |
2637 | |
2638 | +uint32_t InputQueueDisplay::check_max_size() const { |
2639 | + if (queue_) { |
2640 | + return queue_->get_max_size(); |
2641 | + } |
2642 | + assert(settings_); |
2643 | + for (const auto& pair : type_ == Widelands::wwWARE ? settings_->ware_queues : settings_->worker_queues) { |
2644 | + if (pair.first == index_) { |
2645 | + return pair.second.max_fill; |
2646 | + } |
2647 | + } |
2648 | + NEVER_HERE(); |
2649 | +} |
2650 | + |
2651 | +uint32_t InputQueueDisplay::check_max_fill() const { |
2652 | + if (queue_) { |
2653 | + return queue_->get_max_fill(); |
2654 | + } |
2655 | + assert(settings_); |
2656 | + for (const auto& pair : type_ == Widelands::wwWARE ? settings_->ware_queues : settings_->worker_queues) { |
2657 | + if (pair.first == index_) { |
2658 | + return pair.second.desired_fill; |
2659 | + } |
2660 | + } |
2661 | + NEVER_HERE(); |
2662 | +} |
2663 | + |
2664 | /** |
2665 | * Recalculate the panel's size based on the size of the queue. |
2666 | * |
2667 | @@ -94,7 +167,7 @@ |
2668 | uint32_t pbs = show_only_ ? 0 : PriorityButtonSize; |
2669 | uint32_t ctrl_b_size = show_only_ ? 0 : 2 * kWareMenuPicWidth; |
2670 | |
2671 | - cache_size_ = queue_.get_max_size(); |
2672 | + cache_size_ = check_max_size(); |
2673 | |
2674 | update_priority_buttons(); |
2675 | update_max_fill_buttons(); |
2676 | @@ -111,12 +184,12 @@ |
2677 | * Compare the current InputQueue state with the cached state; update if necessary. |
2678 | */ |
2679 | void InputQueueDisplay::think() { |
2680 | - if (static_cast<uint32_t>(queue_.get_max_size()) != cache_size_) |
2681 | + if (static_cast<uint32_t>(check_max_size()) != cache_size_) |
2682 | max_size_changed(); |
2683 | |
2684 | // TODO(sirver): It seems cache_max_fill_ is not really useful for anything. |
2685 | - if (static_cast<uint32_t>(queue_.get_max_fill()) != cache_max_fill_) { |
2686 | - cache_max_fill_ = queue_.get_max_fill(); |
2687 | + if (static_cast<uint32_t>(check_max_fill()) != cache_max_fill_) { |
2688 | + cache_max_fill_ = check_max_fill(); |
2689 | compute_max_fill_buttons_enabled_state(); |
2690 | } |
2691 | } |
2692 | @@ -128,11 +201,12 @@ |
2693 | if (!cache_size_) |
2694 | return; |
2695 | |
2696 | - cache_max_fill_ = queue_.get_max_fill(); |
2697 | + cache_max_fill_ = check_max_fill(); |
2698 | |
2699 | - uint32_t nr_inputs_to_draw = std::min(queue_.get_filled(), cache_size_); |
2700 | + uint32_t nr_inputs_to_draw = queue_ ? std::min(queue_->get_filled(), cache_size_) : cache_max_fill_; |
2701 | uint32_t nr_missing_to_draw = |
2702 | - std::min(queue_.get_missing(), cache_max_fill_) + cache_size_ - cache_max_fill_; |
2703 | + queue_ ? std::min(queue_->get_missing(), cache_max_fill_) + cache_size_ - cache_max_fill_ : |
2704 | + cache_size_ - cache_max_fill_; |
2705 | if (nr_inputs_to_draw > cache_max_fill_) { |
2706 | nr_missing_to_draw -= nr_inputs_to_draw - cache_max_fill_; |
2707 | } |
2708 | @@ -162,7 +236,7 @@ |
2709 | uint16_t pw = max_fill_indicator_->width(); |
2710 | point.y = Border; |
2711 | point.x = Border + CellWidth + CellSpacing + |
2712 | - (queue_.get_max_fill() * (CellWidth + CellSpacing)) - CellSpacing / 2 - pw / 2; |
2713 | + (cache_max_fill_ * (CellWidth + CellSpacing)) - CellSpacing / 2 - pw / 2; |
2714 | dst.blit(point, max_fill_indicator_); |
2715 | } |
2716 | } |
2717 | @@ -206,13 +280,13 @@ |
2718 | |
2719 | int32_t priority = building_.get_priority(type_, index_, false); |
2720 | switch (priority) { |
2721 | - case HIGH_PRIORITY: |
2722 | + case Widelands::kPriorityHigh: |
2723 | priority_radiogroup_->set_state(0); |
2724 | break; |
2725 | - case DEFAULT_PRIORITY: |
2726 | + case Widelands::kPriorityNormal: |
2727 | priority_radiogroup_->set_state(1); |
2728 | break; |
2729 | - case LOW_PRIORITY: |
2730 | + case Widelands::kPriorityLow: |
2731 | priority_radiogroup_->set_state(2); |
2732 | break; |
2733 | default: |
2734 | @@ -314,13 +388,13 @@ |
2735 | |
2736 | switch (state) { |
2737 | case 0: |
2738 | - priority = HIGH_PRIORITY; |
2739 | + priority = Widelands::kPriorityHigh; |
2740 | break; |
2741 | case 1: |
2742 | - priority = DEFAULT_PRIORITY; |
2743 | + priority = Widelands::kPriorityNormal; |
2744 | break; |
2745 | case 2: |
2746 | - priority = LOW_PRIORITY; |
2747 | + priority = Widelands::kPriorityLow; |
2748 | break; |
2749 | default: |
2750 | return; |
2751 | |
2752 | === modified file 'src/wui/inputqueuedisplay.h' |
2753 | --- src/wui/inputqueuedisplay.h 2019-05-06 10:53:42 +0000 |
2754 | +++ src/wui/inputqueuedisplay.h 2019-06-19 09:23:26 +0000 |
2755 | @@ -39,6 +39,8 @@ |
2756 | |
2757 | namespace Widelands { |
2758 | class Building; |
2759 | +class ConstructionSite; |
2760 | +struct ProductionsiteSettings; |
2761 | class InputQueue; |
2762 | } // namespace Widelands |
2763 | |
2764 | @@ -51,6 +53,7 @@ |
2765 | public: |
2766 | enum { CellWidth = kWareMenuPicWidth, CellSpacing = 2, Border = 4, PriorityButtonSize = 10 }; |
2767 | |
2768 | + // Constructor for real queues (e.g. in ProductionSites) |
2769 | InputQueueDisplay(UI::Panel* parent, |
2770 | int32_t x, |
2771 | int32_t y, |
2772 | @@ -58,6 +61,15 @@ |
2773 | Widelands::Building& building, |
2774 | const Widelands::InputQueue& queue, |
2775 | bool = false); |
2776 | + // Constructor for fake queues (e.g. in ConstructionSite settings) |
2777 | + InputQueueDisplay(UI::Panel* parent, |
2778 | + int32_t x, |
2779 | + int32_t y, |
2780 | + InteractiveGameBase&, |
2781 | + Widelands::ConstructionSite&, |
2782 | + Widelands::WareWorker, |
2783 | + Widelands::DescriptionIndex, |
2784 | + bool = false); |
2785 | ~InputQueueDisplay() override; |
2786 | |
2787 | void think() override; |
2788 | @@ -66,7 +78,8 @@ |
2789 | private: |
2790 | InteractiveGameBase& igb_; |
2791 | Widelands::Building& building_; |
2792 | - const Widelands::InputQueue& queue_; |
2793 | + const Widelands::InputQueue* queue_; |
2794 | + const Widelands::ProductionsiteSettings* settings_; |
2795 | UI::Radiogroup* priority_radiogroup_; |
2796 | UI::Button* increase_max_fill_; |
2797 | UI::Button* decrease_max_fill_; |
2798 | @@ -90,6 +103,9 @@ |
2799 | void update_siblings_priority(int32_t); |
2800 | void update_siblings_fill(int32_t); |
2801 | |
2802 | + uint32_t check_max_size() const; |
2803 | + uint32_t check_max_fill() const; |
2804 | + |
2805 | void compute_max_fill_buttons_enabled_state(); |
2806 | }; |
2807 | |
2808 | |
2809 | === modified file 'src/wui/warehousewindow.cc' |
2810 | --- src/wui/warehousewindow.cc 2019-05-01 07:20:25 +0000 |
2811 | +++ src/wui/warehousewindow.cc 2019-06-19 09:23:26 +0000 |
2812 | @@ -75,19 +75,19 @@ |
2813 | void WarehouseWaresDisplay::draw_ware(RenderTarget& dst, Widelands::DescriptionIndex ware) { |
2814 | WaresDisplay::draw_ware(dst, ware); |
2815 | |
2816 | - Widelands::Warehouse::StockPolicy policy = warehouse_.get_stock_policy(get_type(), ware); |
2817 | + Widelands::StockPolicy policy = warehouse_.get_stock_policy(get_type(), ware); |
2818 | const Image* pic = nullptr; |
2819 | switch (policy) { |
2820 | - case Widelands::Warehouse::StockPolicy::kPrefer: |
2821 | + case Widelands::StockPolicy::kPrefer: |
2822 | pic = g_gr->images().get(pic_policy_prefer); |
2823 | break; |
2824 | - case Widelands::Warehouse::StockPolicy::kDontStock: |
2825 | + case Widelands::StockPolicy::kDontStock: |
2826 | pic = g_gr->images().get(pic_policy_dontstock); |
2827 | break; |
2828 | - case Widelands::Warehouse::StockPolicy::kRemove: |
2829 | + case Widelands::StockPolicy::kRemove: |
2830 | pic = g_gr->images().get(pic_policy_remove); |
2831 | break; |
2832 | - case Widelands::Warehouse::StockPolicy::kNormal: |
2833 | + case Widelands::StockPolicy::kNormal: |
2834 | // don't draw anything for the normal policy |
2835 | return; |
2836 | } |
2837 | @@ -106,7 +106,7 @@ |
2838 | Widelands::Warehouse&, |
2839 | Widelands::WareWorker type); |
2840 | |
2841 | - void set_policy(Widelands::Warehouse::StockPolicy); |
2842 | + void set_policy(Widelands::StockPolicy); |
2843 | |
2844 | private: |
2845 | InteractiveGameBase& gb_; |
2846 | @@ -139,7 +139,7 @@ |
2847 | buttons, #policy, 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu, \ |
2848 | g_gr->images().get("images/wui/buildings/stock_policy_button_" #policy ".png"), tooltip), \ |
2849 | b->sigclicked.connect(boost::bind( \ |
2850 | - &WarehouseWaresPanel::set_policy, this, Widelands::Warehouse::StockPolicy::k##policyname)), \ |
2851 | + &WarehouseWaresPanel::set_policy, this, Widelands::StockPolicy::k##policyname)), \ |
2852 | buttons->add(b); |
2853 | |
2854 | ADD_POLICY_BUTTON(normal, Normal, _("Normal policy")) |
2855 | @@ -152,7 +152,7 @@ |
2856 | /** |
2857 | * Add Buttons policy buttons |
2858 | */ |
2859 | -void WarehouseWaresPanel::set_policy(Widelands::Warehouse::StockPolicy newpolicy) { |
2860 | +void WarehouseWaresPanel::set_policy(Widelands::StockPolicy newpolicy) { |
2861 | if (gb_.can_act(wh_.owner().player_number())) { |
2862 | bool is_workers = type_ == Widelands::wwWORKER; |
2863 | const std::set<Widelands::DescriptionIndex> indices = |
Continuous integration builds have changed state:
Travis build 4971. State: errored. Details: https:/ /travis- ci.org/ widelands/ widelands/ builds/ 532431388. /ci.appveyor. com/project/ widelands- dev/widelands/ build/_ widelands_ dev_widelands_ constructionsit e_options- 4752.
Appveyor build 4752. State: success. Details: https:/