Merge lp:~widelands-dev/widelands/storages_garrisons into lp:widelands
- storages_garrisons
- Merge into trunk
Status: | Work in progress |
---|---|
Proposed branch: | lp:~widelands-dev/widelands/storages_garrisons |
Merge into: | lp:widelands |
Diff against target: |
11158 lines (+5369/-2734) (has conflicts) 103 files modified
global/militarysites/barracks.empire/conf (+4/-2) global/militarysites/barrier.barbarians/conf (+5/-3) global/militarysites/barrier.empire/conf (+5/-3) global/militarysites/castle.atlanteans/conf (+4/-2) global/militarysites/castle.empire/conf (+5/-3) global/militarysites/citadel.barbarians/conf (+5/-3) global/militarysites/donjon.barbarians/conf (+5/-3) global/militarysites/fortress.barbarians/conf (+5/-3) global/militarysites/fortress.empire/conf (+5/-3) global/militarysites/guardhall.atlanteans/conf (+4/-2) global/militarysites/guardhouse.atlanteans/conf (+3/-1) global/militarysites/high_tower.atlanteans/conf (+5/-3) global/militarysites/outpost.empire/conf (+5/-3) global/militarysites/sentry.barbarians/conf (+4/-2) global/militarysites/sentry.empire/conf (+4/-2) global/militarysites/small_tower.atlanteans/conf (+5/-3) global/militarysites/stronghold.barbarians/conf (+5/-3) global/militarysites/tower.atlanteans/conf (+6/-4) global/militarysites/tower.empire/conf (+5/-4) src/ai/defaultai.cc (+43/-56) src/ai/defaultai.h (+1/-1) src/economy/economy.cc (+69/-70) src/economy/economy.h (+11/-8) src/economy/idleworkersupply.cc (+3/-3) src/economy/idleworkersupply.h (+3/-1) src/economy/portdock.cc (+2/-2) src/economy/request.cc (+21/-9) src/economy/request.h (+10/-3) src/economy/supply.h (+4/-2) src/economy/transfer.cc (+1/-0) src/economy/ware_instance.cc (+11/-11) src/economy/warehousesupply.h (+0/-76) src/logic/attackable.h (+0/-84) src/logic/building.h (+3/-0) src/logic/findimmovable.cc (+2/-2) src/logic/game.cc (+2/-1) src/logic/game.h (+2/-1) src/logic/garrison.h (+227/-0) src/logic/garrisonhandler.cc (+925/-0) src/logic/garrisonhandler.h (+262/-0) src/logic/item_ware_descr.h (+2/-2) src/logic/militarysite.cc (+159/-173) src/logic/militarysite.h (+14/-96) src/logic/player.cc (+24/-21) src/logic/player.h (+1/-1) src/logic/playercommand.cc (+29/-29) src/logic/playercommand.h (+9/-8) src/logic/production_program.cc (+12/-5) src/logic/productionsite.cc (+1/-1) src/logic/soldier.cc (+35/-20) src/logic/soldiercontrol.h (+0/-119) src/logic/storage.h (+195/-0) src/logic/storagehandler.cc (+1127/-0) src/logic/storagehandler.h (+247/-0) src/logic/trainingsite.cc (+97/-220) src/logic/trainingsite.h (+14/-36) src/logic/warehouse.cc (+111/-459) src/logic/warehouse.h (+19/-115) src/logic/worker.cc (+19/-19) src/logic/worker.h (+3/-0) src/map_io/widelands_map_buildingdata_data_packet.cc (+750/-561) src/map_io/widelands_map_buildingdata_data_packet.h (+18/-0) src/scripting/lua_game.cc (+13/-18) src/scripting/lua_map.cc (+219/-72) src/scripting/lua_map.h (+73/-15) src/wui/attack_box.h (+0/-1) src/wui/buildingwindow.cc (+4/-4) src/wui/fieldaction.cc (+3/-4) src/wui/garrisonpanel.cc (+137/-0) src/wui/garrisonpanel.h (+65/-0) src/wui/military_box.h (+0/-1) src/wui/militarysitewindow.cc (+4/-2) src/wui/soldiercapacitycontrol.cc (+10/-40) src/wui/soldiercapacitycontrol.h (+35/-11) src/wui/soldierlist.cc (+14/-212) src/wui/soldierlist.h (+70/-10) src/wui/stock_menu.cc (+11/-14) src/wui/trainingsitewindow.cc (+4/-6) src/wui/warehousewindow.cc (+23/-8) tribes/atlanteans/castle/conf (+3/-1) tribes/atlanteans/guardhall/conf (+3/-1) tribes/atlanteans/guardhouse/conf (+2/-0) tribes/atlanteans/headquarters/conf (+4/-0) tribes/atlanteans/high_tower/conf (+6/-4) tribes/atlanteans/small_tower/conf (+3/-1) tribes/atlanteans/tower/conf (+5/-3) tribes/barbarians/barrier/conf (+4/-2) tribes/barbarians/citadel/conf (+5/-3) tribes/barbarians/donjon/conf (+5/-3) tribes/barbarians/fortress/conf (+5/-3) tribes/barbarians/headquarters/conf (+5/-1) tribes/barbarians/headquarters_interim/conf (+5/-1) tribes/barbarians/sentry/conf (+3/-1) tribes/barbarians/stronghold/conf (+6/-4) tribes/empire/barracks/conf (+4/-2) tribes/empire/barrier/conf (+5/-3) tribes/empire/castle/conf (+5/-3) tribes/empire/fortress/conf (+5/-3) tribes/empire/headquarters/conf (+5/-1) tribes/empire/headquarters_shipwreck/conf (+5/-1) tribes/empire/outpost/conf (+5/-3) tribes/empire/sentry/conf (+4/-2) tribes/empire/tower/conf (+5/-3) Text conflict in src/logic/militarysite.cc Text conflict in src/logic/soldier.cc Text conflict in src/logic/warehouse.cc Text conflict in src/logic/warehouse.h Text conflict in src/scripting/lua_game.cc Text conflict in src/wui/warehousewindow.cc |
To merge this branch: | bzr merge lp:~widelands-dev/widelands/storages_garrisons |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
SirVer | Needs Fixing | ||
Review via email: mp+178704@code.launchpad.net |
Commit message
Description of the change
I'm not finished working on it yet, but I already put it on review so you can check changes and suggest design changes.
This is a refactoring in order to separate storages (entities storing wares/workers) from the warehouse class and garrisons (entities storing soldiers with control) from the militarysites/
I try to commit only playable revisions. Please note that post-b17 savegames may not be compatible.
My plan is to move portdock stuff out of warehouse class and add a an optional garrison on warehouses for headquarters.
cghislai (charlyghislain) wrote : | # |
You don't have to review the whole thing now. At the very best I would appreciate knowing if I am in the wrong before putting much time in it.
The important files are new interfaces (storage.h garrison.h) and how they are used (militarysite.cc warehouse.cc)
SirVer (sirver) wrote : | # |
Thanks, the pointer to the files to look at was very good. In general I think this is a great change and improves the design a lot - it also shows further places for refactoring which were much harder to see before this change. Here are some thoughts:
class Storage:
looks good. Could you use more empty lines to separate the methods? Also, it feels like wares and workers are disjunct, so maybe you can make a HasWares and HasWorkers Interface (those are the names I choose for Lua, consistency would be preferred, but not needed). I see that you use a lot of interfaces here - be aware that you cannot use double inheritance freely in the code as we static_cast a lot around and this breaks with double inheritance.
class Garrison:
I do not understand how you want to deal trainingssites with this one. It seems to implement the interface needed for warfare which will not be supported by trainingssites/
About the use case: Interfaces are not a as good an idea in C++ than in Java. C++ does not have the concept and therefore creates storage for the classes. This leads to problems like the diamond inheritance[1]. This can be worked around using virtual inheritance, but then you can no longer static_cast your class pointers around. My suggestion for the design here would be to use composition [2] instead - and I would probably add getters into Building that return nullptr_t - productionsites and so on can then overwrite these getters to return correct values. So, by default a Building does not has_wares, nor has_workers nor has_soldiers, but some specialized buildings can overwrite these then.
[1] http://
[2] http://
SirVer (sirver) wrote : | # |
This change would still be awesome to have in Widelands. Charly, you are not by any chance taking things on again soon?
cghislai (charlyghislain) wrote : | # |
Im working on the fh1 branch, but I will have a look into that afterwards.
On Sun, Jul 20, 2014 at 9:56 PM, SirVer <email address hidden> wrote:
> This change would still be awesome to have in Widelands. Charly, you are
> not by any chance taking things on again soon?
> --
>
> https:/
> You proposed lp:~widelands-dev/widelands/storages_garrisons for merging.
>
SirVer (sirver) wrote : | # |
Cool. I am working on getting rid of the old font renderer too in https:/
cghislai (charlyghislain) wrote : | # |
Yep
Ill push my code as soons as I have this last bug gone with the editbox.
On Mon, Jul 21, 2014 at 6:53 AM, SirVer <email address hidden> wrote:
> Cool. I am working on getting rid of the old font renderer too in
> https:/
> Maybe we can join forces.
>
> --
>
> https:/
> You proposed lp:~widelands-dev/widelands/storages_garrisons for merging.
>
Preview Diff
1 | === modified file 'global/militarysites/barracks.empire/conf' | |||
2 | --- global/militarysites/barracks.empire/conf 2013-06-11 16:37:44 +0000 | |||
3 | +++ global/militarysites/barracks.empire/conf 2013-08-10 10:53:03 +0000 | |||
4 | @@ -1,9 +1,11 @@ | |||
5 | 1 | size=small | 1 | size=small |
7 | 2 | heal_per_second=60 # very low -> smallest building | 2 | buildable=no |
8 | 3 | |||
9 | 4 | [garrison] | ||
10 | 3 | conquers=6 | 5 | conquers=6 |
11 | 4 | max_soldiers=1 | 6 | max_soldiers=1 |
12 | 5 | buildable=no | ||
13 | 6 | prefer_heroes=false | 7 | prefer_heroes=false |
14 | 8 | heal_per_second=60 | ||
15 | 7 | 9 | ||
16 | 8 | [idle] | 10 | [idle] |
17 | 9 | pics=../../../tribes/empire/barracks/barracks_i_??.png | 11 | pics=../../../tribes/empire/barracks/barracks_i_??.png |
18 | 10 | 12 | ||
19 | === modified file 'global/militarysites/barrier.barbarians/conf' | |||
20 | --- global/militarysites/barrier.barbarians/conf 2013-06-11 16:37:44 +0000 | |||
21 | +++ global/militarysites/barrier.barbarians/conf 2013-08-10 10:53:03 +0000 | |||
22 | @@ -1,9 +1,11 @@ | |||
23 | 1 | size=medium | 1 | size=medium |
24 | 2 | buildable=no | ||
25 | 3 | |||
26 | 4 | [garrison] | ||
27 | 5 | conquers=8 | ||
28 | 2 | max_soldiers=5 | 6 | max_soldiers=5 |
29 | 7 | prefer_heroes=true | ||
30 | 3 | heal_per_second=130 | 8 | heal_per_second=130 |
31 | 4 | conquers=8 | ||
32 | 5 | buildable=no | ||
33 | 6 | prefer_heroes=true | ||
34 | 7 | 9 | ||
35 | 8 | [idle] | 10 | [idle] |
36 | 9 | pics=../../../tribes/barbarians/barrier/barrier_i_??.png | 11 | pics=../../../tribes/barbarians/barrier/barrier_i_??.png |
37 | 10 | 12 | ||
38 | === modified file 'global/militarysites/barrier.empire/conf' | |||
39 | --- global/militarysites/barrier.empire/conf 2013-06-11 16:37:44 +0000 | |||
40 | +++ global/militarysites/barrier.empire/conf 2013-08-10 10:53:03 +0000 | |||
41 | @@ -1,9 +1,11 @@ | |||
42 | 1 | size=medium | 1 | size=medium |
43 | 2 | buildable=no | ||
44 | 3 | |||
45 | 4 | [garrison] | ||
46 | 5 | conquers=8 | ||
47 | 2 | max_soldiers=5 | 6 | max_soldiers=5 |
48 | 7 | prefer_heroes=true | ||
49 | 3 | heal_per_second=130 | 8 | heal_per_second=130 |
50 | 4 | conquers=8 | ||
51 | 5 | buildable=no | ||
52 | 6 | prefer_heroes=true | ||
53 | 7 | 9 | ||
54 | 8 | [idle] | 10 | [idle] |
55 | 9 | pics=../../../tribes/empire/barrier/barrier_i_??.png | 11 | pics=../../../tribes/empire/barrier/barrier_i_??.png |
56 | 10 | 12 | ||
57 | === modified file 'global/militarysites/castle.atlanteans/conf' | |||
58 | --- global/militarysites/castle.atlanteans/conf 2013-06-11 16:37:44 +0000 | |||
59 | +++ global/militarysites/castle.atlanteans/conf 2013-08-10 10:53:03 +0000 | |||
60 | @@ -1,8 +1,10 @@ | |||
61 | 1 | size=big | 1 | size=big |
63 | 2 | max_soldiers=12 | 2 | buildable=no |
64 | 3 | |||
65 | 4 | [garrison] | ||
66 | 3 | heal_per_second=200 | 5 | heal_per_second=200 |
67 | 4 | conquers=12 | 6 | conquers=12 |
69 | 5 | buildable=no | 7 | max_soldiers=12 |
70 | 6 | prefer_heroes=true | 8 | prefer_heroes=true |
71 | 7 | 9 | ||
72 | 8 | [idle] | 10 | [idle] |
73 | 9 | 11 | ||
74 | === modified file 'global/militarysites/castle.empire/conf' | |||
75 | --- global/militarysites/castle.empire/conf 2013-06-11 16:37:44 +0000 | |||
76 | +++ global/militarysites/castle.empire/conf 2013-08-10 10:53:03 +0000 | |||
77 | @@ -1,9 +1,11 @@ | |||
78 | 1 | size=big | 1 | size=big |
79 | 2 | buildable=no | ||
80 | 3 | |||
81 | 4 | [garrison] | ||
82 | 5 | conquers=12 | ||
83 | 2 | max_soldiers=12 | 6 | max_soldiers=12 |
84 | 7 | prefer_heroes=true | ||
85 | 3 | heal_per_second=220 | 8 | heal_per_second=220 |
86 | 4 | conquers=12 | ||
87 | 5 | buildable=no | ||
88 | 6 | prefer_heroes=true | ||
89 | 7 | 9 | ||
90 | 8 | [idle] | 10 | [idle] |
91 | 9 | pics=../../../tribes/empire/castle/castle_i_??.png | 11 | pics=../../../tribes/empire/castle/castle_i_??.png |
92 | 10 | 12 | ||
93 | === modified file 'global/militarysites/citadel.barbarians/conf' | |||
94 | --- global/militarysites/citadel.barbarians/conf 2013-06-11 16:37:44 +0000 | |||
95 | +++ global/militarysites/citadel.barbarians/conf 2013-08-10 10:53:03 +0000 | |||
96 | @@ -1,9 +1,11 @@ | |||
97 | 1 | size=big | 1 | size=big |
98 | 2 | buildable=no | ||
99 | 3 | |||
100 | 4 | [garrison] | ||
101 | 5 | conquers=12 | ||
102 | 2 | max_soldiers=12 | 6 | max_soldiers=12 |
103 | 7 | prefer_heroes=true | ||
104 | 3 | heal_per_second=220 | 8 | heal_per_second=220 |
105 | 4 | conquers=12 | ||
106 | 5 | buildable=no | ||
107 | 6 | prefer_heroes=true | ||
108 | 7 | 9 | ||
109 | 8 | [idle] | 10 | [idle] |
110 | 9 | pics=../../../tribes/barbarians/citadel/citadel_i_??.png | 11 | pics=../../../tribes/barbarians/citadel/citadel_i_??.png |
111 | 10 | 12 | ||
112 | === modified file 'global/militarysites/donjon.barbarians/conf' | |||
113 | --- global/militarysites/donjon.barbarians/conf 2013-06-11 16:37:44 +0000 | |||
114 | +++ global/militarysites/donjon.barbarians/conf 2013-08-10 10:53:03 +0000 | |||
115 | @@ -1,10 +1,12 @@ | |||
116 | 1 | size=medium | 1 | size=medium |
117 | 2 | max_soldiers=5 | ||
118 | 3 | heal_per_second=150 | ||
119 | 4 | conquers=8 | ||
120 | 5 | vision_range=17 | 2 | vision_range=17 |
121 | 6 | buildable=no | 3 | buildable=no |
122 | 4 | |||
123 | 5 | [garrison] | ||
124 | 6 | conquers=8 | ||
125 | 7 | max_soldiers=5 | ||
126 | 7 | prefer_heroes=true | 8 | prefer_heroes=true |
127 | 9 | heal_per_second=150 | ||
128 | 8 | 10 | ||
129 | 9 | [idle] | 11 | [idle] |
130 | 10 | pics=../../../tribes/barbarians/donjon/donjon_i_??.png | 12 | pics=../../../tribes/barbarians/donjon/donjon_i_??.png |
131 | 11 | 13 | ||
132 | === modified file 'global/militarysites/fortress.barbarians/conf' | |||
133 | --- global/militarysites/fortress.barbarians/conf 2013-06-11 16:37:44 +0000 | |||
134 | +++ global/militarysites/fortress.barbarians/conf 2013-08-10 10:53:03 +0000 | |||
135 | @@ -1,9 +1,11 @@ | |||
136 | 1 | size=big | 1 | size=big |
137 | 2 | buildable=no | ||
138 | 3 | |||
139 | 4 | [garrison] | ||
140 | 5 | conquers=11 | ||
141 | 2 | max_soldiers=8 | 6 | max_soldiers=8 |
142 | 7 | prefer_heroes=true | ||
143 | 3 | heal_per_second=170 | 8 | heal_per_second=170 |
144 | 4 | conquers=11 | ||
145 | 5 | buildable=no | ||
146 | 6 | prefer_heroes=true | ||
147 | 7 | 9 | ||
148 | 8 | [idle] | 10 | [idle] |
149 | 9 | pics=../../../tribes/barbarians/fortress/fortress_i_??.png | 11 | pics=../../../tribes/barbarians/fortress/fortress_i_??.png |
150 | 10 | 12 | ||
151 | === modified file 'global/militarysites/fortress.empire/conf' | |||
152 | --- global/militarysites/fortress.empire/conf 2013-06-11 16:37:44 +0000 | |||
153 | +++ global/militarysites/fortress.empire/conf 2013-08-10 10:53:03 +0000 | |||
154 | @@ -1,9 +1,11 @@ | |||
155 | 1 | size=big | 1 | size=big |
156 | 2 | buildable=no | ||
157 | 3 | |||
158 | 4 | [garrison] | ||
159 | 5 | conquers=11 | ||
160 | 2 | max_soldiers=8 | 6 | max_soldiers=8 |
161 | 7 | prefer_heroes=true | ||
162 | 3 | heal_per_second=170 | 8 | heal_per_second=170 |
163 | 4 | conquers=11 | ||
164 | 5 | buildable=no | ||
165 | 6 | prefer_heroes=true | ||
166 | 7 | 9 | ||
167 | 8 | [idle] | 10 | [idle] |
168 | 9 | pics=../../../tribes/empire/fortress/fortress_i_??.png | 11 | pics=../../../tribes/empire/fortress/fortress_i_??.png |
169 | 10 | 12 | ||
170 | === modified file 'global/militarysites/guardhall.atlanteans/conf' | |||
171 | --- global/militarysites/guardhall.atlanteans/conf 2013-06-11 16:37:44 +0000 | |||
172 | +++ global/militarysites/guardhall.atlanteans/conf 2013-08-10 10:53:03 +0000 | |||
173 | @@ -1,8 +1,10 @@ | |||
174 | 1 | size=medium | 1 | size=medium |
176 | 2 | max_soldiers=7 | 2 | buildable=no |
177 | 3 | |||
178 | 4 | [garrison] | ||
179 | 3 | heal_per_second=140 | 5 | heal_per_second=140 |
180 | 4 | conquers=7 | 6 | conquers=7 |
182 | 5 | buildable=no | 7 | max_soldiers=7 |
183 | 6 | prefer_heroes=true | 8 | prefer_heroes=true |
184 | 7 | 9 | ||
185 | 8 | [idle] | 10 | [idle] |
186 | 9 | 11 | ||
187 | === modified file 'global/militarysites/guardhouse.atlanteans/conf' | |||
188 | --- global/militarysites/guardhouse.atlanteans/conf 2013-06-11 16:37:44 +0000 | |||
189 | +++ global/militarysites/guardhouse.atlanteans/conf 2013-08-10 10:53:03 +0000 | |||
190 | @@ -1,8 +1,10 @@ | |||
191 | 1 | size=small | 1 | size=small |
192 | 2 | buildable=no | ||
193 | 3 | |||
194 | 4 | [garrison] | ||
195 | 2 | heal_per_second=75 | 5 | heal_per_second=75 |
196 | 3 | conquers=6 | 6 | conquers=6 |
197 | 4 | max_soldiers=2 | 7 | max_soldiers=2 |
198 | 5 | buildable=no | ||
199 | 6 | prefer_heroes=false | 8 | prefer_heroes=false |
200 | 7 | 9 | ||
201 | 8 | [idle] | 10 | [idle] |
202 | 9 | 11 | ||
203 | === modified file 'global/militarysites/high_tower.atlanteans/conf' | |||
204 | --- global/militarysites/high_tower.atlanteans/conf 2013-06-11 16:37:44 +0000 | |||
205 | +++ global/militarysites/high_tower.atlanteans/conf 2013-08-10 10:53:03 +0000 | |||
206 | @@ -1,10 +1,12 @@ | |||
207 | 1 | size=medium | 1 | size=medium |
208 | 2 | max_soldiers=5 | ||
209 | 3 | heal_per_second=170 | ||
210 | 4 | conquers=9 | ||
211 | 5 | vision_range=21 | 2 | vision_range=21 |
212 | 6 | buildable=no | 3 | buildable=no |
213 | 4 | |||
214 | 5 | [garrison] | ||
215 | 6 | conquers=9 | ||
216 | 7 | max_soldiers=5 | ||
217 | 7 | prefer_heroes=true | 8 | prefer_heroes=true |
218 | 9 | heal_per_second=170 | ||
219 | 8 | 10 | ||
220 | 9 | [idle] | 11 | [idle] |
221 | 10 | pics=../../../tribes/atlanteans/high_tower/high_tower_i_??.png | 12 | pics=../../../tribes/atlanteans/high_tower/high_tower_i_??.png |
222 | 11 | 13 | ||
223 | === modified file 'global/militarysites/outpost.empire/conf' | |||
224 | --- global/militarysites/outpost.empire/conf 2013-06-11 16:37:44 +0000 | |||
225 | +++ global/militarysites/outpost.empire/conf 2013-08-10 10:53:03 +0000 | |||
226 | @@ -1,9 +1,11 @@ | |||
227 | 1 | size=medium | 1 | size=medium |
228 | 2 | buildable=no | ||
229 | 3 | |||
230 | 4 | [garrison] | ||
231 | 5 | conquers=7 | ||
232 | 2 | max_soldiers=3 | 6 | max_soldiers=3 |
233 | 7 | prefer_heroes=false | ||
234 | 3 | heal_per_second=100 | 8 | heal_per_second=100 |
235 | 4 | conquers=7 | ||
236 | 5 | buildable=no | ||
237 | 6 | prefer_heroes=false | ||
238 | 7 | 9 | ||
239 | 8 | [idle] | 10 | [idle] |
240 | 9 | pics=../../../tribes/empire/outpost/outpost_i_??.png | 11 | pics=../../../tribes/empire/outpost/outpost_i_??.png |
241 | 10 | 12 | ||
242 | === modified file 'global/militarysites/sentry.barbarians/conf' | |||
243 | --- global/militarysites/sentry.barbarians/conf 2013-06-11 16:37:44 +0000 | |||
244 | +++ global/militarysites/sentry.barbarians/conf 2013-08-10 10:53:03 +0000 | |||
245 | @@ -1,9 +1,11 @@ | |||
246 | 1 | size=small | 1 | size=small |
248 | 2 | heal_per_second=80 | 2 | buildable=no |
249 | 3 | |||
250 | 4 | [garrison] | ||
251 | 3 | conquers=6 | 5 | conquers=6 |
252 | 4 | max_soldiers=2 | 6 | max_soldiers=2 |
253 | 5 | buildable=no | ||
254 | 6 | prefer_heroes=false | 7 | prefer_heroes=false |
255 | 8 | heal_per_second=80 | ||
256 | 7 | 9 | ||
257 | 8 | [idle] | 10 | [idle] |
258 | 9 | pics=../../../tribes/barbarians/sentry/sentry_i_??.png | 11 | pics=../../../tribes/barbarians/sentry/sentry_i_??.png |
259 | 10 | 12 | ||
260 | === modified file 'global/militarysites/sentry.empire/conf' | |||
261 | --- global/militarysites/sentry.empire/conf 2013-06-11 16:37:44 +0000 | |||
262 | +++ global/militarysites/sentry.empire/conf 2013-08-10 10:53:03 +0000 | |||
263 | @@ -1,9 +1,11 @@ | |||
264 | 1 | size=small | 1 | size=small |
266 | 2 | heal_per_second=80 | 2 | buildable=no |
267 | 3 | |||
268 | 4 | [garrison] | ||
269 | 3 | conquers=6 | 5 | conquers=6 |
270 | 4 | max_soldiers=2 | 6 | max_soldiers=2 |
271 | 5 | buildable=no | ||
272 | 6 | prefer_heroes=false | 7 | prefer_heroes=false |
273 | 8 | heal_per_second=80 | ||
274 | 7 | 9 | ||
275 | 8 | [idle] | 10 | [idle] |
276 | 9 | pics=../../../tribes/empire/sentry/sentry_i_??.png | 11 | pics=../../../tribes/empire/sentry/sentry_i_??.png |
277 | 10 | 12 | ||
278 | === modified file 'global/militarysites/small_tower.atlanteans/conf' | |||
279 | --- global/militarysites/small_tower.atlanteans/conf 2013-06-11 16:37:44 +0000 | |||
280 | +++ global/militarysites/small_tower.atlanteans/conf 2013-08-10 10:53:03 +0000 | |||
281 | @@ -1,10 +1,12 @@ | |||
282 | 1 | size=small | 1 | size=small |
283 | 2 | vision_range=13 | ||
284 | 3 | buildable=no | ||
285 | 4 | |||
286 | 5 | [garrison] | ||
287 | 2 | heal_per_second=100 | 6 | heal_per_second=100 |
288 | 3 | conquers=5 | 7 | conquers=5 |
289 | 4 | vision_range=13 | ||
290 | 5 | max_soldiers=3 | 8 | max_soldiers=3 |
293 | 6 | buildable=no | 9 | prefer_heroes=true |
292 | 7 | prefer_heroes=false | ||
294 | 8 | 10 | ||
295 | 9 | [idle] | 11 | [idle] |
296 | 10 | pics=../../../tribes/atlanteans/small_tower/small_tower_i_??.png | 12 | pics=../../../tribes/atlanteans/small_tower/small_tower_i_??.png |
297 | 11 | 13 | ||
298 | === modified file 'global/militarysites/stronghold.barbarians/conf' | |||
299 | --- global/militarysites/stronghold.barbarians/conf 2013-06-11 16:37:44 +0000 | |||
300 | +++ global/militarysites/stronghold.barbarians/conf 2013-08-10 10:53:03 +0000 | |||
301 | @@ -1,9 +1,11 @@ | |||
302 | 1 | size=medium | 1 | size=medium |
303 | 2 | buildable=no | ||
304 | 3 | |||
305 | 4 | [garrison] | ||
306 | 5 | conquers=7 | ||
307 | 2 | max_soldiers=3 | 6 | max_soldiers=3 |
308 | 7 | prefer_heroes=false | ||
309 | 3 | heal_per_second=110 | 8 | heal_per_second=110 |
310 | 4 | conquers=7 | ||
311 | 5 | buildable=no | ||
312 | 6 | prefer_heroes=false | ||
313 | 7 | 9 | ||
314 | 8 | [idle] | 10 | [idle] |
315 | 9 | pics=../../../tribes/barbarians/stronghold/stronghold_i_??.png | 11 | pics=../../../tribes/barbarians/stronghold/stronghold_i_??.png |
316 | 10 | 12 | ||
317 | === modified file 'global/militarysites/tower.atlanteans/conf' | |||
318 | --- global/militarysites/tower.atlanteans/conf 2013-06-11 16:37:44 +0000 | |||
319 | +++ global/militarysites/tower.atlanteans/conf 2013-08-10 10:53:03 +0000 | |||
320 | @@ -1,10 +1,12 @@ | |||
321 | 1 | size=medium | 1 | size=medium |
323 | 2 | max_soldiers=4 | 2 | vision_range=17 |
324 | 3 | buildable=no | ||
325 | 4 | |||
326 | 5 | [garrison] | ||
327 | 3 | heal_per_second=120 | 6 | heal_per_second=120 |
328 | 4 | conquers=9 | 7 | conquers=9 |
332 | 5 | vision_range=17 | 8 | max_soldiers=4 |
333 | 6 | buildable=no | 9 | prefer_heroes=false |
331 | 7 | prefer_heroes=true | ||
334 | 8 | 10 | ||
335 | 9 | [idle] | 11 | [idle] |
336 | 10 | pics=../../../tribes/atlanteans/tower/tower_i_??.png | 12 | pics=../../../tribes/atlanteans/tower/tower_i_??.png |
337 | 11 | 13 | ||
338 | === modified file 'global/militarysites/tower.empire/conf' | |||
339 | --- global/militarysites/tower.empire/conf 2013-06-11 16:37:44 +0000 | |||
340 | +++ global/militarysites/tower.empire/conf 2013-08-10 10:53:03 +0000 | |||
341 | @@ -1,10 +1,11 @@ | |||
342 | 1 | size=medium | 1 | size=medium |
343 | 2 | buildable=no | ||
344 | 3 | |||
345 | 4 | [garrison] | ||
346 | 5 | conquers=9 | ||
347 | 2 | max_soldiers=5 | 6 | max_soldiers=5 |
348 | 7 | prefer_heroes=true | ||
349 | 3 | heal_per_second=150 | 8 | heal_per_second=150 |
350 | 4 | conquers=9 | ||
351 | 5 | vision_range=19 | ||
352 | 6 | buildable=no | ||
353 | 7 | prefer_heroes=true | ||
354 | 8 | 9 | ||
355 | 9 | [idle] | 10 | [idle] |
356 | 10 | pics=../../../tribes/empire/tower/tower_i_??.png | 11 | pics=../../../tribes/empire/tower/tower_i_??.png |
357 | 11 | 12 | ||
358 | === modified file 'src/ai/defaultai.cc' | |||
359 | --- src/ai/defaultai.cc 2013-07-26 20:19:36 +0000 | |||
360 | +++ src/ai/defaultai.cc 2013-08-10 10:53:03 +0000 | |||
361 | @@ -72,7 +72,7 @@ | |||
362 | 72 | next_attack_consideration_due(300000), | 72 | next_attack_consideration_due(300000), |
363 | 73 | inhibit_road_building (0), | 73 | inhibit_road_building (0), |
364 | 74 | time_of_last_construction (0), | 74 | time_of_last_construction (0), |
366 | 75 | numof_warehouses (0) | 75 | numof_storages (0) |
367 | 76 | {} | 76 | {} |
368 | 77 | 77 | ||
369 | 78 | DefaultAI::~DefaultAI() | 78 | DefaultAI::~DefaultAI() |
370 | @@ -577,7 +577,7 @@ | |||
371 | 577 | 577 | ||
372 | 578 | if (v > 0) | 578 | if (v > 0) |
373 | 579 | field.military_influence += | 579 | field.military_influence += |
375 | 580 | v * v * militarysite->soldierCapacity(); | 580 | v * v * militarysite->get_garrison()->soldierCapacity(); |
376 | 581 | } | 581 | } |
377 | 582 | 582 | ||
378 | 583 | if (dynamic_cast<const ProductionSite *>(building)) | 583 | if (dynamic_cast<const ProductionSite *>(building)) |
379 | @@ -626,7 +626,7 @@ | |||
380 | 626 | 626 | ||
381 | 627 | if (v > 0) | 627 | if (v > 0) |
382 | 628 | field.military_influence += | 628 | field.military_influence += |
384 | 629 | v * v * militarysite->soldierCapacity(); | 629 | v * v * militarysite->get_garrison()->soldierCapacity(); |
385 | 630 | } | 630 | } |
386 | 631 | } | 631 | } |
387 | 632 | } | 632 | } |
388 | @@ -881,8 +881,8 @@ | |||
389 | 881 | // Check if the produced wares are needed | 881 | // Check if the produced wares are needed |
390 | 882 | Ware_Index wt(static_cast<size_t>(bo.outputs.at(0))); | 882 | Ware_Index wt(static_cast<size_t>(bo.outputs.at(0))); |
391 | 883 | container_iterate(std::list<EconomyObserver *>, economies, l) { | 883 | container_iterate(std::list<EconomyObserver *>, economies, l) { |
394 | 884 | // Don't check if the economy has no warehouse. | 884 | // Don't check if the economy has no storage. |
395 | 885 | if ((*l.current)->economy.warehouses().empty()) | 885 | if ((*l.current)->economy.storages().empty()) |
396 | 886 | continue; | 886 | continue; |
397 | 887 | if ((*l.current)->economy.needs_ware(wt)) | 887 | if ((*l.current)->economy.needs_ware(wt)) |
398 | 888 | prio += 1 + wares.at(bo.outputs.at(0)).preciousness; | 888 | prio += 1 + wares.at(bo.outputs.at(0)).preciousness; |
399 | @@ -918,8 +918,8 @@ | |||
400 | 918 | // the ware they're refreshing | 918 | // the ware they're refreshing |
401 | 919 | Ware_Index wt(static_cast<size_t>(bo.production_hint)); | 919 | Ware_Index wt(static_cast<size_t>(bo.production_hint)); |
402 | 920 | container_iterate(std::list<EconomyObserver *>, economies, l) { | 920 | container_iterate(std::list<EconomyObserver *>, economies, l) { |
405 | 921 | // Don't check if the economy has no warehouse. | 921 | // Don't check if the economy has no storages. |
406 | 922 | if ((*l.current)->economy.warehouses().empty()) | 922 | if ((*l.current)->economy.storages().empty()) |
407 | 923 | continue; | 923 | continue; |
408 | 924 | if ((*l.current)->economy.needs_ware(wt)) { | 924 | if ((*l.current)->economy.needs_ware(wt)) { |
409 | 925 | prio += wares.at(bo.production_hint).preciousness * inout * 2; | 925 | prio += wares.at(bo.production_hint).preciousness * inout * 2; |
410 | @@ -964,8 +964,8 @@ | |||
411 | 964 | 964 | ||
412 | 965 | // Check if the produced wares are needed | 965 | // Check if the produced wares are needed |
413 | 966 | container_iterate(std::list<EconomyObserver *>, economies, l) { | 966 | container_iterate(std::list<EconomyObserver *>, economies, l) { |
416 | 967 | // Don't check if the economy has no warehouse. | 967 | // Don't check if the economy has no storages. |
417 | 968 | if ((*l.current)->economy.warehouses().empty()) | 968 | if ((*l.current)->economy.storages().empty()) |
418 | 969 | continue; | 969 | continue; |
419 | 970 | for (uint32_t m = 0; m < bo.outputs.size(); ++m) { | 970 | for (uint32_t m = 0; m < bo.outputs.size(); ++m) { |
420 | 971 | Ware_Index wt(static_cast<size_t>(bo.outputs.at(m))); | 971 | Ware_Index wt(static_cast<size_t>(bo.outputs.at(m))); |
421 | @@ -1056,7 +1056,7 @@ | |||
422 | 1056 | // needed for soldier training) near the frontier. | 1056 | // needed for soldier training) near the frontier. |
423 | 1057 | prio += productionsites.size() + mines.size(); | 1057 | prio += productionsites.size() + mines.size(); |
424 | 1058 | prio += militarysites.size() / 3; | 1058 | prio += militarysites.size() / 3; |
426 | 1059 | prio -= (bo.cnt_under_construction + numof_warehouses) * 35; | 1059 | prio -= (bo.cnt_under_construction + numof_storages) * 35; |
427 | 1060 | prio *= 2; | 1060 | prio *= 2; |
428 | 1061 | 1061 | ||
429 | 1062 | // take care about borders and enemies | 1062 | // take care about borders and enemies |
430 | @@ -1880,13 +1880,13 @@ | |||
431 | 1880 | 1880 | ||
432 | 1881 | if (map.find_fields(Area<FCoords>(f, vision), 0, find_unowned) == 0) { | 1881 | if (map.find_fields(Area<FCoords>(f, vision), 0, find_unowned) == 0) { |
433 | 1882 | // If no enemy in sight - decrease the number of stationed soldiers | 1882 | // If no enemy in sight - decrease the number of stationed soldiers |
435 | 1883 | // as long as it is > 1 - BUT take care that there is a warehouse in the | 1883 | // as long as it is > 1 - BUT take care that there is a storage in the |
436 | 1884 | // same economy where the thrown out soldiers can go to. | 1884 | // same economy where the thrown out soldiers can go to. |
440 | 1885 | if (ms->economy().warehouses().size()) { | 1885 | if (ms->economy().storages().size()) { |
441 | 1886 | uint32_t const j = ms->soldierCapacity(); | 1886 | uint32_t const j = ms->get_garrison()->soldierCapacity(); |
442 | 1887 | if (MilitarySite::kPrefersRookies != ms->get_soldier_preference()) | 1887 | if (Garrison::SoldierPref::Rookies != ms->get_garrison()->get_soldier_preference()) |
443 | 1888 | { | 1888 | { |
445 | 1889 | game().send_player_militarysite_set_soldier_preference(*ms, MilitarySite::kPrefersRookies); | 1889 | game().send_player_militarysite_set_soldier_preference(*ms, Garrison::SoldierPref::Rookies); |
446 | 1890 | } | 1890 | } |
447 | 1891 | else | 1891 | else |
448 | 1892 | if (j > 1) | 1892 | if (j > 1) |
449 | @@ -1912,7 +1912,7 @@ | |||
450 | 1912 | // the destruction of the flag avoids that defaultAI will have | 1912 | // the destruction of the flag avoids that defaultAI will have |
451 | 1913 | // too many unused roads - if needed the road will be rebuild | 1913 | // too many unused roads - if needed the road will be rebuild |
452 | 1914 | // directly. | 1914 | // directly. |
454 | 1915 | if (static_cast<int32_t>(ms->maxSoldierCapacity() * 4) < bf.military_influence) { | 1915 | if (static_cast<int32_t>(ms->get_garrison()->maxSoldierCapacity() * 4) < bf.military_influence) { |
455 | 1916 | if (ms->get_playercaps() & Widelands::Building::PCap_Dismantle) { | 1916 | if (ms->get_playercaps() & Widelands::Building::PCap_Dismantle) { |
456 | 1917 | flags_to_be_removed.push_back(ms->base_flag().get_position()); | 1917 | flags_to_be_removed.push_back(ms->base_flag().get_position()); |
457 | 1918 | game().send_player_dismantle(*ms); | 1918 | game().send_player_dismantle(*ms); |
458 | @@ -1964,12 +1964,12 @@ | |||
459 | 1964 | } else { | 1964 | } else { |
460 | 1965 | // If an enemy is in sight and the number of stationed soldier is not | 1965 | // If an enemy is in sight and the number of stationed soldier is not |
461 | 1966 | // at maximum - set it to maximum. | 1966 | // at maximum - set it to maximum. |
464 | 1967 | uint32_t const j = ms->maxSoldierCapacity(); | 1967 | uint32_t const j = ms->get_garrison()->maxSoldierCapacity(); |
465 | 1968 | uint32_t const k = ms->soldierCapacity(); | 1968 | uint32_t const k = ms->get_garrison()->soldierCapacity(); |
466 | 1969 | if (j > k) | 1969 | if (j > k) |
467 | 1970 | game().send_player_change_soldier_capacity(*ms, j - k); | 1970 | game().send_player_change_soldier_capacity(*ms, j - k); |
470 | 1971 | if (MilitarySite::kPrefersHeroes != ms->get_soldier_preference()) | 1971 | if (Garrison::SoldierPref::Heroes != ms->get_garrison()->get_soldier_preference()) |
471 | 1972 | game().send_player_militarysite_set_soldier_preference(*ms, MilitarySite::kPrefersHeroes); | 1972 | game().send_player_militarysite_set_soldier_preference(*ms, Garrison::SoldierPref::Heroes); |
472 | 1973 | changed = true; | 1973 | changed = true; |
473 | 1974 | } | 1974 | } |
474 | 1975 | reorder:; | 1975 | reorder:; |
475 | @@ -2182,7 +2182,7 @@ | |||
476 | 2182 | militarysites.back().bo = &bo; | 2182 | militarysites.back().bo = &bo; |
477 | 2183 | militarysites.back().checks = bo.desc->get_size(); | 2183 | militarysites.back().checks = bo.desc->get_size(); |
478 | 2184 | } else if (bo.type == BuildingObserver::WAREHOUSE) | 2184 | } else if (bo.type == BuildingObserver::WAREHOUSE) |
480 | 2185 | ++numof_warehouses; | 2185 | ++numof_storages; |
481 | 2186 | } | 2186 | } |
482 | 2187 | } | 2187 | } |
483 | 2188 | 2188 | ||
484 | @@ -2244,8 +2244,8 @@ | |||
485 | 2244 | break; | 2244 | break; |
486 | 2245 | } | 2245 | } |
487 | 2246 | } else if (bo.type == BuildingObserver::WAREHOUSE) { | 2246 | } else if (bo.type == BuildingObserver::WAREHOUSE) { |
490 | 2247 | assert(numof_warehouses > 0); | 2247 | assert(numof_storages > 0); |
491 | 2248 | --numof_warehouses; | 2248 | --numof_storages; |
492 | 2249 | } | 2249 | } |
493 | 2250 | } | 2250 | } |
494 | 2251 | m_buildable_changed = true; | 2251 | m_buildable_changed = true; |
495 | @@ -2310,41 +2310,28 @@ | |||
496 | 2310 | map.find_immovables | 2310 | map.find_immovables |
497 | 2311 | (Area<FCoords>(f, vision), &immovables, FindImmovableAttackable()); | 2311 | (Area<FCoords>(f, vision), &immovables, FindImmovableAttackable()); |
498 | 2312 | 2312 | ||
532 | 2313 | for (uint32_t j = 0; j < immovables.size(); ++j) | 2313 | for (uint32_t j = 0; j < immovables.size(); ++j) { |
533 | 2314 | if (upcast(MilitarySite, bld, immovables.at(j).object)) { | 2314 | if (upcast(GarrisonOwner, go, immovables.at(j).object)) { |
534 | 2315 | if (!player->is_hostile(bld->owner())) | 2315 | if (!player->is_hostile(go->get_garrison()->owner())) { |
535 | 2316 | continue; | 2316 | continue; |
536 | 2317 | if (bld->canAttack()) { | 2317 | } |
537 | 2318 | int32_t ta = player->findAttackSoldiers(bld->base_flag()); | 2318 | if (!go->get_garrison()->canAttack()) { |
538 | 2319 | if (type == NORMAL) | 2319 | continue; |
539 | 2320 | ta = ta * 2 / 3; | 2320 | } |
540 | 2321 | if (ta < 1) | 2321 | int32_t ta = player->findAttackSoldiers(go->get_building()->base_flag()); |
541 | 2322 | continue; | 2322 | if (type == NORMAL) |
542 | 2323 | 2323 | ta = ta * 2 / 3; | |
543 | 2324 | int32_t const tc = ta - bld->presentSoldiers().size(); | 2324 | if (ta < 1) |
544 | 2325 | if (tc > chance) { | 2325 | continue; |
545 | 2326 | target = bld; | 2326 | |
546 | 2327 | chance = tc; | 2327 | int32_t const tc = ta - go->get_garrison()->presentSoldiers().size(); |
547 | 2328 | attackers = ta; | 2328 | if (tc > chance) { |
548 | 2329 | } | 2329 | target = go->get_building(); |
549 | 2330 | } | 2330 | chance = tc; |
550 | 2331 | } else if (upcast(Warehouse, wh, immovables.at(j).object)) { | 2331 | attackers = ta; |
518 | 2332 | if (!player->is_hostile(wh->owner())) | ||
519 | 2333 | continue; | ||
520 | 2334 | if (wh->canAttack()) { | ||
521 | 2335 | int32_t ta = player->findAttackSoldiers(wh->base_flag()); | ||
522 | 2336 | if (ta < 1) | ||
523 | 2337 | continue; | ||
524 | 2338 | |||
525 | 2339 | // extra priority push! | ||
526 | 2340 | int32_t tc = ta * 2; | ||
527 | 2341 | if (tc > chance) { | ||
528 | 2342 | target = wh; | ||
529 | 2343 | chance = tc; | ||
530 | 2344 | attackers = ta; | ||
531 | 2345 | } | ||
551 | 2346 | } | 2332 | } |
552 | 2347 | } | 2333 | } |
553 | 2334 | } | ||
554 | 2348 | 2335 | ||
555 | 2349 | // Reenque militarysite at the end of list | 2336 | // Reenque militarysite at the end of list |
556 | 2350 | militarysites.push_back(militarysites.front()); | 2337 | militarysites.push_back(militarysites.front()); |
557 | 2351 | 2338 | ||
558 | === modified file 'src/ai/defaultai.h' | |||
559 | --- src/ai/defaultai.h 2013-07-26 20:19:36 +0000 | |||
560 | +++ src/ai/defaultai.h 2013-08-10 10:53:03 +0000 | |||
561 | @@ -191,7 +191,7 @@ | |||
562 | 191 | int32_t inhibit_road_building; | 191 | int32_t inhibit_road_building; |
563 | 192 | int32_t time_of_last_construction; | 192 | int32_t time_of_last_construction; |
564 | 193 | 193 | ||
566 | 194 | uint16_t numof_warehouses; | 194 | uint16_t numof_storages; |
567 | 195 | }; | 195 | }; |
568 | 196 | 196 | ||
569 | 197 | #endif | 197 | #endif |
570 | 198 | 198 | ||
571 | === modified file 'src/economy/economy.cc' | |||
572 | --- src/economy/economy.cc 2013-07-26 20:19:36 +0000 | |||
573 | +++ src/economy/economy.cc 2013-08-10 10:53:03 +0000 | |||
574 | @@ -27,11 +27,10 @@ | |||
575 | 27 | #include "economy/route.h" | 27 | #include "economy/route.h" |
576 | 28 | #include "economy/routeastar.h" | 28 | #include "economy/routeastar.h" |
577 | 29 | #include "economy/router.h" | 29 | #include "economy/router.h" |
578 | 30 | #include "economy/warehousesupply.h" | ||
579 | 31 | #include "logic/game.h" | 30 | #include "logic/game.h" |
580 | 32 | #include "logic/player.h" | 31 | #include "logic/player.h" |
581 | 32 | #include "logic/storage.h" | ||
582 | 33 | #include "logic/tribe.h" | 33 | #include "logic/tribe.h" |
583 | 34 | #include "logic/warehouse.h" | ||
584 | 35 | #include "upcast.h" | 34 | #include "upcast.h" |
585 | 36 | #include "wexception.h" | 35 | #include "wexception.h" |
586 | 37 | 36 | ||
587 | @@ -78,8 +77,8 @@ | |||
588 | 78 | log("Warning: Economy still has requests left on destruction\n"); | 77 | log("Warning: Economy still has requests left on destruction\n"); |
589 | 79 | if (m_flags.size()) | 78 | if (m_flags.size()) |
590 | 80 | log("Warning: Economy still has flags left on destruction\n"); | 79 | log("Warning: Economy still has flags left on destruction\n"); |
593 | 81 | if (m_warehouses.size()) | 80 | if (m_storages.size()) |
594 | 82 | log("Warning: Economy still has warehouses left on destruction\n"); | 81 | log("Warning: Economy still has storages left on destruction\n"); |
595 | 83 | 82 | ||
596 | 84 | delete[] m_ware_target_quantities; | 83 | delete[] m_ware_target_quantities; |
597 | 85 | delete[] m_worker_target_quantities; | 84 | delete[] m_worker_target_quantities; |
598 | @@ -214,22 +213,22 @@ | |||
599 | 214 | }; | 213 | }; |
600 | 215 | 214 | ||
601 | 216 | /** | 215 | /** |
603 | 217 | * Find the warehouse closest to the given starting flag. | 216 | * Find the storage owner closest to the given starting flag. |
604 | 218 | * | 217 | * |
605 | 219 | * If the search was successful and \p route is non-null, | 218 | * If the search was successful and \p route is non-null, |
606 | 220 | * a route is also computed. | 219 | * a route is also computed. |
607 | 221 | * | 220 | * |
608 | 222 | * \param start starting flag | 221 | * \param start starting flag |
609 | 223 | * \param type whether to path-find as if the path were for a ware | 222 | * \param type whether to path-find as if the path were for a ware |
611 | 224 | * \param route if non-null, fill in a route to the warehouse | 223 | * \param route if non-null, fill in a route to the storage |
612 | 225 | * \param cost_cutoff if positive, find paths of at most | 224 | * \param cost_cutoff if positive, find paths of at most |
613 | 226 | * that length (in milliseconds) | 225 | * that length (in milliseconds) |
614 | 227 | */ | 226 | */ |
616 | 228 | Warehouse * Economy::find_closest_warehouse | 227 | StorageOwner* Economy::find_closest_storage |
617 | 229 | (Flag & start, WareWorker type, Route * route, uint32_t cost_cutoff, | 228 | (Flag & start, WareWorker type, Route * route, uint32_t cost_cutoff, |
619 | 230 | const Economy::WarehouseAcceptFn & acceptfn) | 229 | const Economy::StorageAcceptFn & acceptfn) |
620 | 231 | { | 230 | { |
622 | 232 | if (!warehouses().size()) | 231 | if (!storages().size()) |
623 | 233 | return 0; | 232 | return 0; |
624 | 234 | 233 | ||
625 | 235 | // A-star with zero estimator = Dijkstra | 234 | // A-star with zero estimator = Dijkstra |
626 | @@ -243,11 +242,11 @@ | |||
627 | 243 | return 0; | 242 | return 0; |
628 | 244 | 243 | ||
629 | 245 | Flag & flag = current->base_flag(); | 244 | Flag & flag = current->base_flag(); |
632 | 246 | if (upcast(Warehouse, warehouse, flag.get_building())) { | 245 | if (upcast(StorageOwner, storage_owner, flag.get_building())) { |
633 | 247 | if (!acceptfn || acceptfn(*warehouse)) { | 246 | if (!acceptfn || acceptfn(storage_owner)) { |
634 | 248 | if (route) | 247 | if (route) |
635 | 249 | astar.routeto(flag, *route); | 248 | astar.routeto(flag, *route); |
637 | 250 | return warehouse; | 249 | return storage_owner; |
638 | 251 | } | 250 | } |
639 | 252 | } | 251 | } |
640 | 253 | } | 252 | } |
641 | @@ -368,7 +367,7 @@ | |||
642 | 368 | 367 | ||
643 | 369 | /** | 368 | /** |
644 | 370 | * Call this whenever a ware is destroyed or consumed, e.g. food has been | 369 | * Call this whenever a ware is destroyed or consumed, e.g. food has been |
646 | 371 | * eaten or a warehouse has been destroyed. | 370 | * eaten or a storage has been destroyed. |
647 | 372 | * This is also called when a ware is removed from the economy through trade or | 371 | * This is also called when a ware is removed from the economy through trade or |
648 | 373 | * a split of the Economy. | 372 | * a split of the Economy. |
649 | 374 | */ | 373 | */ |
650 | @@ -397,32 +396,32 @@ | |||
651 | 397 | } | 396 | } |
652 | 398 | 397 | ||
653 | 399 | /** | 398 | /** |
657 | 400 | * Add the warehouse to our list of warehouses. | 399 | * Add the storage to our list of storages. |
658 | 401 | * This also adds the wares in the warehouse to the economy. However, if wares | 400 | * This also adds the wares in the storage to the economy. However, if wares |
659 | 402 | * are added to the warehouse in the future, add_wares() must be called. | 401 | * are added to the storage in the future, add_wares() must be called. |
660 | 403 | */ | 402 | */ |
662 | 404 | void Economy::add_warehouse(Warehouse & wh) | 403 | void Economy::add_storage(Storage & storage) |
663 | 405 | { | 404 | { |
665 | 406 | m_warehouses.push_back(&wh); | 405 | m_storages.push_back(&storage); |
666 | 407 | } | 406 | } |
667 | 408 | 407 | ||
668 | 409 | /** | 408 | /** |
670 | 410 | * Remove the warehouse and its wares from the economy. | 409 | * Remove the storage and its wares from the economy. |
671 | 411 | */ | 410 | */ |
673 | 412 | void Economy::remove_warehouse(Warehouse & wh) | 411 | void Economy::remove_storage(Storage & storage) |
674 | 413 | { | 412 | { |
679 | 414 | for (size_t i = 0; i < m_warehouses.size(); ++i) | 413 | for (size_t i = 0; i < m_storages.size(); ++i) |
680 | 415 | if (m_warehouses[i] == &wh) { | 414 | if (m_storages[i] == &storage) { |
681 | 416 | m_warehouses[i] = *m_warehouses.rbegin(); | 415 | m_storages[i] = *m_storages.rbegin(); |
682 | 417 | m_warehouses.pop_back(); | 416 | m_storages.pop_back(); |
683 | 418 | return; | 417 | return; |
684 | 419 | } | 418 | } |
685 | 420 | 419 | ||
686 | 421 | 420 | ||
688 | 422 | // This assert was modified, since on loading, warehouses might try to | 421 | // This assert was modified, since on loading, storages might try to |
689 | 423 | // remove themselves from their own economy, though they weren't added | 422 | // remove themselves from their own economy, though they weren't added |
690 | 424 | // (since they weren't initialized) | 423 | // (since they weren't initialized) |
692 | 425 | assert(m_warehouses.empty()); | 424 | assert(m_storages.empty()); |
693 | 426 | } | 425 | } |
694 | 427 | 426 | ||
695 | 428 | /** | 427 | /** |
696 | @@ -495,8 +494,8 @@ | |||
697 | 495 | bool Economy::needs_ware(Ware_Index const ware_type) const { | 494 | bool Economy::needs_ware(Ware_Index const ware_type) const { |
698 | 496 | uint32_t const t = ware_target_quantity(ware_type).permanent; | 495 | uint32_t const t = ware_target_quantity(ware_type).permanent; |
699 | 497 | uint32_t quantity = 0; | 496 | uint32_t quantity = 0; |
702 | 498 | container_iterate_const(std::vector<Warehouse *>, m_warehouses, wh) { | 497 | container_iterate_const(std::vector<Storage *>, m_storages, storage) { |
703 | 499 | quantity += (*wh)->get_wares().stock(ware_type); | 498 | quantity += (*storage)->get_wares().stock(ware_type); |
704 | 500 | if (t <= quantity) | 499 | if (t <= quantity) |
705 | 501 | return false; | 500 | return false; |
706 | 502 | } | 501 | } |
707 | @@ -507,8 +506,8 @@ | |||
708 | 507 | bool Economy::needs_worker(Ware_Index const worker_type) const { | 506 | bool Economy::needs_worker(Ware_Index const worker_type) const { |
709 | 508 | uint32_t const t = worker_target_quantity(worker_type).permanent; | 507 | uint32_t const t = worker_target_quantity(worker_type).permanent; |
710 | 509 | uint32_t quantity = 0; | 508 | uint32_t quantity = 0; |
713 | 510 | container_iterate_const(std::vector<Warehouse *>, m_warehouses, wh) { | 509 | container_iterate_const(std::vector<Storage *>, m_storages, storage) { |
714 | 511 | quantity += (*wh)->get_workers().stock(worker_type); | 510 | quantity += (*storage)->get_workers().stock(worker_type); |
715 | 512 | if (t <= quantity) | 511 | if (t <= quantity) |
716 | 513 | return false; | 512 | return false; |
717 | 514 | } | 513 | } |
718 | @@ -796,7 +795,7 @@ | |||
719 | 796 | 795 | ||
720 | 797 | /** | 796 | /** |
721 | 798 | * Check whether there is a supply for the given request. If the request is a | 797 | * Check whether there is a supply for the given request. If the request is a |
723 | 799 | * worker request without supply, attempt to create a new worker in a warehouse. | 798 | * worker request without supply, attempt to create a new worker in a storage. |
724 | 800 | */ | 799 | */ |
725 | 801 | void Economy::_create_requested_worker(Game & game, Ware_Index index) | 800 | void Economy::_create_requested_worker(Game & game, Ware_Index index) |
726 | 802 | { | 801 | { |
727 | @@ -820,7 +819,7 @@ | |||
728 | 820 | return; | 819 | return; |
729 | 821 | 820 | ||
730 | 822 | // We have worker demand that is not fulfilled by supplies | 821 | // We have worker demand that is not fulfilled by supplies |
732 | 823 | // Find warehouses where we can create the required workers, | 822 | // Find storages where we can create the required workers, |
733 | 824 | // and collect stats about existing build prerequisites | 823 | // and collect stats about existing build prerequisites |
734 | 825 | const Tribe_Descr & tribe = owner().tribe(); | 824 | const Tribe_Descr & tribe = owner().tribe(); |
735 | 826 | const Worker_Descr & w_desc = *tribe.get_worker_descr(index); | 825 | const Worker_Descr & w_desc = *tribe.get_worker_descr(index); |
736 | @@ -830,20 +829,20 @@ | |||
737 | 830 | 829 | ||
738 | 831 | total_available.insert(total_available.begin(), cost.size(), 0); | 830 | total_available.insert(total_available.begin(), cost.size(), 0); |
739 | 832 | 831 | ||
742 | 833 | for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) { | 832 | for (uint32_t storage_idx = 0; storage_idx < m_storages.size(); ++storage_idx) { |
743 | 834 | Warehouse * wh = m_warehouses[n_wh]; | 833 | Storage * storage = m_storages[storage_idx]; |
744 | 835 | 834 | ||
746 | 836 | uint32_t planned = wh->get_planned_workers(game, index); | 835 | uint32_t planned = storage->get_planned_workers(game, index); |
747 | 837 | total_planned += planned; | 836 | total_planned += planned; |
748 | 838 | 837 | ||
751 | 839 | while (wh->can_create_worker(game, index)) { | 838 | while (storage->can_create_worker(game, index)) { |
752 | 840 | wh->create_worker(game, index); | 839 | storage->create_worker(game, index); |
753 | 841 | if (!--demand) | 840 | if (!--demand) |
754 | 842 | return; | 841 | return; |
755 | 843 | } | 842 | } |
756 | 844 | 843 | ||
757 | 845 | std::vector<uint32_t> wh_available = | 844 | std::vector<uint32_t> wh_available = |
759 | 846 | wh->calc_available_for_worker(game, index); | 845 | storage->calc_available_for_worker(game, index); |
760 | 847 | assert(wh_available.size() == total_available.size()); | 846 | assert(wh_available.size() == total_available.size()); |
761 | 848 | 847 | ||
762 | 849 | for (uint32_t idx = 0; idx < total_available.size(); ++idx) | 848 | for (uint32_t idx = 0; idx < total_available.size(); ++idx) |
763 | @@ -870,25 +869,25 @@ | |||
764 | 870 | // there are supplies for (otherwise, cyclic transportation might happen) | 869 | // there are supplies for (otherwise, cyclic transportation might happen) |
765 | 871 | // Note that supplies might suddenly disappear outside our control because | 870 | // Note that supplies might suddenly disappear outside our control because |
766 | 872 | // of loss of land or silly player actions. | 871 | // of loss of land or silly player actions. |
769 | 873 | for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) { | 872 | for (uint32_t storage_idx = 0; storage_idx < m_storages.size(); ++storage_idx) { |
770 | 874 | Warehouse * wh = m_warehouses[n_wh]; | 873 | Storage * storage = m_storages[storage_idx]; |
771 | 875 | 874 | ||
773 | 876 | uint32_t planned = wh->get_planned_workers(game, index); | 875 | uint32_t planned = storage->get_planned_workers(game, index); |
774 | 877 | uint32_t reduce = std::min(planned, total_planned - can_create); | 876 | uint32_t reduce = std::min(planned, total_planned - can_create); |
776 | 878 | wh->plan_workers(game, index, planned - reduce); | 877 | storage->plan_workers(game, index, planned - reduce); |
777 | 879 | total_planned -= reduce; | 878 | total_planned -= reduce; |
778 | 880 | } | 879 | } |
779 | 881 | } else if (total_planned < demand) { | 880 | } else if (total_planned < demand) { |
780 | 882 | uint32_t plan_goal = std::min(can_create, demand); | 881 | uint32_t plan_goal = std::min(can_create, demand); |
781 | 883 | 882 | ||
784 | 884 | for (uint32_t n_wh = 0; n_wh < warehouses().size(); ++n_wh) { | 883 | for (uint32_t storage_idx = 0; storage_idx < m_storages.size(); ++storage_idx) { |
785 | 885 | Warehouse * wh = m_warehouses[n_wh]; | 884 | Storage * storage = m_storages[storage_idx]; |
786 | 886 | uint32_t supply = | 885 | uint32_t supply = |
788 | 887 | wh->calc_available_for_worker(game, index)[scarcest_idx]; | 886 | storage->calc_available_for_worker(game, index)[scarcest_idx]; |
789 | 888 | 887 | ||
791 | 889 | total_planned -= wh->get_planned_workers(game, index); | 888 | total_planned -= storage->get_planned_workers(game, index); |
792 | 890 | uint32_t plan = std::min(supply, plan_goal - total_planned); | 889 | uint32_t plan = std::min(supply, plan_goal - total_planned); |
794 | 891 | wh->plan_workers(game, index, plan); | 890 | storage->plan_workers(game, index, plan); |
795 | 892 | total_planned += plan; | 891 | total_planned += plan; |
796 | 893 | } | 892 | } |
797 | 894 | } | 893 | } |
798 | @@ -896,11 +895,11 @@ | |||
799 | 896 | 895 | ||
800 | 897 | /** | 896 | /** |
801 | 898 | * Walk all Requests and find requests of workers than aren't supplied. Then | 897 | * Walk all Requests and find requests of workers than aren't supplied. Then |
803 | 899 | * try to create the worker at warehouses. | 898 | * try to create the worker at storages. |
804 | 900 | */ | 899 | */ |
805 | 901 | void Economy::_create_requested_workers(Game & game) | 900 | void Economy::_create_requested_workers(Game & game) |
806 | 902 | { | 901 | { |
808 | 903 | if (!warehouses().size()) | 902 | if (!storages().size()) |
809 | 904 | return; | 903 | return; |
810 | 905 | 904 | ||
811 | 906 | const Tribe_Descr & tribe = owner().tribe(); | 905 | const Tribe_Descr & tribe = owner().tribe(); |
812 | @@ -920,23 +919,23 @@ | |||
813 | 920 | /** | 919 | /** |
814 | 921 | * Helper function for \ref _handle_active_supplies | 920 | * Helper function for \ref _handle_active_supplies |
815 | 922 | */ | 921 | */ |
819 | 923 | static bool accept_warehouse_if_policy | 922 | static bool accept_storage_if_policy |
820 | 924 | (Warehouse & wh, WareWorker type, | 923 | (StorageOwner* storage, WareWorker type, |
821 | 925 | Ware_Index ware, Warehouse::StockPolicy policy) | 924 | Ware_Index ware, Storage::StockPolicy policy) |
822 | 926 | { | 925 | { |
824 | 927 | return wh.get_stock_policy(type, ware) == policy; | 926 | return storage->get_storage()->get_stock_policy(type, ware) == policy; |
825 | 928 | } | 927 | } |
826 | 929 | 928 | ||
827 | 930 | /** | 929 | /** |
828 | 931 | * Send all active supplies (wares that are outside on the road network without | 930 | * Send all active supplies (wares that are outside on the road network without |
830 | 932 | * being sent to a specific request) to a warehouse. | 931 | * being sent to a specific request) to a storage. |
831 | 933 | */ | 932 | */ |
832 | 934 | void Economy::_handle_active_supplies(Game & game) | 933 | void Economy::_handle_active_supplies(Game & game) |
833 | 935 | { | 934 | { |
835 | 936 | if (!warehouses().size()) | 935 | if (!storages().size()) |
836 | 937 | return; | 936 | return; |
837 | 938 | 937 | ||
839 | 939 | typedef std::vector<std::pair<Supply *, Warehouse *> > Assignments; | 938 | typedef std::vector<std::pair<Supply *, StorageOwner *> > Assignments; |
840 | 940 | Assignments assignments; | 939 | Assignments assignments; |
841 | 941 | 940 | ||
842 | 942 | for (uint32_t idx = 0; idx < m_supplies.get_nrsupplies(); ++idx) { | 941 | for (uint32_t idx = 0; idx < m_supplies.get_nrsupplies(); ++idx) { |
843 | @@ -950,38 +949,38 @@ | |||
844 | 950 | 949 | ||
845 | 951 | bool haveprefer = false; | 950 | bool haveprefer = false; |
846 | 952 | bool havenormal = false; | 951 | bool havenormal = false; |
851 | 953 | for (uint32_t nwh = 0; nwh < m_warehouses.size(); ++nwh) { | 952 | for (uint32_t storage_idx = 0; storage_idx < m_storages.size(); ++storage_idx) { |
852 | 954 | Warehouse * wh = m_warehouses[nwh]; | 953 | Storage * storage = m_storages[storage_idx]; |
853 | 955 | Warehouse::StockPolicy policy = wh->get_stock_policy(type, ware); | 954 | Storage::StockPolicy policy = storage->get_stock_policy(type, ware); |
854 | 956 | if (policy == Warehouse::SP_Prefer) { | 955 | if (policy == Storage::StockPolicy::Prefer) { |
855 | 957 | haveprefer = true; | 956 | haveprefer = true; |
856 | 958 | break; | 957 | break; |
857 | 959 | } | 958 | } |
859 | 960 | if (policy == Warehouse::SP_Normal) | 959 | if (policy == Storage::StockPolicy::Normal) |
860 | 961 | havenormal = true; | 960 | havenormal = true; |
861 | 962 | } | 961 | } |
862 | 963 | if (!havenormal && !haveprefer && type == wwWARE) | 962 | if (!havenormal && !haveprefer && type == wwWARE) |
863 | 964 | continue; | 963 | continue; |
864 | 965 | 964 | ||
866 | 966 | Warehouse * wh = find_closest_warehouse | 965 | StorageOwner * storage_owner = find_closest_storage |
867 | 967 | (supply.get_position(game)->base_flag(), type, 0, 0, | 966 | (supply.get_position(game)->base_flag(), type, 0, 0, |
868 | 968 | (!haveprefer && !havenormal) | 967 | (!haveprefer && !havenormal) |
869 | 969 | ? | 968 | ? |
871 | 970 | WarehouseAcceptFn() | 969 | StorageAcceptFn() |
872 | 971 | : | 970 | : |
873 | 972 | boost::bind | 971 | boost::bind |
875 | 973 | (&accept_warehouse_if_policy, | 972 | (&accept_storage_if_policy, |
876 | 974 | _1, type, ware, | 973 | _1, type, ware, |
878 | 975 | haveprefer ? Warehouse::SP_Prefer : Warehouse::SP_Normal)); | 974 | haveprefer ? Storage::StockPolicy::Prefer : Storage::StockPolicy::Normal)); |
879 | 976 | 975 | ||
881 | 977 | if (!wh) { | 976 | if (!storage_owner) { |
882 | 978 | log | 977 | log |
883 | 979 | ("Warning: Economy::_handle_active_supplies " | 978 | ("Warning: Economy::_handle_active_supplies " |
885 | 980 | "didn't find warehouse\n"); | 979 | "didn't find storage\n"); |
886 | 981 | return; | 980 | return; |
887 | 982 | } | 981 | } |
888 | 983 | 982 | ||
890 | 984 | assignments.push_back(std::make_pair(&supply, wh)); | 983 | assignments.push_back(std::make_pair(&supply, storage_owner)); |
891 | 985 | } | 984 | } |
892 | 986 | 985 | ||
893 | 987 | // Actually start with the transfers in a separate second phase, | 986 | // Actually start with the transfers in a separate second phase, |
894 | @@ -991,10 +990,10 @@ | |||
895 | 991 | ss.Unsigned32(0x02decafa); // appears as facade02 in sync stream | 990 | ss.Unsigned32(0x02decafa); // appears as facade02 in sync stream |
896 | 992 | ss.Unsigned32(assignments.size()); | 991 | ss.Unsigned32(assignments.size()); |
897 | 993 | 992 | ||
898 | 993 | // FIXME CGH check thats working | ||
899 | 994 | container_iterate_const(Assignments, assignments, it) { | 994 | container_iterate_const(Assignments, assignments, it) { |
900 | 995 | ss.Unsigned32(it.current->first->get_position(game)->serial()); | 995 | ss.Unsigned32(it.current->first->get_position(game)->serial()); |
903 | 996 | ss.Unsigned32(it.current->second->serial()); | 996 | ss.Unsigned32(it.current->second->get_building()->serial()); |
902 | 997 | |||
904 | 998 | it.current->first->send_to_storage(game, it.current->second); | 997 | it.current->first->send_to_storage(game, it.current->second); |
905 | 999 | } | 998 | } |
906 | 1000 | } | 999 | } |
907 | 1001 | 1000 | ||
908 | === modified file 'src/economy/economy.h' | |||
909 | --- src/economy/economy.h 2013-07-26 20:19:36 +0000 | |||
910 | +++ src/economy/economy.h 2013-08-10 10:53:03 +0000 | |||
911 | @@ -34,12 +34,15 @@ | |||
912 | 34 | 34 | ||
913 | 35 | 35 | ||
914 | 36 | namespace Widelands { | 36 | namespace Widelands { |
915 | 37 | |||
916 | 38 | class StorageOwner; | ||
917 | 39 | |||
918 | 40 | class Storage; | ||
919 | 37 | struct Player; | 41 | struct Player; |
920 | 38 | struct Game; | 42 | struct Game; |
921 | 39 | struct Flag; | 43 | struct Flag; |
922 | 40 | struct Route; | 44 | struct Route; |
923 | 41 | struct RSPairStruct; | 45 | struct RSPairStruct; |
924 | 42 | class Warehouse; | ||
925 | 43 | struct Request; | 46 | struct Request; |
926 | 44 | struct Supply; | 47 | struct Supply; |
927 | 45 | struct Router; | 48 | struct Router; |
928 | @@ -102,11 +105,11 @@ | |||
929 | 102 | WareWorker type, | 105 | WareWorker type, |
930 | 103 | int32_t cost_cutoff = -1); | 106 | int32_t cost_cutoff = -1); |
931 | 104 | 107 | ||
934 | 105 | typedef boost::function<bool (Warehouse &)> WarehouseAcceptFn; | 108 | typedef boost::function<bool (StorageOwner *)> StorageAcceptFn; |
935 | 106 | Warehouse * find_closest_warehouse | 109 | StorageOwner * find_closest_storage |
936 | 107 | (Flag & start, WareWorker type = wwWORKER, Route * route = 0, | 110 | (Flag & start, WareWorker type = wwWORKER, Route * route = 0, |
937 | 108 | uint32_t cost_cutoff = 0, | 111 | uint32_t cost_cutoff = 0, |
939 | 109 | const WarehouseAcceptFn & acceptfn = WarehouseAcceptFn()); | 112 | const StorageAcceptFn & acceptfn = StorageAcceptFn()); |
940 | 110 | 113 | ||
941 | 111 | std::vector<Flag *>::size_type get_nrflags() const {return m_flags.size();} | 114 | std::vector<Flag *>::size_type get_nrflags() const {return m_flags.size();} |
942 | 112 | void add_flag(Flag &); | 115 | void add_flag(Flag &); |
943 | @@ -122,9 +125,9 @@ | |||
944 | 122 | void add_workers(Ware_Index, uint32_t count = 1); | 125 | void add_workers(Ware_Index, uint32_t count = 1); |
945 | 123 | void remove_workers(Ware_Index, uint32_t count = 1); | 126 | void remove_workers(Ware_Index, uint32_t count = 1); |
946 | 124 | 127 | ||
950 | 125 | void add_warehouse(Warehouse &); | 128 | void add_storage(Storage &); |
951 | 126 | void remove_warehouse(Warehouse &); | 129 | void remove_storage(Storage &); |
952 | 127 | const std::vector<Warehouse *>& warehouses() const {return m_warehouses;} | 130 | const std::vector<Storage *>& storages() const {return m_storages;} |
953 | 128 | 131 | ||
954 | 129 | void add_request(Request &); | 132 | void add_request(Request &); |
955 | 130 | void remove_request(Request &); | 133 | void remove_request(Request &); |
956 | @@ -208,7 +211,7 @@ | |||
957 | 208 | Flags m_flags; | 211 | Flags m_flags; |
958 | 209 | WareList m_wares; ///< virtual storage with all wares in this Economy | 212 | WareList m_wares; ///< virtual storage with all wares in this Economy |
959 | 210 | WareList m_workers; ///< virtual storage with all workers in this Economy | 213 | WareList m_workers; ///< virtual storage with all workers in this Economy |
961 | 211 | std::vector<Warehouse *> m_warehouses; | 214 | std::vector<Storage *> m_storages; |
962 | 212 | 215 | ||
963 | 213 | RequestList m_requests; ///< requests | 216 | RequestList m_requests; ///< requests |
964 | 214 | SupplyList m_supplies; | 217 | SupplyList m_supplies; |
965 | 215 | 218 | ||
966 | === modified file 'src/economy/idleworkersupply.cc' | |||
967 | --- src/economy/idleworkersupply.cc 2013-07-26 20:19:36 +0000 | |||
968 | +++ src/economy/idleworkersupply.cc 2013-08-10 10:53:03 +0000 | |||
969 | @@ -25,8 +25,8 @@ | |||
970 | 25 | #include "logic/player.h" | 25 | #include "logic/player.h" |
971 | 26 | #include "logic/requirements.h" | 26 | #include "logic/requirements.h" |
972 | 27 | #include "logic/soldier.h" | 27 | #include "logic/soldier.h" |
973 | 28 | #include "logic/storage.h" | ||
974 | 28 | #include "logic/tribe.h" | 29 | #include "logic/tribe.h" |
975 | 29 | #include "logic/warehouse.h" | ||
976 | 30 | #include "logic/worker.h" | 30 | #include "logic/worker.h" |
977 | 31 | #include "wexception.h" | 31 | #include "wexception.h" |
978 | 32 | 32 | ||
979 | @@ -126,12 +126,12 @@ | |||
980 | 126 | return m_worker; | 126 | return m_worker; |
981 | 127 | } | 127 | } |
982 | 128 | 128 | ||
984 | 129 | void IdleWorkerSupply::send_to_storage(Game & game, Warehouse * wh) | 129 | void IdleWorkerSupply::send_to_storage(Game & game, StorageOwner * storage_owner) |
985 | 130 | { | 130 | { |
986 | 131 | assert(!has_storage()); | 131 | assert(!has_storage()); |
987 | 132 | 132 | ||
988 | 133 | Transfer * t = new Transfer(game, m_worker); | 133 | Transfer * t = new Transfer(game, m_worker); |
990 | 134 | t->set_destination(*wh); | 134 | t->set_destination(*storage_owner->get_building()); |
991 | 135 | m_worker.start_task_transfer(game, t); | 135 | m_worker.start_task_transfer(game, t); |
992 | 136 | } | 136 | } |
993 | 137 | 137 | ||
994 | 138 | 138 | ||
995 | === modified file 'src/economy/idleworkersupply.h' | |||
996 | --- src/economy/idleworkersupply.h 2013-07-26 20:19:36 +0000 | |||
997 | +++ src/economy/idleworkersupply.h 2013-08-10 10:53:03 +0000 | |||
998 | @@ -23,6 +23,8 @@ | |||
999 | 23 | #include "economy/supply.h" | 23 | #include "economy/supply.h" |
1000 | 24 | 24 | ||
1001 | 25 | namespace Widelands { | 25 | namespace Widelands { |
1002 | 26 | |||
1003 | 27 | class StorageOwner; | ||
1004 | 26 | class Worker; | 28 | class Worker; |
1005 | 27 | class Economy; | 29 | class Economy; |
1006 | 28 | 30 | ||
1007 | @@ -36,7 +38,7 @@ | |||
1008 | 36 | virtual bool is_active() const throw (); | 38 | virtual bool is_active() const throw (); |
1009 | 37 | virtual bool has_storage() const throw (); | 39 | virtual bool has_storage() const throw (); |
1010 | 38 | virtual void get_ware_type(WareWorker & type, Ware_Index & ware) const; | 40 | virtual void get_ware_type(WareWorker & type, Ware_Index & ware) const; |
1012 | 39 | virtual void send_to_storage(Game &, Warehouse * wh); | 41 | virtual void send_to_storage(Game &, StorageOwner * storage_owner); |
1013 | 40 | 42 | ||
1014 | 41 | virtual uint32_t nr_supplies(const Game &, const Request &) const; | 43 | virtual uint32_t nr_supplies(const Game &, const Request &) const; |
1015 | 42 | virtual WareInstance & launch_item(Game &, const Request &); | 44 | virtual WareInstance & launch_item(Game &, const Request &); |
1016 | 43 | 45 | ||
1017 | === modified file 'src/economy/portdock.cc' | |||
1018 | --- src/economy/portdock.cc 2013-07-26 20:19:36 +0000 | |||
1019 | +++ src/economy/portdock.cc 2013-08-10 10:53:03 +0000 | |||
1020 | @@ -488,7 +488,7 @@ | |||
1021 | 488 | // Put all wares from the WaresQueues back into the warehouse | 488 | // Put all wares from the WaresQueues back into the warehouse |
1022 | 489 | const std::vector<WaresQueue *> & l_expedition_wares = m_warehouse->get_wares_queue_vector(); | 489 | const std::vector<WaresQueue *> & l_expedition_wares = m_warehouse->get_wares_queue_vector(); |
1023 | 490 | for (uint8_t i = 0; i < l_expedition_wares.size(); ++i) { | 490 | for (uint8_t i = 0; i < l_expedition_wares.size(); ++i) { |
1025 | 491 | m_warehouse->insert_wares(l_expedition_wares.at(i)->get_ware(), l_expedition_wares.at(i)->get_filled()); | 491 | m_warehouse->get_storage()->insert_wares(l_expedition_wares.at(i)->get_ware(), l_expedition_wares.at(i)->get_filled()); |
1026 | 492 | l_expedition_wares.at(i)->set_filled(0); | 492 | l_expedition_wares.at(i)->set_filled(0); |
1027 | 493 | l_expedition_wares.at(i)->set_max_fill(0); | 493 | l_expedition_wares.at(i)->set_max_fill(0); |
1028 | 494 | } | 494 | } |
1029 | @@ -501,7 +501,7 @@ | |||
1030 | 501 | } else { | 501 | } else { |
1031 | 502 | Worker * temp = ew.at(i)->worker; | 502 | Worker * temp = ew.at(i)->worker; |
1032 | 503 | ew.at(i)->worker = 0; | 503 | ew.at(i)->worker = 0; |
1034 | 504 | m_warehouse->incorporate_worker(game, *temp); | 504 | m_warehouse->get_storage()->incorporate_worker(game, *temp); |
1035 | 505 | } | 505 | } |
1036 | 506 | } | 506 | } |
1037 | 507 | // Reset expedition workers list | 507 | // Reset expedition workers list |
1038 | 508 | 508 | ||
1039 | === modified file 'src/economy/request.cc' | |||
1040 | --- src/economy/request.cc 2013-07-26 20:19:36 +0000 | |||
1041 | +++ src/economy/request.cc 2013-08-10 10:53:03 +0000 | |||
1042 | @@ -28,8 +28,8 @@ | |||
1043 | 28 | #include "logic/player.h" | 28 | #include "logic/player.h" |
1044 | 29 | #include "logic/productionsite.h" | 29 | #include "logic/productionsite.h" |
1045 | 30 | #include "logic/soldier.h" | 30 | #include "logic/soldier.h" |
1046 | 31 | #include "logic/storage.h" | ||
1047 | 31 | #include "logic/tribe.h" | 32 | #include "logic/tribe.h" |
1048 | 32 | #include "logic/warehouse.h" | ||
1049 | 33 | #include "logic/worker.h" | 33 | #include "logic/worker.h" |
1050 | 34 | #include "map_io/widelands_map_map_object_loader.h" | 34 | #include "map_io/widelands_map_map_object_loader.h" |
1051 | 35 | #include "map_io/widelands_map_map_object_saver.h" | 35 | #include "map_io/widelands_map_map_object_saver.h" |
1052 | @@ -50,22 +50,27 @@ | |||
1053 | 50 | (PlayerImmovable & _target, | 50 | (PlayerImmovable & _target, |
1054 | 51 | Ware_Index const index, | 51 | Ware_Index const index, |
1055 | 52 | callback_t const cbfn, | 52 | callback_t const cbfn, |
1057 | 53 | WareWorker const w) | 53 | WareWorker const w, |
1058 | 54 | callback_tranfert_t const transfer_cb) | ||
1059 | 54 | : | 55 | : |
1060 | 55 | m_type (w), | 56 | m_type (w), |
1061 | 56 | m_target (_target), | 57 | m_target (_target), |
1062 | 57 | m_target_building (dynamic_cast<Building *>(&_target)), | 58 | m_target_building (dynamic_cast<Building *>(&_target)), |
1063 | 58 | m_target_productionsite (dynamic_cast<ProductionSite *>(&_target)), | 59 | m_target_productionsite (dynamic_cast<ProductionSite *>(&_target)), |
1065 | 59 | m_target_warehouse (dynamic_cast<Warehouse *>(&_target)), | 60 | m_target_storage (nullptr), |
1066 | 60 | m_target_constructionsite (dynamic_cast<ConstructionSite *>(&_target)), | 61 | m_target_constructionsite (dynamic_cast<ConstructionSite *>(&_target)), |
1067 | 61 | m_economy (_target.get_economy()), | 62 | m_economy (_target.get_economy()), |
1068 | 62 | m_index (index), | 63 | m_index (index), |
1069 | 63 | m_count (1), | 64 | m_count (1), |
1070 | 64 | m_callbackfn (cbfn), | 65 | m_callbackfn (cbfn), |
1071 | 66 | m_transfer_cb (transfer_cb), | ||
1072 | 65 | m_required_time (_target.owner().egbase().get_gametime()), | 67 | m_required_time (_target.owner().egbase().get_gametime()), |
1073 | 66 | m_required_interval(0), | 68 | m_required_interval(0), |
1074 | 67 | m_last_request_time(m_required_time) | 69 | m_last_request_time(m_required_time) |
1075 | 68 | { | 70 | { |
1076 | 71 | if (upcast(StorageOwner, storage_owner, &_target)) { | ||
1077 | 72 | m_target_storage = storage_owner->get_storage(); | ||
1078 | 73 | } | ||
1079 | 69 | assert(m_type == wwWARE or m_type == wwWORKER); | 74 | assert(m_type == wwWARE or m_type == wwWORKER); |
1080 | 70 | if (w == wwWARE and _target.owner().tribe().get_nrwares() <= index) | 75 | if (w == wwWARE and _target.owner().tribe().get_nrwares() <= index) |
1081 | 71 | throw wexception | 76 | throw wexception |
1082 | @@ -354,8 +359,8 @@ | |||
1083 | 354 | modifier = m_target_building->get_priority(get_type(), get_index()); | 359 | modifier = m_target_building->get_priority(get_type(), get_index()); |
1084 | 355 | if (m_target_constructionsite) | 360 | if (m_target_constructionsite) |
1085 | 356 | is_construction_site = true; | 361 | is_construction_site = true; |
1088 | 357 | else if (m_target_warehouse) | 362 | else if (m_target_storage) |
1089 | 358 | // if warehouse calculated a priority use it | 363 | // if storage calculated a priority use it |
1090 | 359 | // else lower priority based on cost | 364 | // else lower priority based on cost |
1091 | 360 | return | 365 | return |
1092 | 361 | modifier != 100 ? modifier : | 366 | modifier != 100 ? modifier : |
1093 | @@ -404,7 +409,7 @@ | |||
1094 | 404 | pri = m_target_building->get_priority(get_type(), get_index()); | 409 | pri = m_target_building->get_priority(get_type(), get_index()); |
1095 | 405 | if (m_target_constructionsite) | 410 | if (m_target_constructionsite) |
1096 | 406 | return pri + 3; | 411 | return pri + 3; |
1098 | 407 | else if (m_target_warehouse) | 412 | else if (m_target_storage) |
1099 | 408 | return pri - 2; | 413 | return pri - 2; |
1100 | 409 | } | 414 | } |
1101 | 410 | return pri; | 415 | return pri; |
1102 | @@ -486,10 +491,13 @@ | |||
1103 | 486 | Worker & s = supp.launch_worker(game, *this); | 491 | Worker & s = supp.launch_worker(game, *this); |
1104 | 487 | ss.Unsigned32(s.serial()); | 492 | ss.Unsigned32(s.serial()); |
1105 | 488 | t = new Transfer(game, *this, s); | 493 | t = new Transfer(game, *this, s); |
1106 | 494 | if (m_transfer_cb) { | ||
1107 | 495 | (*m_transfer_cb)(game, *this, m_index, &s, m_target); | ||
1108 | 496 | } | ||
1109 | 489 | } else { | 497 | } else { |
1110 | 490 | // Begin the transfer of an item. The item itself is passive. | 498 | // Begin the transfer of an item. The item itself is passive. |
1111 | 491 | // launch_item() ensures the WareInstance is transported out of the | 499 | // launch_item() ensures the WareInstance is transported out of the |
1113 | 492 | // warehouse. Once it's on the flag, the flag code will decide what to | 500 | // storage. Once it's on the flag, the flag code will decide what to |
1114 | 493 | // do with it. | 501 | // do with it. |
1115 | 494 | WareInstance & item = supp.launch_item(game, *this); | 502 | WareInstance & item = supp.launch_item(game, *this); |
1116 | 495 | ss.Unsigned32(item.serial()); | 503 | ss.Unsigned32(item.serial()); |
1117 | @@ -533,7 +541,7 @@ | |||
1118 | 533 | * | 541 | * |
1119 | 534 | * Re-open the request. | 542 | * Re-open the request. |
1120 | 535 | */ | 543 | */ |
1122 | 536 | void Request::transfer_fail(Game &, Transfer & t) { | 544 | void Request::transfer_fail(Game & game, Transfer & t) { |
1123 | 537 | bool const wasopen = is_open(); | 545 | bool const wasopen = is_open(); |
1124 | 538 | 546 | ||
1125 | 539 | t.m_worker = 0; | 547 | t.m_worker = 0; |
1126 | @@ -541,8 +549,12 @@ | |||
1127 | 541 | 549 | ||
1128 | 542 | remove_transfer(find_transfer(t)); | 550 | remove_transfer(find_transfer(t)); |
1129 | 543 | 551 | ||
1131 | 544 | if (!wasopen) | 552 | if (!wasopen) { |
1132 | 545 | m_economy->add_request(*this); | 553 | m_economy->add_request(*this); |
1133 | 554 | } | ||
1134 | 555 | if (m_transfer_cb) { | ||
1135 | 556 | m_transfer_cb(game, *this, m_index, nullptr, m_target); | ||
1136 | 557 | } | ||
1137 | 546 | } | 558 | } |
1138 | 547 | 559 | ||
1139 | 548 | /// Cancel the transfer with the given index. | 560 | /// Cancel the transfer with the given index. |
1140 | 549 | 561 | ||
1141 | === modified file 'src/economy/request.h' | |||
1142 | --- src/economy/request.h 2013-07-25 21:05:20 +0000 | |||
1143 | +++ src/economy/request.h 2013-08-10 10:53:03 +0000 | |||
1144 | @@ -20,6 +20,8 @@ | |||
1145 | 20 | #ifndef REQUEST_H | 20 | #ifndef REQUEST_H |
1146 | 21 | #define REQUEST_H | 21 | #define REQUEST_H |
1147 | 22 | 22 | ||
1148 | 23 | #include <functional> | ||
1149 | 24 | |||
1150 | 23 | #include "logic/requirements.h" | 25 | #include "logic/requirements.h" |
1151 | 24 | #include "logic/wareworker.h" | 26 | #include "logic/wareworker.h" |
1152 | 25 | #include "logic/widelands.h" | 27 | #include "logic/widelands.h" |
1153 | @@ -39,11 +41,11 @@ | |||
1154 | 39 | class RequestList; | 41 | class RequestList; |
1155 | 40 | struct Requirements; | 42 | struct Requirements; |
1156 | 41 | struct Supply; | 43 | struct Supply; |
1157 | 44 | class Storage; | ||
1158 | 42 | struct Transfer; | 45 | struct Transfer; |
1159 | 43 | class Worker; | 46 | class Worker; |
1160 | 44 | class Building; | 47 | class Building; |
1161 | 45 | class ProductionSite; | 48 | class ProductionSite; |
1162 | 46 | class Warehouse; | ||
1163 | 47 | class ConstructionSite; | 49 | class ConstructionSite; |
1164 | 48 | 50 | ||
1165 | 49 | /** | 51 | /** |
1166 | @@ -63,8 +65,12 @@ | |||
1167 | 63 | 65 | ||
1168 | 64 | typedef void (*callback_t) | 66 | typedef void (*callback_t) |
1169 | 65 | (Game &, Request &, Ware_Index, Worker *, PlayerImmovable &); | 67 | (Game &, Request &, Ware_Index, Worker *, PlayerImmovable &); |
1170 | 68 | typedef void (*callback_tranfert_t) | ||
1171 | 69 | (Game &, Request &, Ware_Index, Worker *, PlayerImmovable &); | ||
1172 | 66 | 70 | ||
1174 | 67 | Request(PlayerImmovable & target, Ware_Index, callback_t, WareWorker); | 71 | Request |
1175 | 72 | (PlayerImmovable & target, Ware_Index, callback_t, WareWorker, | ||
1176 | 73 | callback_tranfert_t transfer_cb = nullptr); | ||
1177 | 68 | ~Request(); | 74 | ~Request(); |
1178 | 69 | 75 | ||
1179 | 70 | PlayerImmovable & target() const throw () {return m_target;} | 76 | PlayerImmovable & target() const throw () {return m_target;} |
1180 | @@ -120,7 +126,7 @@ | |||
1181 | 120 | // are filled with nulls. | 126 | // are filled with nulls. |
1182 | 121 | Building * m_target_building; | 127 | Building * m_target_building; |
1183 | 122 | ProductionSite * m_target_productionsite; | 128 | ProductionSite * m_target_productionsite; |
1185 | 123 | Warehouse * m_target_warehouse; | 129 | Storage * m_target_storage; |
1186 | 124 | ConstructionSite * m_target_constructionsite; | 130 | ConstructionSite * m_target_constructionsite; |
1187 | 125 | 131 | ||
1188 | 126 | Economy * m_economy; | 132 | Economy * m_economy; |
1189 | @@ -128,6 +134,7 @@ | |||
1190 | 128 | uint32_t m_count; // how many do we need in total | 134 | uint32_t m_count; // how many do we need in total |
1191 | 129 | 135 | ||
1192 | 130 | callback_t m_callbackfn; // called on request success | 136 | callback_t m_callbackfn; // called on request success |
1193 | 137 | callback_tranfert_t m_transfer_cb; // called on worker transfer start/cancel | ||
1194 | 131 | 138 | ||
1195 | 132 | // when do we need the first ware (can be in the past) | 139 | // when do we need the first ware (can be in the past) |
1196 | 133 | int32_t m_required_time; | 140 | int32_t m_required_time; |
1197 | 134 | 141 | ||
1198 | === modified file 'src/economy/supply.h' | |||
1199 | --- src/economy/supply.h 2013-07-26 19:16:51 +0000 | |||
1200 | +++ src/economy/supply.h 2013-08-10 10:53:03 +0000 | |||
1201 | @@ -25,10 +25,12 @@ | |||
1202 | 25 | 25 | ||
1203 | 26 | namespace Widelands { | 26 | namespace Widelands { |
1204 | 27 | 27 | ||
1205 | 28 | class StorageOwner; | ||
1206 | 29 | |||
1207 | 28 | struct PlayerImmovable; | 30 | struct PlayerImmovable; |
1208 | 29 | struct Game; | 31 | struct Game; |
1209 | 30 | struct Request; | 32 | struct Request; |
1211 | 31 | class Warehouse; | 33 | class StorageOwner; |
1212 | 32 | struct Ware_Index; | 34 | struct Ware_Index; |
1213 | 33 | class WareInstance; | 35 | class WareInstance; |
1214 | 34 | class Worker; | 36 | class Worker; |
1215 | @@ -77,7 +79,7 @@ | |||
1216 | 77 | * Sets up all the required transfers; assumes that \ref has_storage | 79 | * Sets up all the required transfers; assumes that \ref has_storage |
1217 | 78 | * returns \c false. | 80 | * returns \c false. |
1218 | 79 | */ | 81 | */ |
1220 | 80 | virtual void send_to_storage(Game &, Warehouse * wh) = 0; | 82 | virtual void send_to_storage(Game &, StorageOwner * storage_owner) = 0; |
1221 | 81 | 83 | ||
1222 | 82 | /** | 84 | /** |
1223 | 83 | * \return the number of items or workers that can be launched right | 85 | * \return the number of items or workers that can be launched right |
1224 | 84 | 86 | ||
1225 | === modified file 'src/economy/transfer.cc' | |||
1226 | --- src/economy/transfer.cc 2013-07-26 20:19:36 +0000 | |||
1227 | +++ src/economy/transfer.cc 2013-08-10 10:53:03 +0000 | |||
1228 | @@ -191,6 +191,7 @@ | |||
1229 | 191 | Flag & curflag(m_route.get_flag(m_game, 0)); | 191 | Flag & curflag(m_route.get_flag(m_game, 0)); |
1230 | 192 | Flag & nextflag(m_route.get_flag(m_game, 1)); | 192 | Flag & nextflag(m_route.get_flag(m_game, 1)); |
1231 | 193 | if (!curflag.get_road(nextflag)) { | 193 | if (!curflag.get_road(nextflag)) { |
1232 | 194 | //FIXME CGH | ||
1233 | 194 | upcast(Warehouse, wh, curflag.get_building()); | 195 | upcast(Warehouse, wh, curflag.get_building()); |
1234 | 195 | assert(wh); | 196 | assert(wh); |
1235 | 196 | 197 | ||
1236 | 197 | 198 | ||
1237 | === modified file 'src/economy/ware_instance.cc' | |||
1238 | --- src/economy/ware_instance.cc 2013-07-26 20:19:36 +0000 | |||
1239 | +++ src/economy/ware_instance.cc 2013-08-10 10:53:03 +0000 | |||
1240 | @@ -27,8 +27,8 @@ | |||
1241 | 27 | #include "economy/transfer.h" | 27 | #include "economy/transfer.h" |
1242 | 28 | #include "logic/game.h" | 28 | #include "logic/game.h" |
1243 | 29 | #include "logic/ship.h" | 29 | #include "logic/ship.h" |
1244 | 30 | #include "logic/storage.h" | ||
1245 | 30 | #include "logic/tribe.h" | 31 | #include "logic/tribe.h" |
1246 | 31 | #include "logic/warehouse.h" | ||
1247 | 32 | #include "logic/worker.h" | 32 | #include "logic/worker.h" |
1248 | 33 | #include "map_io/widelands_map_map_object_loader.h" | 33 | #include "map_io/widelands_map_map_object_loader.h" |
1249 | 34 | #include "map_io/widelands_map_map_object_saver.h" | 34 | #include "map_io/widelands_map_map_object_saver.h" |
1250 | @@ -54,7 +54,7 @@ | |||
1251 | 54 | virtual bool is_active() const throw (); | 54 | virtual bool is_active() const throw (); |
1252 | 55 | virtual bool has_storage() const throw (); | 55 | virtual bool has_storage() const throw (); |
1253 | 56 | virtual void get_ware_type(WareWorker & type, Ware_Index & ware) const; | 56 | virtual void get_ware_type(WareWorker & type, Ware_Index & ware) const; |
1255 | 57 | virtual void send_to_storage(Game &, Warehouse * wh); | 57 | virtual void send_to_storage(Game &, StorageOwner * wh); |
1256 | 58 | 58 | ||
1257 | 59 | virtual uint32_t nr_supplies(const Game &, const Request &) const; | 59 | virtual uint32_t nr_supplies(const Game &, const Request &) const; |
1258 | 60 | virtual WareInstance & launch_item(Game &, const Request &); | 60 | virtual WareInstance & launch_item(Game &, const Request &); |
1259 | @@ -166,12 +166,12 @@ | |||
1260 | 166 | throw wexception("IdleWareSupply::launch_worker makes no sense"); | 166 | throw wexception("IdleWareSupply::launch_worker makes no sense"); |
1261 | 167 | } | 167 | } |
1262 | 168 | 168 | ||
1264 | 169 | void IdleWareSupply::send_to_storage(Game & game, Warehouse * wh) | 169 | void IdleWareSupply::send_to_storage(Game & game, StorageOwner * storage_owner) |
1265 | 170 | { | 170 | { |
1266 | 171 | assert(!has_storage()); | 171 | assert(!has_storage()); |
1267 | 172 | 172 | ||
1268 | 173 | Transfer * t = new Transfer(game, m_ware); | 173 | Transfer * t = new Transfer(game, m_ware); |
1270 | 174 | t->set_destination(*wh); | 174 | t->set_destination(*storage_owner->get_building()); |
1271 | 175 | m_ware.set_transfer(game, *t); | 175 | m_ware.set_transfer(game, *t); |
1272 | 176 | } | 176 | } |
1273 | 177 | 177 | ||
1274 | @@ -290,8 +290,8 @@ | |||
1275 | 290 | 290 | ||
1276 | 291 | /** | 291 | /** |
1277 | 292 | * Performs the state updates necessary for the current location: | 292 | * Performs the state updates necessary for the current location: |
1280 | 293 | * - if it's a building, acknowledge the Request or incorporate into warehouse | 293 | * - if it's a building, acknowledge the Request or incorporate into strage |
1281 | 294 | * - if it's a flag and we have no request, start the return to warehouse timer | 294 | * - if it's a flag and we have no request, start the return to storage timer |
1282 | 295 | * and issue a Supply | 295 | * and issue a Supply |
1283 | 296 | * | 296 | * |
1284 | 297 | * \note \ref update() may result in the deletion of this object. | 297 | * \note \ref update() may result in the deletion of this object. |
1285 | @@ -405,22 +405,22 @@ | |||
1286 | 405 | return; | 405 | return; |
1287 | 406 | } | 406 | } |
1288 | 407 | 407 | ||
1290 | 408 | // There are some situations where we might end up in a warehouse | 408 | // There are some situations where we might end up in a storage |
1291 | 409 | // as part of a requested route, and we need to move out of it | 409 | // as part of a requested route, and we need to move out of it |
1292 | 410 | // again, e.g.: | 410 | // again, e.g.: |
1293 | 411 | // - we were requested just when we were being carried into the | 411 | // - we were requested just when we were being carried into the |
1295 | 412 | // warehouse | 412 | // storage |
1296 | 413 | // - we were carried into a harbour/warehouse to be | 413 | // - we were carried into a harbour/warehouse to be |
1297 | 414 | // shipped across the sea, but a better, land-based route has been | 414 | // shipped across the sea, but a better, land-based route has been |
1298 | 415 | // found | 415 | // found |
1301 | 416 | if (upcast(Warehouse, warehouse, &building)) { | 416 | if (upcast(StorageOwner, storage_owner, &building)) { |
1302 | 417 | warehouse->do_launch_item(game, *this); | 417 | storage_owner->get_storage()->do_launch_ware(game, *this); |
1303 | 418 | return; | 418 | return; |
1304 | 419 | } | 419 | } |
1305 | 420 | 420 | ||
1306 | 421 | throw wexception | 421 | throw wexception |
1307 | 422 | ("MO(%u): ware(%s): do not know how to move from building %u (%s at (%u,%u)) " | 422 | ("MO(%u): ware(%s): do not know how to move from building %u (%s at (%u,%u)) " |
1309 | 423 | "to %u (%s) -> not a warehouse!", | 423 | "to %u (%s) -> not a storage owner!", |
1310 | 424 | serial(), m_descr->name().c_str(), building.serial(), | 424 | serial(), m_descr->name().c_str(), building.serial(), |
1311 | 425 | building.name().c_str(), building.get_position().x, | 425 | building.name().c_str(), building.get_position().x, |
1312 | 426 | building.get_position().y, nextstep->serial(), | 426 | building.get_position().y, nextstep->serial(), |
1313 | 427 | 427 | ||
1314 | === removed file 'src/economy/warehousesupply.h' | |||
1315 | --- src/economy/warehousesupply.h 2013-07-26 20:19:36 +0000 | |||
1316 | +++ src/economy/warehousesupply.h 1970-01-01 00:00:00 +0000 | |||
1317 | @@ -1,76 +0,0 @@ | |||
1318 | 1 | /* | ||
1319 | 2 | * Copyright (C) 2008-2010 by the Widelands Development Team | ||
1320 | 3 | * | ||
1321 | 4 | * This program is free software; you can redistribute it and/or | ||
1322 | 5 | * modify it under the terms of the GNU General Public License | ||
1323 | 6 | * as published by the Free Software Foundation; either version 2 | ||
1324 | 7 | * of the License, or (at your option) any later version. | ||
1325 | 8 | * | ||
1326 | 9 | * This program is distributed in the hope that it will be useful, | ||
1327 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1328 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1329 | 12 | * GNU General Public License for more details. | ||
1330 | 13 | * | ||
1331 | 14 | * You should have received a copy of the GNU General Public License | ||
1332 | 15 | * along with this program; if not, write to the Free Software | ||
1333 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
1334 | 17 | * | ||
1335 | 18 | */ | ||
1336 | 19 | |||
1337 | 20 | #ifndef WAREHOUSESUPPLY_H | ||
1338 | 21 | #define WAREHOUSESUPPLY_H | ||
1339 | 22 | |||
1340 | 23 | #include "logic/warelist.h" | ||
1341 | 24 | #include "logic/wareworker.h" | ||
1342 | 25 | #include "economy/supply.h" | ||
1343 | 26 | |||
1344 | 27 | namespace Widelands { | ||
1345 | 28 | |||
1346 | 29 | /* | ||
1347 | 30 | WarehouseSupply is the implementation of Supply that is used by Warehouses. | ||
1348 | 31 | It also manages the list of wares in the warehouse. | ||
1349 | 32 | */ | ||
1350 | 33 | struct WarehouseSupply : public Supply { | ||
1351 | 34 | WarehouseSupply(Warehouse * const wh) : m_economy(0), m_warehouse(wh) {} | ||
1352 | 35 | virtual ~WarehouseSupply(); | ||
1353 | 36 | |||
1354 | 37 | void set_economy(Economy *); | ||
1355 | 38 | |||
1356 | 39 | void set_nrworkers(Ware_Index); | ||
1357 | 40 | void set_nrwares (Ware_Index); | ||
1358 | 41 | |||
1359 | 42 | const WareList & get_wares () const {return m_wares;} | ||
1360 | 43 | const WareList & get_workers() const {return m_workers;} | ||
1361 | 44 | uint32_t stock_wares (Ware_Index const i) const { | ||
1362 | 45 | return m_wares .stock(i); | ||
1363 | 46 | } | ||
1364 | 47 | uint32_t stock_workers(Ware_Index const i) const { | ||
1365 | 48 | return m_workers.stock(i); | ||
1366 | 49 | } | ||
1367 | 50 | void add_wares (Ware_Index, uint32_t count); | ||
1368 | 51 | void remove_wares (Ware_Index, uint32_t count); | ||
1369 | 52 | void add_workers (Ware_Index, uint32_t count); | ||
1370 | 53 | void remove_workers(Ware_Index, uint32_t count); | ||
1371 | 54 | |||
1372 | 55 | // Supply implementation | ||
1373 | 56 | virtual PlayerImmovable * get_position(Game &); | ||
1374 | 57 | virtual bool is_active() const throw (); | ||
1375 | 58 | virtual bool has_storage() const throw (); | ||
1376 | 59 | virtual void get_ware_type(WareWorker & type, Ware_Index & ware) const; | ||
1377 | 60 | |||
1378 | 61 | virtual void send_to_storage(Game &, Warehouse * wh); | ||
1379 | 62 | virtual uint32_t nr_supplies(const Game &, const Request &) const; | ||
1380 | 63 | virtual WareInstance & launch_item(Game &, const Request &); | ||
1381 | 64 | virtual Worker & launch_worker(Game &, const Request &); | ||
1382 | 65 | |||
1383 | 66 | private: | ||
1384 | 67 | Economy * m_economy; | ||
1385 | 68 | WareList m_wares; | ||
1386 | 69 | WareList m_workers; // we use this to keep the soldiers | ||
1387 | 70 | Warehouse * m_warehouse; | ||
1388 | 71 | }; | ||
1389 | 72 | |||
1390 | 73 | } | ||
1391 | 74 | |||
1392 | 75 | |||
1393 | 76 | #endif | ||
1394 | 77 | 0 | ||
1395 | === removed file 'src/logic/attackable.h' | |||
1396 | --- src/logic/attackable.h 2012-02-15 21:25:34 +0000 | |||
1397 | +++ src/logic/attackable.h 1970-01-01 00:00:00 +0000 | |||
1398 | @@ -1,84 +0,0 @@ | |||
1399 | 1 | /* | ||
1400 | 2 | * Copyright (C) 2008-2009 by the Widelands Development Team | ||
1401 | 3 | * | ||
1402 | 4 | * This program is free software; you can redistribute it and/or | ||
1403 | 5 | * modify it under the terms of the GNU General Public License | ||
1404 | 6 | * as published by the Free Software Foundation; either version 2 | ||
1405 | 7 | * of the License, or (at your option) any later version. | ||
1406 | 8 | * | ||
1407 | 9 | * This program is distributed in the hope that it will be useful, | ||
1408 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1409 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1410 | 12 | * GNU General Public License for more details. | ||
1411 | 13 | * | ||
1412 | 14 | * You should have received a copy of the GNU General Public License | ||
1413 | 15 | * along with this program; if not, write to the Free Software | ||
1414 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
1415 | 17 | * | ||
1416 | 18 | */ | ||
1417 | 19 | |||
1418 | 20 | #ifndef ATTACKABLE_H | ||
1419 | 21 | #define ATTACKABLE_H | ||
1420 | 22 | |||
1421 | 23 | namespace Widelands { | ||
1422 | 24 | |||
1423 | 25 | struct Player; | ||
1424 | 26 | class Soldier; | ||
1425 | 27 | |||
1426 | 28 | enum { | ||
1427 | 29 | /** | ||
1428 | 30 | * This is the maximum radius that a military building can protect | ||
1429 | 31 | * in the sense that an enemy soldier that enters the player's territory | ||
1430 | 32 | * will call \ref Attackable::aggressor if it is that close. | ||
1431 | 33 | */ | ||
1432 | 34 | MaxProtectionRadius = 25 | ||
1433 | 35 | }; | ||
1434 | 36 | |||
1435 | 37 | /** | ||
1436 | 38 | * Buildings can implement this interface to indicate that | ||
1437 | 39 | * they can be attacked. | ||
1438 | 40 | */ | ||
1439 | 41 | struct Attackable { | ||
1440 | 42 | /** | ||
1441 | 43 | * Return the player that owns this attackable. | ||
1442 | 44 | */ | ||
1443 | 45 | virtual Player & owner() const = 0; | ||
1444 | 46 | |||
1445 | 47 | /** | ||
1446 | 48 | * Determines whether this building can be attacked right now. | ||
1447 | 49 | * | ||
1448 | 50 | * This should only return false for military sites that have not | ||
1449 | 51 | * been occupied yet. | ||
1450 | 52 | */ | ||
1451 | 53 | virtual bool canAttack() = 0; | ||
1452 | 54 | |||
1453 | 55 | /** | ||
1454 | 56 | * Called by an enemy soldier that enters a node with distance | ||
1455 | 57 | * less than or equal to \ref MaxProtectionRadius from the building. | ||
1456 | 58 | * | ||
1457 | 59 | * This allows the building to send protective forces to intercept | ||
1458 | 60 | * the soldier. | ||
1459 | 61 | */ | ||
1460 | 62 | virtual void aggressor(Soldier &) = 0; | ||
1461 | 63 | |||
1462 | 64 | /** | ||
1463 | 65 | * Called by a soldier who is standing on the building's flag | ||
1464 | 66 | * to attack the building. | ||
1465 | 67 | * | ||
1466 | 68 | * The building must send a soldier for defense, and return \c true. | ||
1467 | 69 | * Otherwise, i.e. if the building cannot defend itself anymore, | ||
1468 | 70 | * it must destroy itself or turn over to the attacking player, | ||
1469 | 71 | * and return \c false. | ||
1470 | 72 | * | ||
1471 | 73 | * \return \c true if a soldier was launched in defense of the building, | ||
1472 | 74 | * or \c false if the building cannot defend itself any longer. | ||
1473 | 75 | */ | ||
1474 | 76 | virtual bool attack(Soldier &) = 0; | ||
1475 | 77 | |||
1476 | 78 | protected: | ||
1477 | 79 | virtual ~Attackable() {} | ||
1478 | 80 | }; | ||
1479 | 81 | |||
1480 | 82 | } | ||
1481 | 83 | |||
1482 | 84 | #endif | ||
1483 | 85 | 0 | ||
1484 | === modified file 'src/logic/building.h' | |||
1485 | --- src/logic/building.h 2013-08-08 19:55:12 +0000 | |||
1486 | +++ src/logic/building.h 2013-08-10 10:53:03 +0000 | |||
1487 | @@ -258,6 +258,9 @@ | |||
1488 | 258 | void set_defeating_player(Player_Number const player_number) { | 258 | void set_defeating_player(Player_Number const player_number) { |
1489 | 259 | m_defeating_player = player_number; | 259 | m_defeating_player = player_number; |
1490 | 260 | } | 260 | } |
1491 | 261 | Player_Number get_defeating_player() { | ||
1492 | 262 | return m_defeating_player; | ||
1493 | 263 | } | ||
1494 | 261 | 264 | ||
1495 | 262 | void add_worker(Worker &); | 265 | void add_worker(Worker &); |
1496 | 263 | void remove_worker(Worker &); | 266 | void remove_worker(Worker &); |
1497 | 264 | 267 | ||
1498 | === modified file 'src/logic/findimmovable.cc' | |||
1499 | --- src/logic/findimmovable.cc 2013-07-26 20:19:36 +0000 | |||
1500 | +++ src/logic/findimmovable.cc 2013-08-10 10:53:03 +0000 | |||
1501 | @@ -20,7 +20,6 @@ | |||
1502 | 20 | #include "logic/findimmovable.h" | 20 | #include "logic/findimmovable.h" |
1503 | 21 | 21 | ||
1504 | 22 | #include "economy/flag.h" | 22 | #include "economy/flag.h" |
1505 | 23 | #include "logic/attackable.h" | ||
1506 | 24 | #include "logic/immovable.h" | 23 | #include "logic/immovable.h" |
1507 | 25 | #include "logic/militarysite.h" | 24 | #include "logic/militarysite.h" |
1508 | 26 | #include "upcast.h" | 25 | #include "upcast.h" |
1509 | @@ -61,7 +60,8 @@ | |||
1510 | 61 | } | 60 | } |
1511 | 62 | 61 | ||
1512 | 63 | bool FindImmovableAttackable ::accept(const BaseImmovable & imm) const { | 62 | bool FindImmovableAttackable ::accept(const BaseImmovable & imm) const { |
1514 | 64 | return dynamic_cast<Attackable const *>(&imm); | 63 | upcast(const GarrisonOwner, go, &imm); |
1515 | 64 | return (go && go->get_garrison()->canAttack()); | ||
1516 | 65 | } | 65 | } |
1517 | 66 | 66 | ||
1518 | 67 | bool FindImmovableByDescr::accept(const BaseImmovable & baseimm) const { | 67 | bool FindImmovableByDescr::accept(const BaseImmovable & baseimm) const { |
1519 | 68 | 68 | ||
1520 | === modified file 'src/logic/game.cc' | |||
1521 | --- src/logic/game.cc 2013-08-07 12:32:36 +0000 | |||
1522 | +++ src/logic/game.cc 2013-08-10 10:53:03 +0000 | |||
1523 | @@ -781,7 +781,8 @@ | |||
1524 | 781 | (get_gametime(), building.owner().player_number(), building)); | 781 | (get_gametime(), building.owner().player_number(), building)); |
1525 | 782 | } | 782 | } |
1526 | 783 | 783 | ||
1528 | 784 | void Game::send_player_militarysite_set_soldier_preference (Building & building, uint8_t my_preference) | 784 | void Game::send_player_militarysite_set_soldier_preference |
1529 | 785 | (Building & building, Garrison::SoldierPref my_preference) | ||
1530 | 785 | { | 786 | { |
1531 | 786 | send_player_command | 787 | send_player_command |
1532 | 787 | (*new Cmd_MilitarySiteSetSoldierPreference | 788 | (*new Cmd_MilitarySiteSetSoldierPreference |
1533 | 788 | 789 | ||
1534 | === modified file 'src/logic/game.h' | |||
1535 | --- src/logic/game.h 2013-08-07 12:32:36 +0000 | |||
1536 | +++ src/logic/game.h 2013-08-10 10:53:03 +0000 | |||
1537 | @@ -22,6 +22,7 @@ | |||
1538 | 22 | 22 | ||
1539 | 23 | #include "logic/cmd_queue.h" | 23 | #include "logic/cmd_queue.h" |
1540 | 24 | #include "logic/editor_game_base.h" | 24 | #include "logic/editor_game_base.h" |
1541 | 25 | #include "logic/garrison.h" | ||
1542 | 25 | #include "md5.h" | 26 | #include "md5.h" |
1543 | 26 | #include "random.h" | 27 | #include "random.h" |
1544 | 27 | #include "save_handler.h" | 28 | #include "save_handler.h" |
1545 | @@ -152,7 +153,7 @@ | |||
1546 | 152 | void send_player_build_road (int32_t, Path &); | 153 | void send_player_build_road (int32_t, Path &); |
1547 | 153 | void send_player_flagaction (Flag &); | 154 | void send_player_flagaction (Flag &); |
1548 | 154 | void send_player_start_stop_building (Building &); | 155 | void send_player_start_stop_building (Building &); |
1550 | 155 | void send_player_militarysite_set_soldier_preference (Building &, uint8_t preference); | 156 | void send_player_militarysite_set_soldier_preference (Building &, Garrison::SoldierPref preference); |
1551 | 156 | void send_player_start_or_cancel_expedition (Building &); | 157 | void send_player_start_or_cancel_expedition (Building &); |
1552 | 157 | 158 | ||
1553 | 158 | void send_player_enhance_building (Building &, Building_Index); | 159 | void send_player_enhance_building (Building &, Building_Index); |
1554 | 159 | 160 | ||
1555 | === added file 'src/logic/garrison.h' | |||
1556 | --- src/logic/garrison.h 1970-01-01 00:00:00 +0000 | |||
1557 | +++ src/logic/garrison.h 2013-08-10 10:53:03 +0000 | |||
1558 | @@ -0,0 +1,227 @@ | |||
1559 | 1 | /* | ||
1560 | 2 | * Copyright (C) 2008-2009 by the Widelands Development Team | ||
1561 | 3 | * | ||
1562 | 4 | * This program is free software; you can redistribute it and/or | ||
1563 | 5 | * modify it under the terms of the GNU General Public License | ||
1564 | 6 | * as published by the Free Software Foundation; either version 2 | ||
1565 | 7 | * of the License, or (at your option) any later version. | ||
1566 | 8 | * | ||
1567 | 9 | * This program is distributed in the hope that it will be useful, | ||
1568 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1569 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1570 | 12 | * GNU General Public License for more details. | ||
1571 | 13 | * | ||
1572 | 14 | * You should have received a copy of the GNU General Public License | ||
1573 | 15 | * along with this program; if not, write to the Free Software | ||
1574 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
1575 | 17 | * | ||
1576 | 18 | */ | ||
1577 | 19 | |||
1578 | 20 | #ifndef GARRISON_H | ||
1579 | 21 | #define GARRISON_H | ||
1580 | 22 | |||
1581 | 23 | #include <vector> | ||
1582 | 24 | |||
1583 | 25 | #include "logic/widelands.h" | ||
1584 | 26 | |||
1585 | 27 | namespace Widelands { | ||
1586 | 28 | |||
1587 | 29 | class Building; | ||
1588 | 30 | |||
1589 | 31 | |||
1590 | 32 | class Building; | ||
1591 | 33 | class Editor_Game_Base; | ||
1592 | 34 | class Game; | ||
1593 | 35 | struct Player; | ||
1594 | 36 | class Soldier; | ||
1595 | 37 | |||
1596 | 38 | enum { | ||
1597 | 39 | /** | ||
1598 | 40 | * This is the maximum radius that a military building can protect | ||
1599 | 41 | * in the sense that an enemy soldier that enters the player's territory | ||
1600 | 42 | * will call \ref Attackable::aggressor if it is that close. | ||
1601 | 43 | */ | ||
1602 | 44 | MaxProtectionRadius = 25 | ||
1603 | 45 | }; | ||
1604 | 46 | /** | ||
1605 | 47 | * A garrison represents a bunch of soldiers. Garrisons are owned by GarrisonOwner | ||
1606 | 48 | * buildings. This interface provides various methods to deal with soldier control | ||
1607 | 49 | * and attacks. | ||
1608 | 50 | */ | ||
1609 | 51 | class Garrison { | ||
1610 | 52 | public: | ||
1611 | 53 | enum SoldierPref : uint8_t { | ||
1612 | 54 | None, | ||
1613 | 55 | Rookies, | ||
1614 | 56 | Heroes, | ||
1615 | 57 | }; | ||
1616 | 58 | /** | ||
1617 | 59 | * Return the player that owns this attackable. | ||
1618 | 60 | */ | ||
1619 | 61 | virtual Player & owner() const = 0; | ||
1620 | 62 | |||
1621 | 63 | /** | ||
1622 | 64 | * Determines whether this building can be attacked right now. | ||
1623 | 65 | * | ||
1624 | 66 | * This should only return false for military sites that have not | ||
1625 | 67 | * been occupied yet, or by passivve garrison such as training sites. | ||
1626 | 68 | */ | ||
1627 | 69 | virtual bool canAttack() const = 0; | ||
1628 | 70 | |||
1629 | 71 | /** | ||
1630 | 72 | * Called by an enemy soldier that enters a node with distance | ||
1631 | 73 | * less than or equal to \ref MaxProtectionRadius from the building. | ||
1632 | 74 | * | ||
1633 | 75 | * This allows the building to send protective forces to intercept | ||
1634 | 76 | * the soldier. | ||
1635 | 77 | */ | ||
1636 | 78 | virtual void aggressor(Soldier &) = 0; | ||
1637 | 79 | |||
1638 | 80 | /** | ||
1639 | 81 | * Called by a soldier who is standing on the building's flag | ||
1640 | 82 | * to attack the building. | ||
1641 | 83 | * | ||
1642 | 84 | * The building must send a soldier for defense, and return \c true. | ||
1643 | 85 | * Otherwise, i.e. if the building cannot defend itself anymore, | ||
1644 | 86 | * it must destroy itself or turn over to the attacking player, | ||
1645 | 87 | * and return \c false. | ||
1646 | 88 | * | ||
1647 | 89 | * \return \c true if a soldier was launched in defense of the building, | ||
1648 | 90 | * or \c false if the building cannot defend itself any longer. | ||
1649 | 91 | */ | ||
1650 | 92 | virtual bool attack(Soldier &) = 0; | ||
1651 | 93 | |||
1652 | 94 | virtual bool is_passive() = 0; | ||
1653 | 95 | |||
1654 | 96 | virtual Building& get_building() = 0; | ||
1655 | 97 | |||
1656 | 98 | /** | ||
1657 | 99 | * \return a list of soldiers that are currently present in the building. | ||
1658 | 100 | */ | ||
1659 | 101 | virtual const std::vector<Soldier *> presentSoldiers() const = 0; | ||
1660 | 102 | |||
1661 | 103 | /** | ||
1662 | 104 | * \return a list of soldiers that are currently stationed in the building. | ||
1663 | 105 | * That is, all soldiers occupying a slot in the garrison. | ||
1664 | 106 | */ | ||
1665 | 107 | virtual const std::vector<Soldier *> stationedSoldiers() const = 0; | ||
1666 | 108 | |||
1667 | 109 | /** | ||
1668 | 110 | * \return the minimum number of soldiers that this building can be | ||
1669 | 111 | * configured to hold. | ||
1670 | 112 | */ | ||
1671 | 113 | virtual uint32_t minSoldierCapacity() const = 0; | ||
1672 | 114 | |||
1673 | 115 | /** | ||
1674 | 116 | * \return the maximum number of soldiers that this building can be | ||
1675 | 117 | * configured to hold. | ||
1676 | 118 | */ | ||
1677 | 119 | virtual uint32_t maxSoldierCapacity() const = 0; | ||
1678 | 120 | |||
1679 | 121 | /** | ||
1680 | 122 | * \return the number of soldiers this building is configured to hold | ||
1681 | 123 | * right now. | ||
1682 | 124 | */ | ||
1683 | 125 | virtual uint32_t soldierCapacity() const = 0; | ||
1684 | 126 | |||
1685 | 127 | /** | ||
1686 | 128 | * Sets the capacity for soldiers of this building. | ||
1687 | 129 | * | ||
1688 | 130 | * New soldiers will be requested and old soldiers will be evicted | ||
1689 | 131 | * as necessary. | ||
1690 | 132 | */ | ||
1691 | 133 | virtual void setSoldierCapacity(uint32_t capacity) = 0; | ||
1692 | 134 | void changeSoldierCapacity(int32_t const difference) { | ||
1693 | 135 | uint32_t const old_capacity = soldierCapacity(); | ||
1694 | 136 | uint32_t const new_capacity = | ||
1695 | 137 | std::min | ||
1696 | 138 | (static_cast<uint32_t> | ||
1697 | 139 | (std::max | ||
1698 | 140 | (static_cast<int32_t>(old_capacity) + difference, | ||
1699 | 141 | static_cast<int32_t>(minSoldierCapacity()))), | ||
1700 | 142 | static_cast<uint32_t>(maxSoldierCapacity())); | ||
1701 | 143 | if (old_capacity != new_capacity) | ||
1702 | 144 | setSoldierCapacity(new_capacity); | ||
1703 | 145 | } | ||
1704 | 146 | /** | ||
1705 | 147 | * Evict the given soldier from the building immediately, | ||
1706 | 148 | * without changing the building's capacity. | ||
1707 | 149 | * | ||
1708 | 150 | * \note This has no effect if the soldier is currently involved in a battle | ||
1709 | 151 | * or otherwise blocked from leaving the building. | ||
1710 | 152 | */ | ||
1711 | 153 | virtual void dropSoldier(Soldier &) = 0; | ||
1712 | 154 | |||
1713 | 155 | /** | ||
1714 | 156 | * Add a new soldier into this site. Returns -1 if there is no space | ||
1715 | 157 | * for him, 0 on success | ||
1716 | 158 | */ | ||
1717 | 159 | virtual int incorporateSoldier(Editor_Game_Base &, Soldier &) = 0; | ||
1718 | 160 | |||
1719 | 161 | /** | ||
1720 | 162 | * Remove a soldier from the internal list. Most SoldierControls will be | ||
1721 | 163 | * informed by the soldier when it is removed, but WareHouses for example | ||
1722 | 164 | * will not. | ||
1723 | 165 | */ | ||
1724 | 166 | virtual int outcorporateSoldier(Editor_Game_Base &, Soldier &) = 0; | ||
1725 | 167 | |||
1726 | 168 | /** | ||
1727 | 169 | * Returns the conquer radius of this garrison | ||
1728 | 170 | */ | ||
1729 | 171 | virtual uint32_t conquerRadius() const = 0; | ||
1730 | 172 | /** | ||
1731 | 173 | * Set the soldier preference. Heroes or rookies? | ||
1732 | 174 | */ | ||
1733 | 175 | virtual void set_soldier_preference(SoldierPref p) = 0; | ||
1734 | 176 | /** | ||
1735 | 177 | * \return the current soldier preference | ||
1736 | 178 | */ | ||
1737 | 179 | virtual SoldierPref get_soldier_preference() const = 0; | ||
1738 | 180 | /** | ||
1739 | 181 | * Try to send the given soldier to attack the fiven target building. | ||
1740 | 182 | * This will fail if the soldier already has a job. | ||
1741 | 183 | */ | ||
1742 | 184 | virtual void sendAttacker(Soldier & soldier, Building & target, uint8_t retreat) = 0; | ||
1743 | 185 | }; | ||
1744 | 186 | |||
1745 | 187 | |||
1746 | 188 | /** | ||
1747 | 189 | * A Garrison owner holds a garrison. This interface is to be implemented by | ||
1748 | 190 | * buildings that want to store some soldiers. The GarrionHandler Garrison | ||
1749 | 191 | * implementation may be used as the Garrison provider. | ||
1750 | 192 | */ | ||
1751 | 193 | class GarrisonOwner { | ||
1752 | 194 | public: | ||
1753 | 195 | /** | ||
1754 | 196 | * \return the garrison instance | ||
1755 | 197 | */ | ||
1756 | 198 | virtual Garrison* get_garrison() const = 0; | ||
1757 | 199 | /** | ||
1758 | 200 | * @return the building owning the garrison | ||
1759 | 201 | */ | ||
1760 | 202 | virtual Building* get_building() = 0; | ||
1761 | 203 | /** | ||
1762 | 204 | * Called when the garrison has been lost. \param defeating is set to the | ||
1763 | 205 | * enemy owner, or this owner if we keep military presence. if \param captured, | ||
1764 | 206 | * the enemy captured the building and a new one must be force built. | ||
1765 | 207 | * | ||
1766 | 208 | * Will not be called by passive garrisons | ||
1767 | 209 | */ | ||
1768 | 210 | virtual void garrison_lost(Game & game, Player_Number defeating, bool captured) = 0; | ||
1769 | 211 | /** | ||
1770 | 212 | * Called when the garrison is occupied. You may light up the fire now | ||
1771 | 213 | * | ||
1772 | 214 | * Will not be called by passive garrison | ||
1773 | 215 | */ | ||
1774 | 216 | virtual void garrison_occupied() = 0; | ||
1775 | 217 | /** | ||
1776 | 218 | * Called on the new site when a site has been conquered | ||
1777 | 219 | * | ||
1778 | 220 | * Will not be called by passive garrison | ||
1779 | 221 | */ | ||
1780 | 222 | virtual void reinit_after_conqueral(Game & game) = 0; | ||
1781 | 223 | }; | ||
1782 | 224 | |||
1783 | 225 | } | ||
1784 | 226 | |||
1785 | 227 | #endif | ||
1786 | 0 | 228 | ||
1787 | === added file 'src/logic/garrisonhandler.cc' | |||
1788 | --- src/logic/garrisonhandler.cc 1970-01-01 00:00:00 +0000 | |||
1789 | +++ src/logic/garrisonhandler.cc 2013-08-10 10:53:03 +0000 | |||
1790 | @@ -0,0 +1,925 @@ | |||
1791 | 1 | /* | ||
1792 | 2 | * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team | ||
1793 | 3 | * | ||
1794 | 4 | * This program is free software; you can redistribute it and/or | ||
1795 | 5 | * modify it under the terms of the GNU General Public License | ||
1796 | 6 | * as published by the Free Software Foundation; either version 2 | ||
1797 | 7 | * of the License, or (at your option) any later version. | ||
1798 | 8 | * | ||
1799 | 9 | * This program is distributed in the hope that it will be useful, | ||
1800 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1801 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1802 | 12 | * GNU General Public License for more details. | ||
1803 | 13 | * | ||
1804 | 14 | * You should have received a copy of the GNU General Public License | ||
1805 | 15 | * along with this program; if not, write to the Free Software | ||
1806 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
1807 | 17 | * | ||
1808 | 18 | */ | ||
1809 | 19 | |||
1810 | 20 | #include "logic/garrisonhandler.h" | ||
1811 | 21 | |||
1812 | 22 | #include <functional> | ||
1813 | 23 | #include <memory> | ||
1814 | 24 | #include <vector> | ||
1815 | 25 | |||
1816 | 26 | #include <boost/foreach.hpp> | ||
1817 | 27 | #include <boost/format.hpp> | ||
1818 | 28 | |||
1819 | 29 | #include "container_iterate.h" | ||
1820 | 30 | #include "economy/flag.h" | ||
1821 | 31 | #include "economy/request.h" | ||
1822 | 32 | #include "log.h" | ||
1823 | 33 | #include "logic/building.h" | ||
1824 | 34 | #include "logic/findbob.h" | ||
1825 | 35 | #include "logic/instances.h" | ||
1826 | 36 | #include "logic/militarysite.h" | ||
1827 | 37 | #include "logic/player.h" | ||
1828 | 38 | #include "logic/soldier.h" | ||
1829 | 39 | #include "upcast.h" | ||
1830 | 40 | |||
1831 | 41 | namespace Widelands { | ||
1832 | 42 | |||
1833 | 43 | GarrisonHandler::GarrisonHandler | ||
1834 | 44 | (Building& building, uint32_t min_soldiers, uint32_t max_soldiers, uint32_t conquer_radius, | ||
1835 | 45 | uint32_t heal_per_second, SoldierPref soldier_pref, bool passive) | ||
1836 | 46 | : Garrison(), | ||
1837 | 47 | m_building(building), | ||
1838 | 48 | m_min_capacity(min_soldiers), | ||
1839 | 49 | m_max_capacity(max_soldiers), | ||
1840 | 50 | m_capacity(max_soldiers), | ||
1841 | 51 | m_passive(passive), | ||
1842 | 52 | m_heal_per_second(heal_per_second), | ||
1843 | 53 | m_last_heal_time(0), | ||
1844 | 54 | m_conquer_radius(conquer_radius), | ||
1845 | 55 | m_didconquer(false), | ||
1846 | 56 | m_soldier_preference(soldier_pref), | ||
1847 | 57 | m_last_swap_soldiers_time(0), | ||
1848 | 58 | m_try_soldier_upgrade(false), | ||
1849 | 59 | m_doing_upgrade_request(false) | ||
1850 | 60 | { | ||
1851 | 61 | assert(is_a(GarrisonOwner, &m_building)); | ||
1852 | 62 | } | ||
1853 | 63 | |||
1854 | 64 | GarrisonHandler::~GarrisonHandler() | ||
1855 | 65 | { | ||
1856 | 66 | assert(m_normal_soldier_request.get() == nullptr); | ||
1857 | 67 | assert(m_upgrade_soldier_request.get() == nullptr); | ||
1858 | 68 | } | ||
1859 | 69 | |||
1860 | 70 | void GarrisonHandler::load_finish(Editor_Game_Base& egbase) | ||
1861 | 71 | { | ||
1862 | 72 | // If our soldiers array is empty (old savegame), fill it with soldiers | ||
1863 | 73 | // found in building | ||
1864 | 74 | if (m_soldiers.empty()) { | ||
1865 | 75 | container_iterate_const(std::vector<Worker *>, m_building.get_workers(), i) { | ||
1866 | 76 | if (upcast(Soldier, soldier, *i.current)) { | ||
1867 | 77 | if (m_soldiers.size() < m_capacity) { | ||
1868 | 78 | m_soldiers.push_back(soldier); | ||
1869 | 79 | } else { | ||
1870 | 80 | break; | ||
1871 | 81 | } | ||
1872 | 82 | } | ||
1873 | 83 | } | ||
1874 | 84 | } | ||
1875 | 85 | } | ||
1876 | 86 | |||
1877 | 87 | void GarrisonHandler::init(Editor_Game_Base & egbase) | ||
1878 | 88 | { | ||
1879 | 89 | // Ensure all soldiers are fresh and give them a new task | ||
1880 | 90 | upcast(Game, game, &egbase); | ||
1881 | 91 | container_iterate_const(std::vector<Soldier *>, m_soldiers, i) { | ||
1882 | 92 | Soldier* soldier = *i.current; | ||
1883 | 93 | assert(!soldier->get_state()); // Should be newly created. | ||
1884 | 94 | soldier->set_location_initially(m_building); | ||
1885 | 95 | if (game) { | ||
1886 | 96 | if (m_passive) { | ||
1887 | 97 | soldier->start_task_idle(*game, 0, -1); | ||
1888 | 98 | } else { | ||
1889 | 99 | soldier->start_task_buildingwork(*game); | ||
1890 | 100 | } | ||
1891 | 101 | } | ||
1892 | 102 | } | ||
1893 | 103 | // Update requests and timers | ||
1894 | 104 | update_soldier_request(); | ||
1895 | 105 | m_last_heal_time = egbase.get_gametime(); | ||
1896 | 106 | } | ||
1897 | 107 | |||
1898 | 108 | void GarrisonHandler::reinit_after_conqueral(Game& game) | ||
1899 | 109 | { | ||
1900 | 110 | m_soldier_requirements = Requirements(); | ||
1901 | 111 | conquer_area(game); | ||
1902 | 112 | update_soldier_request(); | ||
1903 | 113 | } | ||
1904 | 114 | |||
1905 | 115 | void GarrisonHandler::cleanup(Editor_Game_Base& egbase) | ||
1906 | 116 | { | ||
1907 | 117 | if (m_didconquer && !m_passive) { | ||
1908 | 118 | egbase.unconquer_area | ||
1909 | 119 | (Player_Area<Area<FCoords> > | ||
1910 | 120 | (owner().player_number(), | ||
1911 | 121 | Area<FCoords>(egbase.map().get_fcoords(m_building.get_position()), m_conquer_radius)), | ||
1912 | 122 | m_building.get_defeating_player()); | ||
1913 | 123 | } | ||
1914 | 124 | } | ||
1915 | 125 | |||
1916 | 126 | void GarrisonHandler::cleanup_requests(Editor_Game_Base&) | ||
1917 | 127 | { | ||
1918 | 128 | m_normal_soldier_request.reset(); | ||
1919 | 129 | m_upgrade_soldier_request.reset(); | ||
1920 | 130 | } | ||
1921 | 131 | |||
1922 | 132 | |||
1923 | 133 | int32_t GarrisonHandler::act(Game& game) | ||
1924 | 134 | { | ||
1925 | 135 | const int32_t timeofgame = game.get_gametime(); | ||
1926 | 136 | int32_t next_act = -1; | ||
1927 | 137 | // Ensure requests integrity | ||
1928 | 138 | if (m_normal_soldier_request && m_upgrade_soldier_request) | ||
1929 | 139 | { | ||
1930 | 140 | throw wexception("GarrisonHandler::act: Two soldier requests are ongoing -- should never happen!\n"); | ||
1931 | 141 | } | ||
1932 | 142 | // Update requests periodically | ||
1933 | 143 | bool full = stationedSoldiers().size() >= m_capacity; | ||
1934 | 144 | if (!full && !m_doing_upgrade_request && !m_normal_soldier_request) { | ||
1935 | 145 | // if we miss soldiers | ||
1936 | 146 | update_soldier_request(); | ||
1937 | 147 | } else { | ||
1938 | 148 | // If we may issue a new upgrade request | ||
1939 | 149 | int32_t time_since_last_swap = (timeofgame - m_last_swap_soldiers_time); | ||
1940 | 150 | if (time_since_last_swap > GARRISON_SWAP_TIMEOUT) { | ||
1941 | 151 | time_since_last_swap = timeofgame; | ||
1942 | 152 | update_soldier_request(); | ||
1943 | 153 | if (next_act < 0 || next_act > GARRISON_SWAP_TIMEOUT) { | ||
1944 | 154 | next_act = GARRISON_SWAP_TIMEOUT; | ||
1945 | 155 | } | ||
1946 | 156 | } | ||
1947 | 157 | } | ||
1948 | 158 | |||
1949 | 159 | // Calculate the amount of heal point to distribute | ||
1950 | 160 | uint32_t to_heal_amount = static_cast<uint32_t> | ||
1951 | 161 | ((timeofgame - m_last_heal_time) * m_heal_per_second / 1000); | ||
1952 | 162 | const std::vector<Soldier*> soldiers = presentSoldiers(); | ||
1953 | 163 | BOOST_FOREACH(Soldier* soldier, soldiers) { | ||
1954 | 164 | uint32_t to_heal = soldier->get_max_hitpoints() - soldier->get_current_hitpoints(); | ||
1955 | 165 | if (to_heal > to_heal_amount) to_heal = to_heal_amount; | ||
1956 | 166 | if (to_heal > 0) { | ||
1957 | 167 | soldier->heal(to_heal); | ||
1958 | 168 | to_heal_amount -= to_heal; | ||
1959 | 169 | // Act once/s while healing | ||
1960 | 170 | if (next_act < 0 || next_act > 1000) { | ||
1961 | 171 | next_act = 1000; | ||
1962 | 172 | } | ||
1963 | 173 | } | ||
1964 | 174 | if (to_heal_amount <= 0) break; | ||
1965 | 175 | } | ||
1966 | 176 | m_last_heal_time = timeofgame; | ||
1967 | 177 | // Act once/5s when idle | ||
1968 | 178 | if (next_act < 0) { | ||
1969 | 179 | next_act = 5000; | ||
1970 | 180 | } | ||
1971 | 181 | return next_act; | ||
1972 | 182 | } | ||
1973 | 183 | |||
1974 | 184 | void GarrisonHandler::popSoldier(Soldier* soldier) | ||
1975 | 185 | { | ||
1976 | 186 | // Pop the soldier and update requests | ||
1977 | 187 | popSoldierJob(soldier, nullptr, nullptr); | ||
1978 | 188 | update_soldier_request(); | ||
1979 | 189 | } | ||
1980 | 190 | |||
1981 | 191 | void GarrisonHandler::set_economy(Economy * const e) | ||
1982 | 192 | { | ||
1983 | 193 | // update requests | ||
1984 | 194 | if (m_normal_soldier_request && e) | ||
1985 | 195 | m_normal_soldier_request->set_economy(e); | ||
1986 | 196 | if (m_upgrade_soldier_request && e) | ||
1987 | 197 | m_upgrade_soldier_request->set_economy(e); | ||
1988 | 198 | } | ||
1989 | 199 | |||
1990 | 200 | |||
1991 | 201 | |||
1992 | 202 | bool GarrisonHandler::get_garrison_work(Game& game, Soldier* soldier) | ||
1993 | 203 | { | ||
1994 | 204 | // Evict soldiers that have returned home if the capacity is too low | ||
1995 | 205 | if (m_capacity < stationedSoldiers().size()) { | ||
1996 | 206 | evict_soldier(game, soldier); | ||
1997 | 207 | return true; | ||
1998 | 208 | } | ||
1999 | 209 | |||
2000 | 210 | bool stayhome; | ||
2001 | 211 | uint8_t retreat; | ||
2002 | 212 | if (Map_Object* enemy = popSoldierJob(soldier, &stayhome, &retreat)) { | ||
2003 | 213 | if (upcast(Building, building, enemy)) { | ||
2004 | 214 | soldier->start_task_attack(game, *building, retreat); | ||
2005 | 215 | return true; | ||
2006 | 216 | } else if (upcast(Soldier, opponent, enemy)) { | ||
2007 | 217 | if (!opponent->getBattle()) { | ||
2008 | 218 | soldier->start_task_defense(game, stayhome, retreat); | ||
2009 | 219 | if (stayhome) | ||
2010 | 220 | opponent->send_signal(game, "sleep"); | ||
2011 | 221 | return true; | ||
2012 | 222 | } | ||
2013 | 223 | } else | ||
2014 | 224 | throw wexception("GarrisonHandler::get_garrison_work: bad SoldierJob"); | ||
2015 | 225 | } | ||
2016 | 226 | return false; | ||
2017 | 227 | } | ||
2018 | 228 | |||
2019 | 229 | void GarrisonHandler::set_soldier_requirements(Requirements req) | ||
2020 | 230 | { | ||
2021 | 231 | m_soldier_requirements = req; | ||
2022 | 232 | } | ||
2023 | 233 | |||
2024 | 234 | // | ||
2025 | 235 | // Garrison implementation | ||
2026 | 236 | // | ||
2027 | 237 | |||
2028 | 238 | Player& GarrisonHandler::owner() const | ||
2029 | 239 | { | ||
2030 | 240 | return m_building.owner(); | ||
2031 | 241 | } | ||
2032 | 242 | |||
2033 | 243 | bool GarrisonHandler::canAttack() const | ||
2034 | 244 | { | ||
2035 | 245 | return m_didconquer && !m_passive; | ||
2036 | 246 | } | ||
2037 | 247 | |||
2038 | 248 | void GarrisonHandler::aggressor(Soldier& enemy) | ||
2039 | 249 | { | ||
2040 | 250 | Game & game = ref_cast<Game, Editor_Game_Base>(owner().egbase()); | ||
2041 | 251 | Map & map = game.map(); | ||
2042 | 252 | // Do not react if enemy is occupied or too far away | ||
2043 | 253 | if | ||
2044 | 254 | (enemy.get_owner() == &owner() || enemy.getBattle() | ||
2045 | 255 | || m_conquer_radius <= map.calc_distance | ||
2046 | 256 | (enemy.get_position(), m_building.get_position())) | ||
2047 | 257 | { | ||
2048 | 258 | return; | ||
2049 | 259 | } | ||
2050 | 260 | |||
2051 | 261 | // Do not react if enemy is at our door | ||
2052 | 262 | if | ||
2053 | 263 | (map.find_bobs | ||
2054 | 264 | (Area<FCoords>(map.get_fcoords(m_building.base_flag().get_position()), 2), 0, | ||
2055 | 265 | FindBobEnemySoldier(&owner()))) | ||
2056 | 266 | { | ||
2057 | 267 | return; | ||
2058 | 268 | } | ||
2059 | 269 | |||
2060 | 270 | // Send some soldiers to defend, keeping min capacity inside | ||
2061 | 271 | // This will send 1 soldier out to defend each time agressor() | ||
2062 | 272 | // is called //FIXME? | ||
2063 | 273 | const std::vector<Soldier*>& presents = presentSoldiers(); | ||
2064 | 274 | if (presents.size() > m_min_capacity) { | ||
2065 | 275 | container_iterate_const(std::vector<Soldier *>, presents, i) { | ||
2066 | 276 | if (!haveSoldierJob(**i.current)) { | ||
2067 | 277 | SoldierJob sj; | ||
2068 | 278 | sj.soldier = *i.current; | ||
2069 | 279 | sj.enemy = &enemy; | ||
2070 | 280 | sj.stayhome = false; | ||
2071 | 281 | sj.retreat = owner().get_retreat_percentage(); | ||
2072 | 282 | m_soldierjobs.push_back(sj); | ||
2073 | 283 | (*i.current)->update_task_buildingwork(game); | ||
2074 | 284 | return; | ||
2075 | 285 | } | ||
2076 | 286 | } | ||
2077 | 287 | } | ||
2078 | 288 | |||
2079 | 289 | // Inform the player, that we are under attack by adding a new entry to the | ||
2080 | 290 | // message queue - a sound will automatically be played. | ||
2081 | 291 | inform_owner(game, InfoType::AGGRESSSED); | ||
2082 | 292 | } | ||
2083 | 293 | |||
2084 | 294 | bool GarrisonHandler::attack(Soldier& enemy) | ||
2085 | 295 | { | ||
2086 | 296 | Game & game = ref_cast<Game, Editor_Game_Base>(owner().egbase()); | ||
2087 | 297 | |||
2088 | 298 | const std::vector<Soldier*>& present = presentSoldiers(); | ||
2089 | 299 | Soldier * defender = 0; | ||
2090 | 300 | |||
2091 | 301 | if (!present.empty()) { | ||
2092 | 302 | // Find soldier with greatest hitpoints | ||
2093 | 303 | uint32_t current_max = 0; | ||
2094 | 304 | container_iterate_const(std::vector<Soldier *>, present, i) { | ||
2095 | 305 | if ((*i.current)->get_current_hitpoints() > current_max) { | ||
2096 | 306 | defender = *i.current; | ||
2097 | 307 | current_max = defender->get_current_hitpoints(); | ||
2098 | 308 | } | ||
2099 | 309 | } | ||
2100 | 310 | } else { | ||
2101 | 311 | // If one of our stationed soldiers is currently walking into the | ||
2102 | 312 | // building, give us another chance. | ||
2103 | 313 | const std::vector<Soldier *>& stationed = stationedSoldiers(); | ||
2104 | 314 | container_iterate_const(std::vector<Soldier *>, stationed, i) { | ||
2105 | 315 | if ((*i.current)->get_position() == m_building.get_position()) { | ||
2106 | 316 | defender = *i.current; | ||
2107 | 317 | break; | ||
2108 | 318 | } | ||
2109 | 319 | } | ||
2110 | 320 | } | ||
2111 | 321 | |||
2112 | 322 | if (defender) { | ||
2113 | 323 | popSoldierJob(defender); // defense overrides all other jobs | ||
2114 | 324 | |||
2115 | 325 | SoldierJob sj; | ||
2116 | 326 | sj.soldier = defender; | ||
2117 | 327 | sj.enemy = &enemy; | ||
2118 | 328 | sj.stayhome = true; | ||
2119 | 329 | sj.retreat = 0; // Flag defenders could not retreat | ||
2120 | 330 | m_soldierjobs.push_back(sj); | ||
2121 | 331 | |||
2122 | 332 | defender->update_task_buildingwork(game); | ||
2123 | 333 | |||
2124 | 334 | // Inform the player, that we are under attack by adding a new entry to | ||
2125 | 335 | // the message queue - a sound will automatically be played. | ||
2126 | 336 | inform_owner(game, InfoType::UNDER_ATTACK); | ||
2127 | 337 | return true; | ||
2128 | 338 | } | ||
2129 | 339 | |||
2130 | 340 | // The enemy has defeated our forces, we should inform the player | ||
2131 | 341 | // Code for handling change of owner are handled in the garrison | ||
2132 | 342 | // owner class. | ||
2133 | 343 | upcast(GarrisonOwner, go, &m_building); | ||
2134 | 344 | if (military_presence_kept(game)) { | ||
2135 | 345 | inform_owner(game, InfoType::GARRISON_LOST); | ||
2136 | 346 | go->garrison_lost(game, owner().player_number(), false); | ||
2137 | 347 | } else { | ||
2138 | 348 | inform_owner(game, InfoType::GARRISON_CAPTURED); | ||
2139 | 349 | go->garrison_lost(game, enemy.owner().player_number(), true); | ||
2140 | 350 | } | ||
2141 | 351 | return false; | ||
2142 | 352 | } | ||
2143 | 353 | |||
2144 | 354 | bool GarrisonHandler::is_passive() | ||
2145 | 355 | { | ||
2146 | 356 | return m_passive; | ||
2147 | 357 | } | ||
2148 | 358 | |||
2149 | 359 | Building& GarrisonHandler::get_building() | ||
2150 | 360 | { | ||
2151 | 361 | return m_building; | ||
2152 | 362 | } | ||
2153 | 363 | |||
2154 | 364 | |||
2155 | 365 | |||
2156 | 366 | const std::vector< Soldier* > GarrisonHandler::presentSoldiers() const | ||
2157 | 367 | { | ||
2158 | 368 | std::vector<Soldier *> present_soldiers; | ||
2159 | 369 | container_iterate_const(std::vector<Soldier*>, m_soldiers, i) { | ||
2160 | 370 | if (isPresent(**i.current)) { | ||
2161 | 371 | present_soldiers.push_back(*i.current); | ||
2162 | 372 | } | ||
2163 | 373 | } | ||
2164 | 374 | return present_soldiers; | ||
2165 | 375 | } | ||
2166 | 376 | |||
2167 | 377 | const std::vector< Soldier* > GarrisonHandler::stationedSoldiers() const | ||
2168 | 378 | { | ||
2169 | 379 | return m_soldiers; | ||
2170 | 380 | } | ||
2171 | 381 | |||
2172 | 382 | uint32_t GarrisonHandler::minSoldierCapacity() const | ||
2173 | 383 | { | ||
2174 | 384 | return m_min_capacity; | ||
2175 | 385 | } | ||
2176 | 386 | |||
2177 | 387 | uint32_t GarrisonHandler::maxSoldierCapacity() const | ||
2178 | 388 | { | ||
2179 | 389 | return m_max_capacity; | ||
2180 | 390 | } | ||
2181 | 391 | |||
2182 | 392 | uint32_t GarrisonHandler::soldierCapacity() const | ||
2183 | 393 | { | ||
2184 | 394 | return m_capacity; | ||
2185 | 395 | } | ||
2186 | 396 | |||
2187 | 397 | void GarrisonHandler::setSoldierCapacity(uint32_t capacity) | ||
2188 | 398 | { | ||
2189 | 399 | assert(minSoldierCapacity() <= capacity); | ||
2190 | 400 | assert (capacity <= maxSoldierCapacity()); | ||
2191 | 401 | assert(m_capacity != capacity); | ||
2192 | 402 | m_capacity = capacity; | ||
2193 | 403 | update_soldier_request(); | ||
2194 | 404 | } | ||
2195 | 405 | |||
2196 | 406 | void GarrisonHandler::dropSoldier(Soldier& soldier) | ||
2197 | 407 | { | ||
2198 | 408 | Game & game = ref_cast<Game, Editor_Game_Base>(owner().egbase()); | ||
2199 | 409 | |||
2200 | 410 | if (!isPresent(soldier)) { | ||
2201 | 411 | // This can happen when the "drop soldier" player command is delayed | ||
2202 | 412 | // by network delay or a client has bugs. | ||
2203 | 413 | return; | ||
2204 | 414 | } | ||
2205 | 415 | // Ensure min capacity is respected | ||
2206 | 416 | if (presentSoldiers().size() <= minSoldierCapacity()) { | ||
2207 | 417 | return; | ||
2208 | 418 | } | ||
2209 | 419 | // Drop the soldier and update requests | ||
2210 | 420 | evict_soldier(game, &soldier); | ||
2211 | 421 | update_soldier_request(); | ||
2212 | 422 | } | ||
2213 | 423 | |||
2214 | 424 | int GarrisonHandler::incorporateSoldier(Editor_Game_Base& egbase, Soldier& s) | ||
2215 | 425 | { | ||
2216 | 426 | // Adjust the soldier location if required. | ||
2217 | 427 | if (s.get_location(egbase) != &m_building) | ||
2218 | 428 | { | ||
2219 | 429 | s.set_location(&m_building); | ||
2220 | 430 | } | ||
2221 | 431 | m_soldiers.push_back(&s); | ||
2222 | 432 | |||
2223 | 433 | upcast(Game, game, &egbase); | ||
2224 | 434 | // If it's the first soldier, conquer the area | ||
2225 | 435 | if (!m_passive && !m_didconquer) { | ||
2226 | 436 | conquer_area(egbase); | ||
2227 | 437 | if (game) { | ||
2228 | 438 | inform_owner(*game, InfoType::GARRISON_OCCUPIED); | ||
2229 | 439 | } | ||
2230 | 440 | upcast(GarrisonOwner, go, &m_building); | ||
2231 | 441 | go->garrison_occupied(); | ||
2232 | 442 | } | ||
2233 | 443 | |||
2234 | 444 | // Bind the worker into this house, hide him on the map | ||
2235 | 445 | if (game) { | ||
2236 | 446 | s.reset_tasks(*game); | ||
2237 | 447 | if (m_passive) { | ||
2238 | 448 | s.start_task_idle(*game, 0, -1); | ||
2239 | 449 | } else { | ||
2240 | 450 | s.start_task_buildingwork(*game); | ||
2241 | 451 | } | ||
2242 | 452 | } | ||
2243 | 453 | // Make sure the request count is reduced or the request is deleted. | ||
2244 | 454 | update_soldier_request(); | ||
2245 | 455 | return 0; | ||
2246 | 456 | } | ||
2247 | 457 | |||
2248 | 458 | int GarrisonHandler::outcorporateSoldier(Editor_Game_Base&, Soldier&) | ||
2249 | 459 | { | ||
2250 | 460 | // not needed | ||
2251 | 461 | log("CGH Outcorporate called\n"); | ||
2252 | 462 | return -1; | ||
2253 | 463 | } | ||
2254 | 464 | |||
2255 | 465 | uint32_t GarrisonHandler::conquerRadius() const | ||
2256 | 466 | { | ||
2257 | 467 | return m_conquer_radius; | ||
2258 | 468 | } | ||
2259 | 469 | |||
2260 | 470 | void GarrisonHandler::set_soldier_preference(GarrisonHandler::SoldierPref p) | ||
2261 | 471 | { | ||
2262 | 472 | assert(SoldierPref::Heroes == p || SoldierPref::Rookies == p); | ||
2263 | 473 | m_soldier_preference = p; | ||
2264 | 474 | update_normal_soldier_request(); | ||
2265 | 475 | } | ||
2266 | 476 | |||
2267 | 477 | |||
2268 | 478 | void GarrisonHandler::sendAttacker(Soldier& soldier, Building& target, uint8_t retreat) | ||
2269 | 479 | { | ||
2270 | 480 | assert(isPresent(soldier)); | ||
2271 | 481 | |||
2272 | 482 | if (haveSoldierJob(soldier)) { | ||
2273 | 483 | return; | ||
2274 | 484 | } | ||
2275 | 485 | |||
2276 | 486 | SoldierJob sj; | ||
2277 | 487 | sj.soldier = &soldier; | ||
2278 | 488 | sj.enemy = ⌖ | ||
2279 | 489 | sj.stayhome = false; | ||
2280 | 490 | sj.retreat = retreat; | ||
2281 | 491 | m_soldierjobs.push_back(sj); | ||
2282 | 492 | |||
2283 | 493 | soldier.update_task_buildingwork(ref_cast<Game, Editor_Game_Base>(owner().egbase())); | ||
2284 | 494 | } | ||
2285 | 495 | |||
2286 | 496 | // | ||
2287 | 497 | // Private helper methods | ||
2288 | 498 | // | ||
2289 | 499 | void GarrisonHandler::inform_owner(Game& game, GarrisonHandler::InfoType info) | ||
2290 | 500 | { | ||
2291 | 501 | if (m_passive) { | ||
2292 | 502 | return; | ||
2293 | 503 | } | ||
2294 | 504 | std::string message; | ||
2295 | 505 | std::string message_id; | ||
2296 | 506 | std::string message_title; | ||
2297 | 507 | std::string building_name = m_building.descname(); | ||
2298 | 508 | switch (info) { | ||
2299 | 509 | case InfoType::AGGRESSSED: | ||
2300 | 510 | message = | ||
2301 | 511 | (boost::format | ||
2302 | 512 | (_("Your %s discovered an aggressor")) % building_name) | ||
2303 | 513 | .str(); | ||
2304 | 514 | message_id = "under_attack"; | ||
2305 | 515 | message_title = _("You are under attack"); | ||
2306 | 516 | break; | ||
2307 | 517 | case InfoType::UNDER_ATTACK: | ||
2308 | 518 | message = | ||
2309 | 519 | (boost::format | ||
2310 | 520 | (_("Your %s is under attack")) % building_name) | ||
2311 | 521 | .str(); | ||
2312 | 522 | message_id = "under_attack"; | ||
2313 | 523 | message_title = _("You are under attack"); | ||
2314 | 524 | break; | ||
2315 | 525 | case InfoType::GARRISON_LOST: | ||
2316 | 526 | message = | ||
2317 | 527 | (boost::format | ||
2318 | 528 | (_("The enemy defeated your soldiers and destroyed your %s")) % building_name) | ||
2319 | 529 | .str(); | ||
2320 | 530 | message_id = "garrison_lost"; | ||
2321 | 531 | message_title = _("Garrison lost"); | ||
2322 | 532 | break; | ||
2323 | 533 | case InfoType::GARRISON_CAPTURED: | ||
2324 | 534 | message = | ||
2325 | 535 | (boost::format | ||
2326 | 536 | (_("The enemy defeated your soldiers and captured your %s")) % building_name) | ||
2327 | 537 | .str(); | ||
2328 | 538 | message_id = "garrison_lost"; | ||
2329 | 539 | message_title = _("Garrison captured"); | ||
2330 | 540 | break; | ||
2331 | 541 | case InfoType::GARRISON_OCCUPIED: | ||
2332 | 542 | message = | ||
2333 | 543 | (boost::format | ||
2334 | 544 | (_("Your soldier occupied your %s")) % building_name) | ||
2335 | 545 | .str(); | ||
2336 | 546 | message_id = "garrison_occupied"; | ||
2337 | 547 | message_title = _("Garrison occupied"); | ||
2338 | 548 | break; | ||
2339 | 549 | default: | ||
2340 | 550 | assert(false); | ||
2341 | 551 | } | ||
2342 | 552 | m_building.send_message(game, message_id, message_title, message); | ||
2343 | 553 | } | ||
2344 | 554 | |||
2345 | 555 | bool GarrisonHandler::isPresent(Soldier& soldier) const | ||
2346 | 556 | { | ||
2347 | 557 | if | ||
2348 | 558 | (soldier.get_location(owner().egbase()) != &m_building | ||
2349 | 559 | || soldier.get_position() != m_building.get_position()) | ||
2350 | 560 | { | ||
2351 | 561 | return false; | ||
2352 | 562 | } | ||
2353 | 563 | // Present soldiers are working for the garrison only if it is not passive | ||
2354 | 564 | if (!m_passive) { | ||
2355 | 565 | return | ||
2356 | 566 | soldier.get_state() == soldier.get_state(Worker::taskBuildingwork); | ||
2357 | 567 | } | ||
2358 | 568 | return true; | ||
2359 | 569 | } | ||
2360 | 570 | |||
2361 | 571 | void GarrisonHandler::conquer_area(Editor_Game_Base& egbase) | ||
2362 | 572 | { | ||
2363 | 573 | assert(!m_didconquer); | ||
2364 | 574 | egbase.conquer_area | ||
2365 | 575 | (Player_Area<Area<FCoords> > | ||
2366 | 576 | (owner().player_number(), | ||
2367 | 577 | Area<FCoords> | ||
2368 | 578 | (egbase.map().get_fcoords(m_building.get_position()), m_conquer_radius))); | ||
2369 | 579 | m_didconquer = true; | ||
2370 | 580 | } | ||
2371 | 581 | |||
2372 | 582 | bool GarrisonHandler::military_presence_kept(Game& game) | ||
2373 | 583 | { | ||
2374 | 584 | // collect information about immovables in the area | ||
2375 | 585 | std::vector<ImmovableFound> immovables; | ||
2376 | 586 | |||
2377 | 587 | // Search in a radius of 3 (needed for big militarysites) | ||
2378 | 588 | FCoords const fc = game.map().get_fcoords(m_building.get_position()); | ||
2379 | 589 | game.map().find_immovables(Area<FCoords>(fc, 3), &immovables); | ||
2380 | 590 | |||
2381 | 591 | for (uint32_t i = 0; i < immovables.size(); ++i) { | ||
2382 | 592 | upcast(GarrisonOwner, go, immovables[i].object); | ||
2383 | 593 | if (!go) { | ||
2384 | 594 | continue; | ||
2385 | 595 | } | ||
2386 | 596 | Garrison* g = go->get_garrison(); | ||
2387 | 597 | upcast(GarrisonOwner, mygo, &m_building); | ||
2388 | 598 | // NOCOM I changed the logic here to check for any stationed soldier | ||
2389 | 599 | // and not for m_didconquer. So a msite with all slots empty and soldiers | ||
2390 | 600 | // on their way won't keep military presence anymore. | ||
2391 | 601 | |||
2392 | 602 | // Presence kept if any non-empty garrison with higher conquer radius | ||
2393 | 603 | // and owned by our owner is nearby | ||
2394 | 604 | if | ||
2395 | 605 | (mygo != go | ||
2396 | 606 | && owner().player_number() == g->owner().player_number() | ||
2397 | 607 | && conquerRadius() < g->conquerRadius() | ||
2398 | 608 | && !g->stationedSoldiers().empty()) | ||
2399 | 609 | { | ||
2400 | 610 | return true; | ||
2401 | 611 | } | ||
2402 | 612 | } | ||
2403 | 613 | return false; | ||
2404 | 614 | } | ||
2405 | 615 | |||
2406 | 616 | //FIXME CGH use a cleaner way without polling required | ||
2407 | 617 | void GarrisonHandler::update_soldier_request(bool upgraded_in) | ||
2408 | 618 | { | ||
2409 | 619 | /* | ||
2410 | 620 | * I have update_soldier_request | ||
2411 | 621 | * update_upgrade_soldier_request | ||
2412 | 622 | * update_normal_soldier_request | ||
2413 | 623 | * | ||
2414 | 624 | * The first one handles state switching between site fill (normal more) | ||
2415 | 625 | * and grabbing soldiers with proper training (upgrade mode). The last | ||
2416 | 626 | * two actually make the requests. | ||
2417 | 627 | * | ||
2418 | 628 | * The input parameter incd is true, if we just incorporated a new soldier | ||
2419 | 629 | * as a result of an upgrade request. In such cases, we will re-arm the | ||
2420 | 630 | * upgrade request. | ||
2421 | 631 | */ | ||
2422 | 632 | const uint32_t capacity = soldierCapacity(); | ||
2423 | 633 | const uint32_t stationed = stationedSoldiers().size(); | ||
2424 | 634 | |||
2425 | 635 | if (m_doing_upgrade_request) { | ||
2426 | 636 | if (upgraded_in && m_upgrade_soldier_request) {// update requests always ask for one soldier at time! | ||
2427 | 637 | m_upgrade_soldier_request.reset(); | ||
2428 | 638 | } | ||
2429 | 639 | if (capacity > stationed) { | ||
2430 | 640 | // Somebody is killing my soldiers in the middle of upgrade | ||
2431 | 641 | // or I have kicked out his predecessor already. | ||
2432 | 642 | if | ||
2433 | 643 | ((m_upgrade_soldier_request) | ||
2434 | 644 | && (m_upgrade_soldier_request->is_open() || 0 == m_upgrade_soldier_request->get_count())) | ||
2435 | 645 | { | ||
2436 | 646 | // Economy was not able to find the soldiers I need. | ||
2437 | 647 | // I can safely drop the upgrade request and go to fill mode. | ||
2438 | 648 | m_upgrade_soldier_request.reset(); | ||
2439 | 649 | } | ||
2440 | 650 | if (!m_upgrade_soldier_request) { | ||
2441 | 651 | //phoo -- I can safely request new soldiers. | ||
2442 | 652 | m_doing_upgrade_request = false; | ||
2443 | 653 | update_normal_soldier_request(); | ||
2444 | 654 | } | ||
2445 | 655 | // else -- ohno please help me! Player is in trouble -- evil grin | ||
2446 | 656 | // An upgraded soldier is on his way, but since we only make one request | ||
2447 | 657 | // at a time, we have to wait for him to arrive before doing another | ||
2448 | 658 | // request to fill capacity. | ||
2449 | 659 | //FIXME | ||
2450 | 660 | } else if (capacity < stationed) {// player is reducing capacity | ||
2451 | 661 | drop_least_suited_soldier(); | ||
2452 | 662 | } else {// capacity == stationed size | ||
2453 | 663 | update_upgrade_soldier_request(); | ||
2454 | 664 | } | ||
2455 | 665 | } else {// not doing upgrade request | ||
2456 | 666 | if ((capacity != stationed) or (m_normal_soldier_request)) { | ||
2457 | 667 | update_normal_soldier_request(); | ||
2458 | 668 | } | ||
2459 | 669 | if ((capacity == stationed) && (! m_normal_soldier_request) && !m_passive) { | ||
2460 | 670 | // Our site is full, we might try to get upgraded soldiers | ||
2461 | 671 | // TODO not allowed for passive garrison for now | ||
2462 | 672 | if (presentSoldiers().size() == capacity && capacity > m_min_capacity) { | ||
2463 | 673 | m_doing_upgrade_request = true; | ||
2464 | 674 | } | ||
2465 | 675 | } | ||
2466 | 676 | } | ||
2467 | 677 | } | ||
2468 | 678 | |||
2469 | 679 | void GarrisonHandler::update_normal_soldier_request() | ||
2470 | 680 | { | ||
2471 | 681 | // Request new soldiers if needed | ||
2472 | 682 | std::vector<Soldier*> soldiers = stationedSoldiers(); | ||
2473 | 683 | if (soldiers.size() < m_capacity) { | ||
2474 | 684 | if (!m_normal_soldier_request) { | ||
2475 | 685 | // No ongoing request, fill a new one | ||
2476 | 686 | Request* r = new Request | ||
2477 | 687 | (m_building, m_building.tribe().safe_worker_index("soldier"), | ||
2478 | 688 | GarrisonHandler::request_soldier_callback, wwWORKER); | ||
2479 | 689 | r->set_requirements(m_soldier_requirements); | ||
2480 | 690 | m_normal_soldier_request.reset(r); | ||
2481 | 691 | } | ||
2482 | 692 | // Already an ongoing request, update counts | ||
2483 | 693 | m_normal_soldier_request->set_count(m_capacity - soldiers.size()); | ||
2484 | 694 | } else { | ||
2485 | 695 | // No new soldier required. Destroy request if there is one | ||
2486 | 696 | m_normal_soldier_request.reset(); | ||
2487 | 697 | } | ||
2488 | 698 | // Evict present soldiers if required | ||
2489 | 699 | const std::vector<Soldier *>& present = presentSoldiers(); | ||
2490 | 700 | if (present.size() > m_capacity) { | ||
2491 | 701 | Game & game = ref_cast<Game, Editor_Game_Base>(owner().egbase()); | ||
2492 | 702 | for (uint32_t i = 0; i < present.size() - m_capacity; ++i) { | ||
2493 | 703 | Soldier * soldier = present[i]; | ||
2494 | 704 | evict_soldier(game, soldier); | ||
2495 | 705 | } | ||
2496 | 706 | } | ||
2497 | 707 | } | ||
2498 | 708 | |||
2499 | 709 | void GarrisonHandler::update_upgrade_soldier_request() | ||
2500 | 710 | { | ||
2501 | 711 | bool reqirement_changed = update_upgrade_requirements(); | ||
2502 | 712 | // Update the requirements | ||
2503 | 713 | if (!m_try_soldier_upgrade) { | ||
2504 | 714 | return; | ||
2505 | 715 | } | ||
2506 | 716 | // Do not perform a new request if someone is on his way | ||
2507 | 717 | // or if we are going to request the same thing | ||
2508 | 718 | if (m_upgrade_soldier_request) { | ||
2509 | 719 | if (!m_upgrade_soldier_request->is_open()) { | ||
2510 | 720 | // upgraded soldier is on his way | ||
2511 | 721 | return; | ||
2512 | 722 | } | ||
2513 | 723 | if (!reqirement_changed && m_upgrade_soldier_request->get_count() > 0) { | ||
2514 | 724 | // Current request is still valid | ||
2515 | 725 | return; | ||
2516 | 726 | } | ||
2517 | 727 | } | ||
2518 | 728 | // Issue a new request | ||
2519 | 729 | Request* r = new Request | ||
2520 | 730 | (m_building, m_building.tribe().safe_worker_index("soldier"), | ||
2521 | 731 | GarrisonHandler::request_soldier_callback, wwWORKER, | ||
2522 | 732 | GarrisonHandler::request_soldier_transfer_callback); | ||
2523 | 733 | // Honor soldier requirements if set by the garrison owner | ||
2524 | 734 | RequireAnd upgrade_requirement; | ||
2525 | 735 | upgrade_requirement.add(m_soldier_requirements); | ||
2526 | 736 | upgrade_requirement.add(m_soldier_upgrade_requirements); | ||
2527 | 737 | r->set_requirements(upgrade_requirement); | ||
2528 | 738 | r->set_count(1); | ||
2529 | 739 | m_upgrade_soldier_request.reset(r); | ||
2530 | 740 | } | ||
2531 | 741 | |||
2532 | 742 | void GarrisonHandler::request_soldier_callback | ||
2533 | 743 | (Game& game, Request&, Ware_Index, Worker* w, PlayerImmovable& pi) | ||
2534 | 744 | { | ||
2535 | 745 | Soldier& s = ref_cast<Soldier, Worker>(*w); | ||
2536 | 746 | upcast(GarrisonOwner, go, &pi); | ||
2537 | 747 | upcast(GarrisonHandler, gh, go->get_garrison()); | ||
2538 | 748 | |||
2539 | 749 | if (!gh->m_doing_upgrade_request) { | ||
2540 | 750 | gh->incorporateSoldier(game, s); | ||
2541 | 751 | } else { | ||
2542 | 752 | gh->incorporateUpgradedSoldier(game, s); | ||
2543 | 753 | } | ||
2544 | 754 | } | ||
2545 | 755 | |||
2546 | 756 | void GarrisonHandler::request_soldier_transfer_callback | ||
2547 | 757 | (Game&, Request&, Ware_Index, Worker* w, PlayerImmovable& pi) | ||
2548 | 758 | { | ||
2549 | 759 | Soldier& s = ref_cast<Soldier, Worker>(*w); | ||
2550 | 760 | upcast(GarrisonOwner, go, &pi); | ||
2551 | 761 | upcast(GarrisonHandler, gh, go->get_garrison()); | ||
2552 | 762 | |||
2553 | 763 | if (gh->m_doing_upgrade_request) { | ||
2554 | 764 | gh->drop_least_suited_soldier(&s); | ||
2555 | 765 | } | ||
2556 | 766 | } | ||
2557 | 767 | |||
2558 | 768 | bool GarrisonHandler::update_upgrade_requirements() | ||
2559 | 769 | { | ||
2560 | 770 | int32_t soldier_upgrade_required_min = m_soldier_upgrade_requirements.getMin(); | ||
2561 | 771 | int32_t soldier_upgrade_required_max = m_soldier_upgrade_requirements.getMax(); | ||
2562 | 772 | |||
2563 | 773 | if | ||
2564 | 774 | (SoldierPref::Heroes != m_soldier_preference | ||
2565 | 775 | && SoldierPref::Rookies != m_soldier_preference) | ||
2566 | 776 | { | ||
2567 | 777 | m_try_soldier_upgrade = false; | ||
2568 | 778 | return false; | ||
2569 | 779 | } | ||
2570 | 780 | |||
2571 | 781 | // Find the level of the soldier that is currently least-suited. | ||
2572 | 782 | Soldier * worst_guy = find_least_suited_soldier(); | ||
2573 | 783 | if (worst_guy == nullptr) { | ||
2574 | 784 | // There could be no soldier in the militarysite right now. No reason to freak out. | ||
2575 | 785 | return false; | ||
2576 | 786 | } | ||
2577 | 787 | int32_t wg_level = worst_guy->get_level(atrTotal); | ||
2578 | 788 | |||
2579 | 789 | // Micro-optimization: I assume that the majority of military sites have only level-zero | ||
2580 | 790 | // soldiers and prefer rookies. Handle them separately. | ||
2581 | 791 | if (m_soldier_preference == SoldierPref::Rookies && wg_level == 0) { | ||
2582 | 792 | m_try_soldier_upgrade = false; | ||
2583 | 793 | return false; | ||
2584 | 794 | } | ||
2585 | 795 | m_try_soldier_upgrade = true; | ||
2586 | 796 | |||
2587 | 797 | // Now I actually build the new requirements. | ||
2588 | 798 | int32_t reqmin = SoldierPref::Heroes == m_soldier_preference ? 1 + wg_level : 0; | ||
2589 | 799 | int32_t reqmax = SoldierPref::Heroes == m_soldier_preference ? SHRT_MAX : wg_level - 1; | ||
2590 | 800 | |||
2591 | 801 | bool maxchanged = reqmax != soldier_upgrade_required_max; | ||
2592 | 802 | bool minchanged = reqmin != soldier_upgrade_required_min; | ||
2593 | 803 | |||
2594 | 804 | if (maxchanged or minchanged) { | ||
2595 | 805 | m_soldier_upgrade_requirements = RequireAttribute(atrTotal, reqmin, reqmax); | ||
2596 | 806 | return true; | ||
2597 | 807 | } | ||
2598 | 808 | return false; | ||
2599 | 809 | } | ||
2600 | 810 | |||
2601 | 811 | bool GarrisonHandler::incorporateUpgradedSoldier(Editor_Game_Base& egbase, Soldier& s) | ||
2602 | 812 | { | ||
2603 | 813 | // Call to drop_least routine has side effects: it tries to drop a soldier. Order is important! | ||
2604 | 814 | assert(isPresent(s)); | ||
2605 | 815 | std::vector<Soldier*> stationned = stationedSoldiers(); | ||
2606 | 816 | if (stationned.size() < m_capacity || drop_least_suited_soldier(&s)) { | ||
2607 | 817 | Game & game = ref_cast<Game, Editor_Game_Base>(egbase); | ||
2608 | 818 | s.set_location(&m_building); | ||
2609 | 819 | m_soldiers.push_back(&s); | ||
2610 | 820 | s.reset_tasks(game); | ||
2611 | 821 | if (!m_passive) { | ||
2612 | 822 | s.start_task_buildingwork(game); | ||
2613 | 823 | } else { | ||
2614 | 824 | s.start_task_idle(game, 0, -1); | ||
2615 | 825 | } | ||
2616 | 826 | // Reset timer for new request | ||
2617 | 827 | m_upgrade_soldier_request.reset(); | ||
2618 | 828 | m_last_swap_soldiers_time = game.get_gametime(); | ||
2619 | 829 | return true; | ||
2620 | 830 | } | ||
2621 | 831 | return false; | ||
2622 | 832 | } | ||
2623 | 833 | |||
2624 | 834 | Soldier* GarrisonHandler::find_least_suited_soldier() | ||
2625 | 835 | { | ||
2626 | 836 | const std::vector<Soldier *>& present = presentSoldiers(); | ||
2627 | 837 | const int32_t multiplier = m_soldier_preference == SoldierPref::Heroes ? -1 : 1; | ||
2628 | 838 | int worst_soldier_level = INT_MIN; | ||
2629 | 839 | Soldier * worst_soldier = nullptr; | ||
2630 | 840 | BOOST_FOREACH(Soldier * sld, present) | ||
2631 | 841 | { | ||
2632 | 842 | int this_soldier_level = multiplier * static_cast<int> (sld->get_level(atrTotal)); | ||
2633 | 843 | if (this_soldier_level > worst_soldier_level) | ||
2634 | 844 | { | ||
2635 | 845 | worst_soldier_level = this_soldier_level; | ||
2636 | 846 | worst_soldier = sld; | ||
2637 | 847 | } | ||
2638 | 848 | } | ||
2639 | 849 | return worst_soldier; | ||
2640 | 850 | } | ||
2641 | 851 | |||
2642 | 852 | bool GarrisonHandler::drop_least_suited_soldier(Soldier* newguy) | ||
2643 | 853 | { | ||
2644 | 854 | const std::vector<Soldier *>& present = presentSoldiers(); | ||
2645 | 855 | // Don't drop under the minimum capacity if new guy is not here yet | ||
2646 | 856 | if (newguy == nullptr && present.size() <= m_min_capacity) { | ||
2647 | 857 | return false; | ||
2648 | 858 | } | ||
2649 | 859 | Soldier * kickoutCandidate = find_least_suited_soldier(); | ||
2650 | 860 | |||
2651 | 861 | // If the arriving guy is worse than worst present, I wont't release. | ||
2652 | 862 | if (newguy != nullptr && kickoutCandidate != nullptr) { | ||
2653 | 863 | int32_t old_level = kickoutCandidate->get_level(atrTotal); | ||
2654 | 864 | int32_t new_level = newguy->get_level(atrTotal); | ||
2655 | 865 | if (m_soldier_preference == SoldierPref::Heroes && old_level >= new_level) { | ||
2656 | 866 | return false; | ||
2657 | 867 | } else if (m_soldier_preference == SoldierPref::Rookies && old_level <= new_level) { | ||
2658 | 868 | return false; | ||
2659 | 869 | } | ||
2660 | 870 | } | ||
2661 | 871 | |||
2662 | 872 | // Now I know that the new guy is worthy. | ||
2663 | 873 | if (kickoutCandidate != nullptr) { | ||
2664 | 874 | Game & game = ref_cast<Game, Editor_Game_Base>(owner().egbase()); | ||
2665 | 875 | evict_soldier(game, kickoutCandidate); | ||
2666 | 876 | return true; | ||
2667 | 877 | } | ||
2668 | 878 | return false; | ||
2669 | 879 | } | ||
2670 | 880 | |||
2671 | 881 | bool GarrisonHandler::haveSoldierJob(Soldier& soldier) const | ||
2672 | 882 | { | ||
2673 | 883 | container_iterate_const(std::vector<SoldierJob>, m_soldierjobs, i) { | ||
2674 | 884 | if (i.current->soldier == &soldier) { | ||
2675 | 885 | return true; | ||
2676 | 886 | } | ||
2677 | 887 | } | ||
2678 | 888 | return false; | ||
2679 | 889 | } | ||
2680 | 890 | |||
2681 | 891 | Map_Object* GarrisonHandler::popSoldierJob(Soldier* soldier, bool* stayhome, uint8_t* retreat) | ||
2682 | 892 | { | ||
2683 | 893 | container_iterate(std::vector<SoldierJob>, m_soldierjobs, i) | ||
2684 | 894 | if (i.current->soldier == soldier) { | ||
2685 | 895 | Map_Object * const enemy = i.current->enemy.get(owner().egbase()); | ||
2686 | 896 | if (stayhome) | ||
2687 | 897 | *stayhome = i.current->stayhome; | ||
2688 | 898 | if (retreat) | ||
2689 | 899 | *retreat = i.current->retreat; | ||
2690 | 900 | m_soldierjobs.erase(i.current); | ||
2691 | 901 | return enemy; | ||
2692 | 902 | } | ||
2693 | 903 | return 0; | ||
2694 | 904 | } | ||
2695 | 905 | |||
2696 | 906 | void GarrisonHandler::evict_soldier(Game& game, Soldier* s) | ||
2697 | 907 | { | ||
2698 | 908 | assert(s); | ||
2699 | 909 | upcast(StorageOwner, storage_owner, &m_building); | ||
2700 | 910 | std::vector<Soldier*>::iterator it; | ||
2701 | 911 | for (it = m_soldiers.begin(); it != m_soldiers.end(); ++it) { | ||
2702 | 912 | if ((*it)->serial() == s->serial()) { | ||
2703 | 913 | m_soldiers.erase(it); | ||
2704 | 914 | s->reset_tasks(game); | ||
2705 | 915 | if (storage_owner) { | ||
2706 | 916 | storage_owner->get_storage()->incorporate_worker(game, *s); | ||
2707 | 917 | } else { | ||
2708 | 918 | s->start_task_leavebuilding(game, true); | ||
2709 | 919 | } | ||
2710 | 920 | return; | ||
2711 | 921 | } | ||
2712 | 922 | } | ||
2713 | 923 | } | ||
2714 | 924 | |||
2715 | 925 | } | ||
2716 | 0 | 926 | ||
2717 | === added file 'src/logic/garrisonhandler.h' | |||
2718 | --- src/logic/garrisonhandler.h 1970-01-01 00:00:00 +0000 | |||
2719 | +++ src/logic/garrisonhandler.h 2013-08-10 10:53:03 +0000 | |||
2720 | @@ -0,0 +1,262 @@ | |||
2721 | 1 | /* | ||
2722 | 2 | * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team | ||
2723 | 3 | * | ||
2724 | 4 | * This program is free software; you can redistribute it and/or | ||
2725 | 5 | * modify it under the terms of the GNU General Public License | ||
2726 | 6 | * as published by the Free Software Foundation; either version 2 | ||
2727 | 7 | * of the License, or (at your option) any later version. | ||
2728 | 8 | * | ||
2729 | 9 | * This program is distributed in the hope that it will be useful, | ||
2730 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2731 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2732 | 12 | * GNU General Public License for more details. | ||
2733 | 13 | * | ||
2734 | 14 | * You should have received a copy of the GNU General Public License | ||
2735 | 15 | * along with this program; if not, write to the Free Software | ||
2736 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
2737 | 17 | * | ||
2738 | 18 | */ | ||
2739 | 19 | |||
2740 | 20 | #ifndef GARRISON_HANDLER_H | ||
2741 | 21 | #define GARRISON_HANDLER_H | ||
2742 | 22 | |||
2743 | 23 | #include "logic/instances.h" | ||
2744 | 24 | #include "logic/garrison.h" | ||
2745 | 25 | #include "logic/requirements.h" | ||
2746 | 26 | #include "logic/worker.h" | ||
2747 | 27 | |||
2748 | 28 | namespace Widelands { | ||
2749 | 29 | |||
2750 | 30 | struct Building; | ||
2751 | 31 | struct Request; | ||
2752 | 32 | class Soldier; | ||
2753 | 33 | |||
2754 | 34 | #define GARRISON_SWAP_TIMEOUT 20000 | ||
2755 | 35 | /** | ||
2756 | 36 | * Implementation of the Garrison interface to used by GarrisonOwner. | ||
2757 | 37 | */ | ||
2758 | 38 | class GarrisonHandler : public Garrison { | ||
2759 | 39 | friend struct Map_Buildingdata_Data_Packet; | ||
2760 | 40 | public: | ||
2761 | 41 | /** | ||
2762 | 42 | * Create a new garrison handler | ||
2763 | 43 | * \param building The building that holds this garrison. Must implements GarrisonOwner | ||
2764 | 44 | * \param min_soldiers The minimum soldiers to be present in the garrison | ||
2765 | 45 | * \param max_soldiers The maximum soldiers that can be present in this garrison | ||
2766 | 46 | * \param conquer_radius The radius of the area conqered by this garrison | ||
2767 | 47 | * \param heal_per_second The speed at which soldiers will be healed | ||
2768 | 48 | * \param soldier_pref The soldier preference for rookies or heroes | ||
2769 | 49 | * \param passive A passive garrison is only helpful to keep some soldiers around. It can't | ||
2770 | 50 | * attack nor be attacked. I think of training site or ships | ||
2771 | 51 | */ | ||
2772 | 52 | GarrisonHandler | ||
2773 | 53 | (Building& building, uint32_t min_soldiers, uint32_t max_soldiers, | ||
2774 | 54 | uint32_t conquer_radius, uint32_t heal_per_second, SoldierPref soldier_pref, | ||
2775 | 55 | bool passive = false); | ||
2776 | 56 | virtual ~GarrisonHandler(); | ||
2777 | 57 | |||
2778 | 58 | void load_finish(Editor_Game_Base &); | ||
2779 | 59 | /** | ||
2780 | 60 | * Must be called once | ||
2781 | 61 | */ | ||
2782 | 62 | void init(Editor_Game_Base &); | ||
2783 | 63 | /** | ||
2784 | 64 | * Must be called once after conqueral | ||
2785 | 65 | */ | ||
2786 | 66 | void reinit_after_conqueral(Game & game); | ||
2787 | 67 | /** | ||
2788 | 68 | * Cleanup handled objects | ||
2789 | 69 | */ | ||
2790 | 70 | void cleanup(Editor_Game_Base &); | ||
2791 | 71 | /** | ||
2792 | 72 | * Eequests must be cleaned up after the building has | ||
2793 | 73 | * been cleaned up, hence this seperate function. | ||
2794 | 74 | */ | ||
2795 | 75 | void cleanup_requests(Editor_Game_Base &); | ||
2796 | 76 | /** | ||
2797 | 77 | * Must be called regularly. It is not time dependant though. | ||
2798 | 78 | * \Return the time when the next act should occur | ||
2799 | 79 | */ | ||
2800 | 80 | int32_t act(Game &); | ||
2801 | 81 | /** | ||
2802 | 82 | * Must be called when the owner building changes economy | ||
2803 | 83 | */ | ||
2804 | 84 | void set_economy(Economy * const e); | ||
2805 | 85 | /** | ||
2806 | 86 | * Pop the given soldier out of the building, while keeping it | ||
2807 | 87 | * in the garrion. | ||
2808 | 88 | */ | ||
2809 | 89 | void popSoldier(Soldier* soldier); | ||
2810 | 90 | /** | ||
2811 | 91 | * Get some work for a soldier that asks for it | ||
2812 | 92 | */ | ||
2813 | 93 | bool get_garrison_work(Game & game, Soldier* soldier); | ||
2814 | 94 | /** | ||
2815 | 95 | * Set the requirements for that soldier. This will be used when filling | ||
2816 | 96 | * request for soldiers. | ||
2817 | 97 | */ | ||
2818 | 98 | void set_soldier_requirements(Requirements req); | ||
2819 | 99 | |||
2820 | 100 | // Garrison implementation | ||
2821 | 101 | virtual Player & owner() const; | ||
2822 | 102 | virtual bool canAttack() const; | ||
2823 | 103 | virtual void aggressor(Soldier &); | ||
2824 | 104 | virtual bool attack(Soldier &); | ||
2825 | 105 | virtual bool is_passive(); | ||
2826 | 106 | virtual Building& get_building(); | ||
2827 | 107 | virtual const std::vector<Soldier *> presentSoldiers() const; | ||
2828 | 108 | virtual const std::vector<Soldier *> stationedSoldiers() const; | ||
2829 | 109 | virtual uint32_t minSoldierCapacity() const; | ||
2830 | 110 | virtual uint32_t maxSoldierCapacity() const; | ||
2831 | 111 | virtual uint32_t soldierCapacity() const; | ||
2832 | 112 | virtual void setSoldierCapacity(uint32_t capacity); | ||
2833 | 113 | virtual void dropSoldier(Soldier &); | ||
2834 | 114 | virtual int incorporateSoldier(Editor_Game_Base &, Soldier &); | ||
2835 | 115 | virtual int outcorporateSoldier(Editor_Game_Base &, Soldier &); | ||
2836 | 116 | virtual uint32_t conquerRadius() const; | ||
2837 | 117 | virtual void set_soldier_preference(SoldierPref p); | ||
2838 | 118 | virtual SoldierPref get_soldier_preference() const { | ||
2839 | 119 | return m_soldier_preference; | ||
2840 | 120 | } | ||
2841 | 121 | virtual void sendAttacker(Soldier & soldier, Building & target, uint8_t retreat); | ||
2842 | 122 | |||
2843 | 123 | |||
2844 | 124 | private: | ||
2845 | 125 | enum class InfoType : uint8_t { | ||
2846 | 126 | AGGRESSSED, | ||
2847 | 127 | UNDER_ATTACK, | ||
2848 | 128 | GARRISON_LOST, | ||
2849 | 129 | GARRISON_CAPTURED, | ||
2850 | 130 | GARRISON_OCCUPIED | ||
2851 | 131 | }; | ||
2852 | 132 | // Helper methods | ||
2853 | 133 | /** | ||
2854 | 134 | * Sends a message to the owner | ||
2855 | 135 | */ | ||
2856 | 136 | void inform_owner(Game&, InfoType); | ||
2857 | 137 | /** | ||
2858 | 138 | * Check if a soldier is actually present in building | ||
2859 | 139 | */ | ||
2860 | 140 | bool isPresent(Soldier &) const; | ||
2861 | 141 | /** | ||
2862 | 142 | * Conquers the area once a soldier occupied the site | ||
2863 | 143 | */ | ||
2864 | 144 | void conquer_area(Editor_Game_Base &); | ||
2865 | 145 | /** | ||
2866 | 146 | * Check if we keep military influence once our garrison | ||
2867 | 147 | * has been conquered | ||
2868 | 148 | */ | ||
2869 | 149 | bool military_presence_kept(Game &); | ||
2870 | 150 | /** | ||
2871 | 151 | * Update the soldier requests. If upgraded_incorporated, a soldier | ||
2872 | 152 | * requested by an upgrade request has just been incorporated. This | ||
2873 | 153 | * method handle requesting for normal case (filling slots) or for | ||
2874 | 154 | * upgrading to a better suited soldier | ||
2875 | 155 | */ | ||
2876 | 156 | void update_soldier_request(bool upgraded_incorporated = false); | ||
2877 | 157 | /** | ||
2878 | 158 | * Request new soldiers or evict some to fill the capacity | ||
2879 | 159 | */ | ||
2880 | 160 | void update_normal_soldier_request(); | ||
2881 | 161 | /* There are two kinds of soldier requests: "normal", which is used whenever the military site needs | ||
2882 | 162 | * more soldiers, and "upgrade" which is used when there is a preference for either heroes or | ||
2883 | 163 | * rookies. | ||
2884 | 164 | * | ||
2885 | 165 | * In case of normal requests, the military site is filled. In case of upgrade requests, only one guy | ||
2886 | 166 | * is exchanged at a time. | ||
2887 | 167 | * | ||
2888 | 168 | * There would be more efficient ways to get well trained soldiers. Now, new buildings appearing in battle | ||
2889 | 169 | * field are more vulnerable at the beginning. This is intentional. The purpose of this upgrade thing is | ||
2890 | 170 | * to reduce the benefits of site micromanagement. The intention is not to make gameplay easier | ||
2891 | 171 | * in other ways. | ||
2892 | 172 | */ | ||
2893 | 173 | void update_upgrade_soldier_request(); | ||
2894 | 174 | /** | ||
2895 | 175 | * The callback function, called whenever one of our soldier requested arrived | ||
2896 | 176 | */ | ||
2897 | 177 | static void request_soldier_callback | ||
2898 | 178 | (Game &, Request &, Ware_Index, Worker *, PlayerImmovable &); | ||
2899 | 179 | /** | ||
2900 | 180 | * The transfer callback function, called whenever one of our requested | ||
2901 | 181 | * soldier started to move towards the garrison | ||
2902 | 182 | */ | ||
2903 | 183 | static void request_soldier_transfer_callback | ||
2904 | 184 | (Game &, Request &, Ware_Index, Worker *, PlayerImmovable &); | ||
2905 | 185 | /* | ||
2906 | 186 | * When upgrading soldiers, we do not ask for just any soldiers, but soldiers | ||
2907 | 187 | * that are better than what we already have. This routine sets the requirements | ||
2908 | 188 | * used by the request. | ||
2909 | 189 | * | ||
2910 | 190 | * The routine returns true if upgrade request thresholds have changed. This information could be | ||
2911 | 191 | * used to decide whether the soldier-Request should be upgraded. Additionally, the m_try_soldier_upgrade | ||
2912 | 192 | * field will be set so to know if an attempt to get better soldier sould be performed. | ||
2913 | 193 | */ | ||
2914 | 194 | bool update_upgrade_requirements(); | ||
2915 | 195 | /** | ||
2916 | 196 | * Called when an upgraded soldier comes to join the garrison | ||
2917 | 197 | */ | ||
2918 | 198 | bool incorporateUpgradedSoldier(Editor_Game_Base & game, Soldier & s); | ||
2919 | 199 | /** | ||
2920 | 200 | * Find the least suited soldier for this garrison. We don't play | ||
2921 | 201 | * in the same league | ||
2922 | 202 | */ | ||
2923 | 203 | Soldier * find_least_suited_soldier(); | ||
2924 | 204 | /** | ||
2925 | 205 | * Try to drop the lease suited soldier, return true on success. | ||
2926 | 206 | * If a new soldier s has arrived, extra care will be taken to not drop | ||
2927 | 207 | * anyone if the new one is even worst | ||
2928 | 208 | */ | ||
2929 | 209 | bool drop_least_suited_soldier(Soldier * s = nullptr); | ||
2930 | 210 | /** | ||
2931 | 211 | * Return true if we hold a running job for that soldied | ||
2932 | 212 | */ | ||
2933 | 213 | bool haveSoldierJob(Soldier &) const; | ||
2934 | 214 | /** | ||
2935 | 215 | * \return the enemy, if any, that the given soldier was scheduled | ||
2936 | 216 | * to attack, and remove the job. | ||
2937 | 217 | */ | ||
2938 | 218 | Map_Object * popSoldierJob(Soldier *, bool * stayhome = 0, uint8_t * retreat = 0); | ||
2939 | 219 | |||
2940 | 220 | void evict_soldier(Game&, Soldier*); | ||
2941 | 221 | |||
2942 | 222 | // Basic fields | ||
2943 | 223 | Building& m_building; | ||
2944 | 224 | uint32_t m_min_capacity; | ||
2945 | 225 | uint32_t m_max_capacity; | ||
2946 | 226 | uint32_t m_capacity; | ||
2947 | 227 | bool m_passive; | ||
2948 | 228 | std::vector<Soldier*> m_soldiers; | ||
2949 | 229 | |||
2950 | 230 | // Healing | ||
2951 | 231 | uint32_t m_heal_per_second; | ||
2952 | 232 | uint32_t m_last_heal_time; | ||
2953 | 233 | |||
2954 | 234 | // Requests | ||
2955 | 235 | Requirements m_soldier_requirements; // This is used to grab a bunch of soldiers: Anything goes | ||
2956 | 236 | RequireAttribute m_soldier_upgrade_requirements; // This is used when exchanging soldiers. | ||
2957 | 237 | std::unique_ptr<Request> m_normal_soldier_request; // filling the site | ||
2958 | 238 | std::unique_ptr<Request> m_upgrade_soldier_request; // seeking for better soldiers | ||
2959 | 239 | |||
2960 | 240 | // Conqueral | ||
2961 | 241 | uint32_t m_conquer_radius; | ||
2962 | 242 | bool m_didconquer; | ||
2963 | 243 | |||
2964 | 244 | // Job | ||
2965 | 245 | struct SoldierJob { | ||
2966 | 246 | Soldier * soldier; | ||
2967 | 247 | Object_Ptr enemy; | ||
2968 | 248 | bool stayhome; | ||
2969 | 249 | uint8_t retreat; | ||
2970 | 250 | }; | ||
2971 | 251 | std::vector<SoldierJob> m_soldierjobs; | ||
2972 | 252 | |||
2973 | 253 | // Soldier preferences | ||
2974 | 254 | SoldierPref m_soldier_preference; | ||
2975 | 255 | uint32_t m_last_swap_soldiers_time; | ||
2976 | 256 | bool m_try_soldier_upgrade; // optimization -- if everybody is zero-level, do not downgrade | ||
2977 | 257 | bool m_doing_upgrade_request; | ||
2978 | 258 | }; | ||
2979 | 259 | |||
2980 | 260 | } | ||
2981 | 261 | |||
2982 | 262 | #endif | ||
2983 | 0 | 263 | ||
2984 | === modified file 'src/logic/item_ware_descr.h' | |||
2985 | --- src/logic/item_ware_descr.h 2013-07-26 20:19:36 +0000 | |||
2986 | +++ src/logic/item_ware_descr.h 2013-08-10 10:53:03 +0000 | |||
2987 | @@ -41,7 +41,7 @@ | |||
2988 | 41 | namespace Widelands { | 41 | namespace Widelands { |
2989 | 42 | 42 | ||
2990 | 43 | /** | 43 | /** |
2992 | 44 | * Wares can be stored in warehouses. They can be transferred across an | 44 | * Wares can be stored in storages. They can be transferred across an |
2993 | 45 | * Economy. They can be traded. | 45 | * Economy. They can be traded. |
2994 | 46 | * Both items (lumber, stone, ...) and workers are considered wares. | 46 | * Both items (lumber, stone, ...) and workers are considered wares. |
2995 | 47 | * Every ware has a unique name. Note that an item must not have the same | 47 | * Every ware has a unique name. Note that an item must not have the same |
2996 | @@ -75,7 +75,7 @@ | |||
2997 | 75 | /// \return ware's localized descriptive text | 75 | /// \return ware's localized descriptive text |
2998 | 76 | const std::string & helptext() const throw () {return m_helptext;} | 76 | const std::string & helptext() const throw () {return m_helptext;} |
2999 | 77 | 77 | ||
3001 | 78 | /// How much of the ware type that an economy should store in warehouses. | 78 | /// How much of the ware type that an economy should store in storages. |
3002 | 79 | /// The special value std::numeric_limits<uint32_t>::max() means that the | 79 | /// The special value std::numeric_limits<uint32_t>::max() means that the |
3003 | 80 | /// the target quantity of this ware type will never be checked and should | 80 | /// the target quantity of this ware type will never be checked and should |
3004 | 81 | /// not be configurable. | 81 | /// not be configurable. |
3005 | 82 | 82 | ||
3006 | === modified file 'src/logic/militarysite.cc' | |||
3007 | --- src/logic/militarysite.cc 2013-08-08 19:55:12 +0000 | |||
3008 | +++ src/logic/militarysite.cc 2013-08-10 10:53:03 +0000 | |||
3009 | @@ -21,8 +21,10 @@ | |||
3010 | 21 | 21 | ||
3011 | 22 | #include <clocale> | 22 | #include <clocale> |
3012 | 23 | #include <cstdio> | 23 | #include <cstdio> |
3013 | 24 | #include <memory> | ||
3014 | 24 | 25 | ||
3015 | 25 | #include <boost/foreach.hpp> | 26 | #include <boost/foreach.hpp> |
3016 | 27 | #include <boost/format.hpp> | ||
3017 | 26 | #include <libintl.h> | 28 | #include <libintl.h> |
3018 | 27 | 29 | ||
3019 | 28 | #include "economy/flag.h" | 30 | #include "economy/flag.h" |
3020 | @@ -33,6 +35,7 @@ | |||
3021 | 33 | #include "logic/editor_game_base.h" | 35 | #include "logic/editor_game_base.h" |
3022 | 34 | #include "logic/findbob.h" | 36 | #include "logic/findbob.h" |
3023 | 35 | #include "logic/game.h" | 37 | #include "logic/game.h" |
3024 | 38 | #include "logic/garrisonhandler.h" | ||
3025 | 36 | #include "logic/message_queue.h" | 39 | #include "logic/message_queue.h" |
3026 | 37 | #include "logic/player.h" | 40 | #include "logic/player.h" |
3027 | 38 | #include "logic/soldier.h" | 41 | #include "logic/soldier.h" |
3028 | @@ -55,13 +58,13 @@ | |||
3029 | 55 | m_num_soldiers (0), | 58 | m_num_soldiers (0), |
3030 | 56 | m_heal_per_second (0) | 59 | m_heal_per_second (0) |
3031 | 57 | { | 60 | { |
3035 | 58 | m_conquer_radius = global_s.get_safe_int("conquers"); | 61 | Section& garrison_s = prof.get_safe_section("garrison"); |
3036 | 59 | m_num_soldiers = global_s.get_safe_int("max_soldiers"); | 62 | m_conquer_radius = garrison_s.get_safe_int("conquers"); |
3037 | 60 | m_heal_per_second = global_s.get_safe_int("heal_per_second"); | 63 | m_num_soldiers = garrison_s.get_safe_int("max_soldiers"); |
3038 | 64 | m_heal_per_second = garrison_s.get_safe_int("heal_per_second"); | ||
3039 | 61 | if (m_conquer_radius > 0) | 65 | if (m_conquer_radius > 0) |
3040 | 62 | m_workarea_info[m_conquer_radius].insert(descname() + _(" conquer")); | 66 | m_workarea_info[m_conquer_radius].insert(descname() + _(" conquer")); |
3043 | 63 | m_prefers_heroes_at_start = global_s.get_safe_bool("prefer_heroes"); | 67 | m_prefers_heroes_at_start = garrison_s.get_safe_bool("prefer_heroes"); |
3042 | 64 | |||
3044 | 65 | } | 68 | } |
3045 | 66 | 69 | ||
3046 | 67 | /** | 70 | /** |
3047 | @@ -83,96 +86,45 @@ | |||
3048 | 83 | */ | 86 | */ |
3049 | 84 | 87 | ||
3050 | 85 | MilitarySite::MilitarySite(const MilitarySite_Descr & ms_descr) : | 88 | MilitarySite::MilitarySite(const MilitarySite_Descr & ms_descr) : |
3057 | 86 | ProductionSite(ms_descr), | 89 | ProductionSite(ms_descr) |
3052 | 87 | m_didconquer (false), | ||
3053 | 88 | m_capacity (ms_descr.get_max_number_of_soldiers()), | ||
3054 | 89 | m_nexthealtime(0), | ||
3055 | 90 | m_soldier_preference(ms_descr.m_prefers_heroes_at_start ? kPrefersHeroes : kPrefersRookies), | ||
3056 | 91 | m_soldier_upgrade_try(false) | ||
3058 | 92 | { | 90 | { |
3060 | 93 | m_next_swap_soldiers_time = 0; | 91 | GarrisonHandler* gh = new GarrisonHandler |
3061 | 92 | (*this, 1, | ||
3062 | 93 | descr().get_max_number_of_soldiers(), | ||
3063 | 94 | descr().get_conquers(), descr().get_heal_per_second(), | ||
3064 | 95 | descr().m_prefers_heroes_at_start ? GarrisonHandler::SoldierPref::Heroes | ||
3065 | 96 | : GarrisonHandler::SoldierPref::Rookies); | ||
3066 | 97 | m_garrison.reset(gh); | ||
3067 | 94 | } | 98 | } |
3068 | 95 | 99 | ||
3069 | 96 | |||
3070 | 97 | MilitarySite::~MilitarySite() | 100 | MilitarySite::~MilitarySite() |
3071 | 98 | { | 101 | { |
3072 | 99 | assert(!m_normal_soldier_request); | ||
3073 | 100 | assert(!m_upgrade_soldier_request); | ||
3074 | 101 | } | 102 | } |
3075 | 102 | 103 | ||
3083 | 103 | 104 | void MilitarySite::load_finish(Editor_Game_Base& egbase) | |
3077 | 104 | /** | ||
3078 | 105 | =============== | ||
3079 | 106 | Display number of soldiers. | ||
3080 | 107 | =============== | ||
3081 | 108 | */ | ||
3082 | 109 | std::string MilitarySite::get_statistics_string() | ||
3084 | 110 | { | 105 | { |
3109 | 111 | char buffer[255]; | 106 | Widelands::Building::load_finish(egbase); |
3110 | 112 | std::string str; | 107 | m_garrison->load_finish(egbase); |
3087 | 113 | uint32_t present = presentSoldiers().size(); | ||
3088 | 114 | uint32_t total = stationedSoldiers().size(); | ||
3089 | 115 | |||
3090 | 116 | if (present == total) { | ||
3091 | 117 | snprintf | ||
3092 | 118 | (buffer, sizeof(buffer), | ||
3093 | 119 | ngettext("%u soldier", "%u soldiers", total), | ||
3094 | 120 | total); | ||
3095 | 121 | } else { | ||
3096 | 122 | snprintf | ||
3097 | 123 | (buffer, sizeof(buffer), | ||
3098 | 124 | ngettext("%u(+%u) soldier", "%u(+%u) soldiers", total), | ||
3099 | 125 | present, total - present); | ||
3100 | 126 | } | ||
3101 | 127 | str = buffer; | ||
3102 | 128 | |||
3103 | 129 | if (m_capacity > total) { | ||
3104 | 130 | snprintf(buffer, sizeof(buffer), " (+%u)", m_capacity - total); | ||
3105 | 131 | str += buffer; | ||
3106 | 132 | } | ||
3107 | 133 | |||
3108 | 134 | return str; | ||
3111 | 135 | } | 108 | } |
3112 | 136 | 109 | ||
3113 | 137 | |||
3114 | 138 | void MilitarySite::init(Editor_Game_Base & egbase) | 110 | void MilitarySite::init(Editor_Game_Base & egbase) |
3115 | 139 | { | 111 | { |
3116 | 140 | ProductionSite::init(egbase); | 112 | ProductionSite::init(egbase); |
3118 | 141 | 113 | m_garrison->init(egbase); | |
3119 | 142 | upcast(Game, game, &egbase); | 114 | upcast(Game, game, &egbase); |
3120 | 143 | 115 | ||
3121 | 144 | const std::vector<Worker*>& ws = get_workers(); | 116 | const std::vector<Worker*>& ws = get_workers(); |
3123 | 145 | container_iterate_const(std::vector<Worker *>, ws, i) | 117 | container_iterate_const(std::vector<Worker *>, ws, i) { |
3124 | 146 | if (upcast(Soldier, soldier, *i.current)) { | 118 | if (upcast(Soldier, soldier, *i.current)) { |
3125 | 147 | soldier->set_location_initially(*this); | 119 | soldier->set_location_initially(*this); |
3129 | 148 | assert(!soldier->get_state()); // Should be newly created. | 120 | m_garrison->incorporateSoldier(egbase, *soldier); |
3127 | 149 | if (game) | ||
3128 | 150 | soldier->start_task_buildingwork(*game); | ||
3130 | 151 | } | 121 | } |
3136 | 152 | update_soldier_request(); | 122 | } |
3137 | 153 | 123 | if (game) { | |
3133 | 154 | // schedule the first healing | ||
3134 | 155 | m_nexthealtime = egbase.get_gametime() + 1000; | ||
3135 | 156 | if (game) | ||
3138 | 157 | schedule_act(*game, 1000); | 124 | schedule_act(*game, 1000); |
3157 | 158 | } | 125 | } |
3158 | 159 | 126 | } | |
3159 | 160 | 127 | ||
3142 | 161 | /** | ||
3143 | 162 | =============== | ||
3144 | 163 | Change the economy for the wares queues. | ||
3145 | 164 | Note that the workers are dealt with in the PlayerImmovable code. | ||
3146 | 165 | =============== | ||
3147 | 166 | */ | ||
3148 | 167 | void MilitarySite::set_economy(Economy * const e) | ||
3149 | 168 | { | ||
3150 | 169 | ProductionSite::set_economy(e); | ||
3151 | 170 | |||
3152 | 171 | if (m_normal_soldier_request && e) | ||
3153 | 172 | m_normal_soldier_request->set_economy(e); | ||
3154 | 173 | if (m_upgrade_soldier_request && e) | ||
3155 | 174 | m_upgrade_soldier_request->set_economy(e); | ||
3156 | 175 | } | ||
3160 | 176 | 128 | ||
3161 | 177 | /** | 129 | /** |
3162 | 178 | =============== | 130 | =============== |
3163 | @@ -181,16 +133,12 @@ | |||
3164 | 181 | */ | 133 | */ |
3165 | 182 | void MilitarySite::cleanup(Editor_Game_Base & egbase) | 134 | void MilitarySite::cleanup(Editor_Game_Base & egbase) |
3166 | 183 | { | 135 | { |
3176 | 184 | // unconquer land | 136 | // Order matters. Building needed to unconquer, building |
3177 | 185 | if (m_didconquer) | 137 | // cleanup will trigger new requests in garrison, garrison |
3178 | 186 | egbase.unconquer_area | 138 | // cleanup will destroy them |
3179 | 187 | (Player_Area<Area<FCoords> > | 139 | m_garrison->cleanup(egbase); |
3171 | 188 | (owner().player_number(), | ||
3172 | 189 | Area<FCoords> | ||
3173 | 190 | (egbase.map().get_fcoords(get_position()), get_conquers())), | ||
3174 | 191 | m_defeating_player); | ||
3175 | 192 | |||
3180 | 193 | ProductionSite::cleanup(egbase); | 140 | ProductionSite::cleanup(egbase); |
3181 | 141 | <<<<<<< TREE | ||
3182 | 194 | 142 | ||
3183 | 195 | // Note that removing workers during ProductionSite::cleanup can generate | 143 | // Note that removing workers during ProductionSite::cleanup can generate |
3184 | 196 | // new requests; that's why we delete it at the end of this function. | 144 | // new requests; that's why we delete it at the end of this function. |
3185 | @@ -538,6 +486,9 @@ | |||
3186 | 538 | // reason, hoping that all stationed soldiers would be present. | 486 | // reason, hoping that all stationed soldiers would be present. |
3187 | 539 | } | 487 | } |
3188 | 540 | } | 488 | } |
3189 | 489 | ======= | ||
3190 | 490 | m_garrison->cleanup_requests(egbase); | ||
3191 | 491 | >>>>>>> MERGE-SOURCE | ||
3192 | 541 | } | 492 | } |
3193 | 542 | 493 | ||
3194 | 543 | /* | 494 | /* |
3195 | @@ -554,60 +505,53 @@ | |||
3196 | 554 | // Maybe a new queueing system like MilitaryAct could be introduced. | 505 | // Maybe a new queueing system like MilitaryAct could be introduced. |
3197 | 555 | 506 | ||
3198 | 556 | ProductionSite::act(game, data); | 507 | ProductionSite::act(game, data); |
3253 | 557 | 508 | m_garrison->act(game); | |
3254 | 558 | const int32_t timeofgame = game.get_gametime(); | 509 | schedule_act(game, 1000); |
3255 | 559 | if (m_normal_soldier_request && m_upgrade_soldier_request) | 510 | } |
3256 | 560 | { | 511 | |
3257 | 561 | throw wexception("MilitarySite::act: Two soldier requests are ongoing -- should never happen!\n"); | 512 | /** |
3258 | 562 | } | 513 | =============== |
3259 | 563 | 514 | Display number of soldiers. | |
3260 | 564 | // I do not get a callback when stationed, non-present soldier returns -- | 515 | =============== |
3261 | 565 | // Therefore I must poll in some occasions. Let's do that rather infrequently, | 516 | */ |
3262 | 566 | // to keep the game lightweight. | 517 | std::string MilitarySite::get_statistics_string() |
3263 | 567 | 518 | { | |
3264 | 568 | //TODO: I would need two new callbacks, to get rid ot this polling. | 519 | std::string str; |
3265 | 569 | if (timeofgame > m_next_swap_soldiers_time) | 520 | uint32_t present = m_garrison->presentSoldiers().size(); |
3266 | 570 | { | 521 | uint32_t total = m_garrison->stationedSoldiers().size(); |
3267 | 571 | m_next_swap_soldiers_time = timeofgame + (m_soldier_upgrade_try ? 20000 : 100000); | 522 | uint32_t capacity = m_garrison->soldierCapacity(); |
3268 | 572 | update_soldier_request(); | 523 | |
3269 | 573 | } | 524 | if (present == total) { |
3270 | 574 | 525 | str = | |
3271 | 575 | if (m_nexthealtime <= game.get_gametime()) { | 526 | (boost::format |
3272 | 576 | uint32_t total_heal = descr().get_heal_per_second(); | 527 | (ngettext(_("%u soldier"), _("%u soldiers"), total)) % total) |
3273 | 577 | std::vector<Soldier *> soldiers = presentSoldiers(); | 528 | .str(); |
3274 | 578 | 529 | } else { | |
3275 | 579 | for (uint32_t i = 0; i < soldiers.size(); ++i) { | 530 | str = |
3276 | 580 | Soldier & s = *soldiers[i]; | 531 | (boost::format |
3277 | 581 | 532 | (ngettext(_("%u(+%u) soldier"), _("%u(+%u) soldiers"), present)) | |
3278 | 582 | // The healing algorithm is totally arbitrary | 533 | % present % (total - present)) |
3279 | 583 | if (s.get_current_hitpoints() < s.get_max_hitpoints()) { | 534 | .str(); |
3280 | 584 | s.heal(total_heal); | 535 | } |
3281 | 585 | break; | 536 | |
3282 | 586 | } | 537 | if (capacity > total) { |
3283 | 587 | } | 538 | str += (boost::format(" (+%u)") % (capacity - total)).str(); |
3284 | 588 | 539 | } | |
3285 | 589 | m_nexthealtime = game.get_gametime() + 1000; | 540 | |
3286 | 590 | schedule_act(game, 1000); | 541 | return str; |
3287 | 591 | } | 542 | } |
3288 | 592 | } | 543 | |
3289 | 593 | 544 | /** | |
3290 | 594 | 545 | =============== | |
3291 | 595 | /** | 546 | Change the economy for the wares queues. |
3292 | 596 | * The worker is about to be removed. | 547 | Note that the workers are dealt with in the PlayerImmovable code. |
3293 | 597 | * | 548 | =============== |
3294 | 598 | * After the removal of the worker, check whether we need to request | 549 | */ |
3295 | 599 | * new soldiers. | 550 | void MilitarySite::set_economy(Economy * const e) |
3296 | 600 | */ | 551 | { |
3297 | 601 | void MilitarySite::remove_worker(Worker & w) | 552 | ProductionSite::set_economy(e); |
3298 | 602 | { | 553 | m_garrison->set_economy(e); |
3299 | 603 | ProductionSite::remove_worker(w); | 554 | } |
3246 | 604 | |||
3247 | 605 | if (upcast(Soldier, soldier, &w)) | ||
3248 | 606 | popSoldierJob(soldier, 0, 0); | ||
3249 | 607 | |||
3250 | 608 | update_soldier_request(); | ||
3251 | 609 | } | ||
3252 | 610 | |||
3300 | 611 | 555 | ||
3301 | 612 | /** | 556 | /** |
3302 | 613 | * Called by soldiers in the building. | 557 | * Called by soldiers in the building. |
3303 | @@ -615,41 +559,13 @@ | |||
3304 | 615 | bool MilitarySite::get_building_work(Game & game, Worker & worker, bool) | 559 | bool MilitarySite::get_building_work(Game & game, Worker & worker, bool) |
3305 | 616 | { | 560 | { |
3306 | 617 | if (upcast(Soldier, soldier, &worker)) { | 561 | if (upcast(Soldier, soldier, &worker)) { |
3336 | 618 | // Evict soldiers that have returned home if the capacity is too low | 562 | return m_garrison->get_garrison_work(game, soldier); |
3308 | 619 | if (m_capacity < presentSoldiers().size()) { | ||
3309 | 620 | worker.reset_tasks(game); | ||
3310 | 621 | worker.start_task_leavebuilding(game, true); | ||
3311 | 622 | return true; | ||
3312 | 623 | } | ||
3313 | 624 | |||
3314 | 625 | bool stayhome; | ||
3315 | 626 | uint8_t retreat; | ||
3316 | 627 | if | ||
3317 | 628 | (Map_Object * const enemy | ||
3318 | 629 | = | ||
3319 | 630 | popSoldierJob(soldier, &stayhome, &retreat)) | ||
3320 | 631 | { | ||
3321 | 632 | if (upcast(Building, building, enemy)) { | ||
3322 | 633 | soldier->start_task_attack | ||
3323 | 634 | (game, *building, retreat); | ||
3324 | 635 | return true; | ||
3325 | 636 | } else if (upcast(Soldier, opponent, enemy)) { | ||
3326 | 637 | if (!opponent->getBattle()) { | ||
3327 | 638 | soldier->start_task_defense | ||
3328 | 639 | (game, stayhome, retreat); | ||
3329 | 640 | if (stayhome) | ||
3330 | 641 | opponent->send_signal(game, "sleep"); | ||
3331 | 642 | return true; | ||
3332 | 643 | } | ||
3333 | 644 | } else | ||
3334 | 645 | throw wexception("MilitarySite::get_building_work: bad SoldierJob"); | ||
3335 | 646 | } | ||
3337 | 647 | } | 563 | } |
3338 | 648 | |||
3339 | 649 | return false; | 564 | return false; |
3340 | 650 | } | 565 | } |
3341 | 651 | 566 | ||
3342 | 652 | 567 | ||
3343 | 568 | <<<<<<< TREE | ||
3344 | 653 | /** | 569 | /** |
3345 | 654 | * \return \c true if the soldier is currently present and idle in the building. | 570 | * \return \c true if the soldier is currently present and idle in the building. |
3346 | 655 | */ | 571 | */ |
3347 | @@ -885,7 +801,28 @@ | |||
3348 | 885 | 801 | ||
3349 | 886 | // Now we destroy the old building before we place the new one. | 802 | // Now we destroy the old building before we place the new one. |
3350 | 887 | set_defeating_player(enemy.owner().player_number()); | 803 | set_defeating_player(enemy.owner().player_number()); |
3351 | 804 | ======= | ||
3352 | 805 | Garrison* MilitarySite::get_garrison() const | ||
3353 | 806 | { | ||
3354 | 807 | return m_garrison.get(); | ||
3355 | 808 | } | ||
3356 | 809 | |||
3357 | 810 | Building* MilitarySite::get_building() | ||
3358 | 811 | { | ||
3359 | 812 | return this; | ||
3360 | 813 | } | ||
3361 | 814 | |||
3362 | 815 | void MilitarySite::garrison_occupied() | ||
3363 | 816 | { | ||
3364 | 817 | start_animation(owner().egbase(), descr().get_animation("idle")); | ||
3365 | 818 | } | ||
3366 | 819 | |||
3367 | 820 | void MilitarySite::garrison_lost(Game& game, Widelands::Player_Number defeating, bool captured) | ||
3368 | 821 | { | ||
3369 | 822 | if (!captured) { | ||
3370 | 823 | >>>>>>> MERGE-SOURCE | ||
3371 | 888 | schedule_destroy(game); | 824 | schedule_destroy(game); |
3372 | 825 | <<<<<<< TREE | ||
3373 | 889 | 826 | ||
3374 | 890 | enemyplayer->force_building(coords, former_buildings); | 827 | enemyplayer->force_building(coords, former_buildings); |
3375 | 891 | BaseImmovable * const newimm = game.map()[coords].get_immovable(); | 828 | BaseImmovable * const newimm = game.map()[coords].get_immovable(); |
3376 | @@ -907,17 +844,64 @@ | |||
3377 | 907 | 844 | ||
3378 | 908 | return false; | 845 | return false; |
3379 | 909 | } | 846 | } |
3380 | 847 | ======= | ||
3381 | 848 | return; | ||
3382 | 849 | } | ||
3383 | 850 | // The enemy conquers the building | ||
3384 | 851 | // In fact we do not conquer it, but place a new building of same type at | ||
3385 | 852 | // the old location. | ||
3386 | 853 | Player * enemyplayer = game.get_player(defeating); | ||
3387 | 854 | const Tribe_Descr & enemytribe = enemyplayer->tribe(); | ||
3388 | 855 | |||
3389 | 856 | // Add suffix to all descr in former buildings in cases | ||
3390 | 857 | // the new owner comes from another tribe | ||
3391 | 858 | Building_Descr::FormerBuildings former_buildings; | ||
3392 | 859 | BOOST_FOREACH(const Building_Descr * old_descr, m_old_buildings) { | ||
3393 | 860 | std::string bldname = old_descr->name(); | ||
3394 | 861 | // Has this building already a suffix? == conquered building? | ||
3395 | 862 | std::string::size_type const dot = bldname.rfind('.'); | ||
3396 | 863 | if (dot >= bldname.size()) { | ||
3397 | 864 | // Add suffix, if the new owner uses another tribe than we. | ||
3398 | 865 | if (enemytribe.name() != owner().tribe().name()) | ||
3399 | 866 | bldname += "." + owner().tribe().name(); | ||
3400 | 867 | } else if (enemytribe.name() == bldname.substr(dot + 1, bldname.size())) | ||
3401 | 868 | bldname = bldname.substr(0, dot); | ||
3402 | 869 | Building_Index bldi = enemytribe.safe_building_index(bldname.c_str()); | ||
3403 | 870 | const Building_Descr * former_descr = enemytribe.get_building_descr(bldi); | ||
3404 | 871 | former_buildings.push_back(former_descr); | ||
3405 | 872 | } | ||
3406 | 873 | |||
3407 | 874 | const Coords coords = get_position(); | ||
3408 | 875 | // Now we destroy the old building before we place the new one. | ||
3409 | 876 | set_defeating_player(defeating); | ||
3410 | 877 | schedule_destroy(game); | ||
3411 | 878 | |||
3412 | 879 | enemyplayer->force_building(coords, former_buildings); | ||
3413 | 880 | BaseImmovable * const newimm = game.map()[coords].get_immovable(); | ||
3414 | 881 | upcast(GarrisonOwner, go, newimm); | ||
3415 | 882 | go->reinit_after_conqueral(game); | ||
3416 | 883 | |||
3417 | 884 | // Of course we should inform the victorious player as well | ||
3418 | 885 | upcast(Building, new_building, newimm); | ||
3419 | 886 | std::string message = | ||
3420 | 887 | (boost::format | ||
3421 | 888 | (_("Your soldiers defeated the enemy at the %s.")) | ||
3422 | 889 | % new_building->descname()) | ||
3423 | 890 | .str(); | ||
3424 | 891 | new_building->send_message | ||
3425 | 892 | (game, "site_defeated", | ||
3426 | 893 | _("Enemy at site defeated!"), | ||
3427 | 894 | message); | ||
3428 | 895 | >>>>>>> MERGE-SOURCE | ||
3429 | 910 | } | 896 | } |
3430 | 911 | 897 | ||
3433 | 912 | /// Initialises the militarysite after it was "conquered" (the old was replaced) | 898 | void MilitarySite::reinit_after_conqueral(Game& game) |
3432 | 913 | void MilitarySite::reinit_after_conqueration(Game & game) | ||
3434 | 914 | { | 899 | { |
3438 | 915 | clear_requirements(); | 900 | m_garrison->reinit_after_conqueral(game); |
3436 | 916 | conquer_area(game); | ||
3437 | 917 | update_soldier_request(); | ||
3439 | 918 | start_animation(game, descr().get_animation("idle")); | 901 | start_animation(game, descr().get_animation("idle")); |
3440 | 919 | } | 902 | } |
3441 | 920 | 903 | ||
3442 | 904 | <<<<<<< TREE | ||
3443 | 921 | /// Calculates whether the military presence is still kept and \returns true if. | 905 | /// Calculates whether the military presence is still kept and \returns true if. |
3444 | 922 | bool MilitarySite::military_presence_kept(Game & game) | 906 | bool MilitarySite::military_presence_kept(Game & game) |
3445 | 923 | { | 907 | { |
3446 | @@ -1103,4 +1087,6 @@ | |||
3447 | 1103 | m_next_swap_soldiers_time = 0; | 1087 | m_next_swap_soldiers_time = 0; |
3448 | 1104 | } | 1088 | } |
3449 | 1105 | 1089 | ||
3450 | 1090 | ======= | ||
3451 | 1091 | >>>>>>> MERGE-SOURCE | ||
3452 | 1106 | } | 1092 | } |
3453 | 1107 | 1093 | ||
3454 | === modified file 'src/logic/militarysite.h' | |||
3455 | --- src/logic/militarysite.h 2013-07-26 20:19:36 +0000 | |||
3456 | +++ src/logic/militarysite.h 2013-08-10 10:53:03 +0000 | |||
3457 | @@ -20,10 +20,10 @@ | |||
3458 | 20 | #ifndef MILITARYSITE_H | 20 | #ifndef MILITARYSITE_H |
3459 | 21 | #define MILITARYSITE_H | 21 | #define MILITARYSITE_H |
3460 | 22 | 22 | ||
3462 | 23 | #include "logic/attackable.h" | 23 | #include "logic/garrison.h" |
3463 | 24 | #include "logic/garrisonhandler.h" | ||
3464 | 24 | #include "logic/productionsite.h" | 25 | #include "logic/productionsite.h" |
3465 | 25 | #include "logic/requirements.h" | 26 | #include "logic/requirements.h" |
3466 | 26 | #include "logic/soldiercontrol.h" | ||
3467 | 27 | 27 | ||
3468 | 28 | namespace Widelands { | 28 | namespace Widelands { |
3469 | 29 | 29 | ||
3470 | @@ -53,121 +53,39 @@ | |||
3471 | 53 | }; | 53 | }; |
3472 | 54 | 54 | ||
3473 | 55 | class MilitarySite : | 55 | class MilitarySite : |
3475 | 56 | public ProductionSite, public SoldierControl, public Attackable | 56 | public ProductionSite, public GarrisonOwner |
3476 | 57 | { | 57 | { |
3477 | 58 | friend struct Map_Buildingdata_Data_Packet; | 58 | friend struct Map_Buildingdata_Data_Packet; |
3478 | 59 | MO_DESCR(MilitarySite_Descr); | 59 | MO_DESCR(MilitarySite_Descr); |
3479 | 60 | 60 | ||
3480 | 61 | public: | 61 | public: |
3481 | 62 | // I assume elsewhere, that enum SoldierPreference fits to uint8_t. | ||
3482 | 63 | enum SoldierPreference : uint8_t { | ||
3483 | 64 | kNoPreference, | ||
3484 | 65 | kPrefersRookies, | ||
3485 | 66 | kPrefersHeroes, | ||
3486 | 67 | }; | ||
3487 | 68 | |||
3488 | 69 | MilitarySite(const MilitarySite_Descr &); | 62 | MilitarySite(const MilitarySite_Descr &); |
3489 | 70 | virtual ~MilitarySite(); | 63 | virtual ~MilitarySite(); |
3490 | 71 | 64 | ||
3494 | 72 | char const * type_name() const throw () {return "militarysite";} | 65 | void load_finish(Editor_Game_Base &); |
3492 | 73 | virtual std::string get_statistics_string(); | ||
3493 | 74 | |||
3495 | 75 | virtual void init(Editor_Game_Base &); | 66 | virtual void init(Editor_Game_Base &); |
3496 | 76 | virtual void cleanup(Editor_Game_Base &); | 67 | virtual void cleanup(Editor_Game_Base &); |
3497 | 77 | virtual void act(Game &, uint32_t data); | 68 | virtual void act(Game &, uint32_t data); |
3499 | 78 | virtual void remove_worker(Worker &); | 69 | |
3500 | 70 | char const * type_name() const throw () {return "militarysite";} | ||
3501 | 71 | virtual std::string get_statistics_string(); | ||
3502 | 79 | 72 | ||
3503 | 80 | virtual void set_economy(Economy *); | 73 | virtual void set_economy(Economy *); |
3504 | 81 | virtual bool get_building_work(Game &, Worker &, bool success); | 74 | virtual bool get_building_work(Game &, Worker &, bool success); |
3505 | 82 | 75 | ||
3545 | 83 | // Begin implementation of SoldierControl | 76 | // GarrisonOwner implementation |
3546 | 84 | virtual std::vector<Soldier *> presentSoldiers() const; | 77 | virtual Garrison* get_garrison() const; |
3547 | 85 | virtual std::vector<Soldier *> stationedSoldiers() const; | 78 | virtual Building* get_building(); |
3548 | 86 | virtual uint32_t minSoldierCapacity() const throw (); | 79 | virtual void garrison_occupied(); |
3549 | 87 | virtual uint32_t maxSoldierCapacity() const throw (); | 80 | virtual void garrison_lost(Game & game, Player_Number defeating, bool captured); |
3550 | 88 | virtual uint32_t soldierCapacity() const; | 81 | virtual void reinit_after_conqueral(Game& game); |
3512 | 89 | virtual void setSoldierCapacity(uint32_t capacity); | ||
3513 | 90 | virtual void dropSoldier(Soldier &); | ||
3514 | 91 | virtual int incorporateSoldier(Editor_Game_Base & game, Soldier & s); | ||
3515 | 92 | // End implementation of SoldierControl | ||
3516 | 93 | |||
3517 | 94 | // Begin implementation of Attackable | ||
3518 | 95 | virtual Player & owner() const {return Building::owner();} | ||
3519 | 96 | virtual bool canAttack(); | ||
3520 | 97 | virtual void aggressor(Soldier &); | ||
3521 | 98 | virtual bool attack (Soldier &); | ||
3522 | 99 | // End implementation of Attackable | ||
3523 | 100 | |||
3524 | 101 | /** | ||
3525 | 102 | * Launch the given soldier on an attack towards the given | ||
3526 | 103 | * target building. | ||
3527 | 104 | */ | ||
3528 | 105 | void sendAttacker(Soldier &, Building &, uint8_t); | ||
3529 | 106 | |||
3530 | 107 | /// This methods are helper for use at configure this site. | ||
3531 | 108 | void set_requirements (const Requirements &); | ||
3532 | 109 | void clear_requirements(); | ||
3533 | 110 | const Requirements & get_requirements () const { | ||
3534 | 111 | return m_soldier_requirements; | ||
3535 | 112 | } | ||
3536 | 113 | |||
3537 | 114 | void reinit_after_conqueration(Game &); | ||
3538 | 115 | |||
3539 | 116 | void update_soldier_request(bool i = false); | ||
3540 | 117 | |||
3541 | 118 | void set_soldier_preference(SoldierPreference); | ||
3542 | 119 | SoldierPreference get_soldier_preference() const { | ||
3543 | 120 | return m_soldier_preference; | ||
3544 | 121 | } | ||
3551 | 122 | 82 | ||
3552 | 123 | protected: | 83 | protected: |
3553 | 124 | void conquer_area(Editor_Game_Base &); | ||
3554 | 125 | |||
3555 | 126 | virtual void create_options_window | 84 | virtual void create_options_window |
3556 | 127 | (Interactive_GameBase &, UI::Window * & registry); | 85 | (Interactive_GameBase &, UI::Window * & registry); |
3557 | 128 | 86 | ||
3558 | 129 | private: | 87 | private: |
3600 | 130 | bool isPresent(Soldier &) const; | 88 | std::unique_ptr<GarrisonHandler> m_garrison; |
3560 | 131 | static void request_soldier_callback | ||
3561 | 132 | (Game &, Request &, Ware_Index, Worker *, PlayerImmovable &); | ||
3562 | 133 | |||
3563 | 134 | Map_Object * popSoldierJob | ||
3564 | 135 | (Soldier *, bool * stayhome = 0, uint8_t * retreat = 0); | ||
3565 | 136 | bool haveSoldierJob(Soldier &); | ||
3566 | 137 | bool military_presence_kept(Game &); | ||
3567 | 138 | void informPlayer(Game &, bool discovered = false); | ||
3568 | 139 | bool update_upgrade_requirements(); | ||
3569 | 140 | void update_normal_soldier_request(); | ||
3570 | 141 | void update_upgrade_soldier_request(); | ||
3571 | 142 | bool incorporateUpgradedSoldier(Editor_Game_Base & game, Soldier & s); | ||
3572 | 143 | Soldier * find_least_suited_soldier(); | ||
3573 | 144 | bool drop_least_suited_soldier(bool new_has_arrived, Soldier * s); | ||
3574 | 145 | |||
3575 | 146 | |||
3576 | 147 | private: | ||
3577 | 148 | Requirements m_soldier_requirements; // This is used to grab a bunch of soldiers: Anything goes | ||
3578 | 149 | RequireAttribute m_soldier_upgrade_requirements; // This is used when exchanging soldiers. | ||
3579 | 150 | std::unique_ptr<Request> m_normal_soldier_request; // filling the site | ||
3580 | 151 | std::unique_ptr<Request> m_upgrade_soldier_request; // seeking for better soldiers | ||
3581 | 152 | bool m_didconquer; | ||
3582 | 153 | uint32_t m_capacity; | ||
3583 | 154 | |||
3584 | 155 | /** | ||
3585 | 156 | * Next gametime where we should heal something. | ||
3586 | 157 | */ | ||
3587 | 158 | int32_t m_nexthealtime; | ||
3588 | 159 | |||
3589 | 160 | struct SoldierJob { | ||
3590 | 161 | Soldier * soldier; | ||
3591 | 162 | Object_Ptr enemy; | ||
3592 | 163 | bool stayhome; | ||
3593 | 164 | uint8_t retreat; | ||
3594 | 165 | }; | ||
3595 | 166 | std::vector<SoldierJob> m_soldierjobs; | ||
3596 | 167 | SoldierPreference m_soldier_preference; | ||
3597 | 168 | int32_t m_next_swap_soldiers_time; | ||
3598 | 169 | bool m_soldier_upgrade_try; // optimization -- if everybody is zero-level, do not downgrade | ||
3599 | 170 | bool m_doing_upgrade_request; | ||
3601 | 171 | }; | 89 | }; |
3602 | 172 | 90 | ||
3603 | 173 | } | 91 | } |
3604 | 174 | 92 | ||
3605 | === modified file 'src/logic/player.cc' | |||
3606 | --- src/logic/player.cc 2013-08-08 20:02:13 +0000 | |||
3607 | +++ src/logic/player.cc 2013-08-10 10:53:03 +0000 | |||
3608 | @@ -38,7 +38,6 @@ | |||
3609 | 38 | #include "logic/militarysite.h" | 38 | #include "logic/militarysite.h" |
3610 | 39 | #include "logic/playercommand.h" | 39 | #include "logic/playercommand.h" |
3611 | 40 | #include "logic/soldier.h" | 40 | #include "logic/soldier.h" |
3612 | 41 | #include "logic/soldiercontrol.h" | ||
3613 | 42 | #include "logic/trainingsite.h" | 41 | #include "logic/trainingsite.h" |
3614 | 43 | #include "logic/tribe.h" | 42 | #include "logic/tribe.h" |
3615 | 44 | #include "logic/warehouse.h" | 43 | #include "logic/warehouse.h" |
3616 | @@ -699,12 +698,14 @@ | |||
3617 | 699 | 698 | ||
3618 | 700 | void Player::military_site_set_soldier_preference(PlayerImmovable & imm, uint8_t m_soldier_preference) | 699 | void Player::military_site_set_soldier_preference(PlayerImmovable & imm, uint8_t m_soldier_preference) |
3619 | 701 | { | 700 | { |
3623 | 702 | if (&imm.owner() == this) | 701 | if (&imm.owner() == this) { |
3624 | 703 | if (upcast(MilitarySite, milsite, &imm)) | 702 | if (upcast(GarrisonOwner, go, &imm)) { |
3625 | 704 | milsite->set_soldier_preference(static_cast<MilitarySite::SoldierPreference>(m_soldier_preference)); | 703 | Garrison* const garrison = go->get_garrison(); |
3626 | 704 | garrison->set_soldier_preference(static_cast<Garrison::SoldierPref>(m_soldier_preference)); | ||
3627 | 705 | } | ||
3628 | 706 | } | ||
3629 | 705 | } | 707 | } |
3630 | 706 | 708 | ||
3631 | 707 | |||
3632 | 708 | /* | 709 | /* |
3633 | 709 | * enhance this building, remove it, but give the constructionsite | 710 | * enhance this building, remove it, but give the constructionsite |
3634 | 710 | * an idea of enhancing | 711 | * an idea of enhancing |
3635 | @@ -867,8 +868,9 @@ | |||
3636 | 867 | return; | 868 | return; |
3637 | 868 | if (soldier.get_worker_type() != Worker_Descr::SOLDIER) | 869 | if (soldier.get_worker_type() != Worker_Descr::SOLDIER) |
3638 | 869 | return; | 870 | return; |
3641 | 870 | if (upcast(SoldierControl, ctrl, &imm)) | 871 | if (upcast(GarrisonOwner, go, &imm)) { |
3642 | 871 | ctrl->dropSoldier(soldier); | 872 | go->get_garrison()->dropSoldier(soldier); |
3643 | 873 | } | ||
3644 | 872 | } | 874 | } |
3645 | 873 | 875 | ||
3646 | 874 | /* | 876 | /* |
3647 | @@ -926,9 +928,10 @@ | |||
3648 | 926 | 928 | ||
3649 | 927 | container_iterate_const(std::vector<BaseImmovable *>, flags, i) { | 929 | container_iterate_const(std::vector<BaseImmovable *>, flags, i) { |
3650 | 928 | const Flag * attackerflag = static_cast<Flag *>(*i.current); | 930 | const Flag * attackerflag = static_cast<Flag *>(*i.current); |
3654 | 929 | const MilitarySite * ms = static_cast<MilitarySite *>(attackerflag->get_building()); | 931 | GarrisonOwner * go = dynamic_cast<GarrisonOwner *>(attackerflag->get_building()); |
3655 | 930 | std::vector<Soldier *> const present = ms->presentSoldiers(); | 932 | Garrison * garrison = go->get_garrison(); |
3656 | 931 | uint32_t const nr_staying = ms->minSoldierCapacity(); | 933 | std::vector<Soldier *> const present = garrison->presentSoldiers(); |
3657 | 934 | uint32_t const nr_staying = garrison->minSoldierCapacity(); | ||
3658 | 932 | uint32_t const nr_present = present.size(); | 935 | uint32_t const nr_present = present.size(); |
3659 | 933 | if (nr_staying < nr_present) { | 936 | if (nr_staying < nr_present) { |
3660 | 934 | uint32_t const nr_taken = | 937 | uint32_t const nr_taken = |
3661 | @@ -964,8 +967,8 @@ | |||
3662 | 964 | log("enemyflagaction: count is 0\n"); | 967 | log("enemyflagaction: count is 0\n"); |
3663 | 965 | else if (is_hostile(flag.owner())) | 968 | else if (is_hostile(flag.owner())) |
3664 | 966 | if (Building * const building = flag.get_building()) | 969 | if (Building * const building = flag.get_building()) |
3667 | 967 | if (upcast(Attackable, attackable, building)) | 970 | if (upcast(GarrisonOwner, go, building)) |
3668 | 968 | if (attackable->canAttack()) { | 971 | if (go->get_garrison()->canAttack()) { |
3669 | 969 | std::vector<Soldier *> attackers; | 972 | std::vector<Soldier *> attackers; |
3670 | 970 | findAttackSoldiers(flag, &attackers, count); | 973 | findAttackSoldiers(flag, &attackers, count); |
3671 | 971 | assert(attackers.size() <= count); | 974 | assert(attackers.size() <= count); |
3672 | @@ -975,10 +978,10 @@ | |||
3673 | 975 | retreat = std::min | 978 | retreat = std::min |
3674 | 976 | (retreat, tribe().get_military_data().get_max_retreat()); | 979 | (retreat, tribe().get_military_data().get_max_retreat()); |
3675 | 977 | 980 | ||
3680 | 978 | container_iterate_const(std::vector<Soldier *>, attackers, i) | 981 | container_iterate_const(std::vector<Soldier *>, attackers, i) { |
3681 | 979 | ref_cast<MilitarySite, PlayerImmovable> | 982 | upcast(GarrisonOwner, igo, (*i.current)->get_location(egbase())); |
3682 | 980 | (*(*i.current)->get_location(egbase())) | 983 | igo->get_garrison()->sendAttacker(**i.current, *building, retreat); |
3683 | 981 | .sendAttacker(**i.current, *building, retreat); | 984 | } |
3684 | 982 | } | 985 | } |
3685 | 983 | } | 986 | } |
3686 | 984 | 987 | ||
3687 | @@ -1177,13 +1180,13 @@ | |||
3688 | 1177 | 1180 | ||
3689 | 1178 | const uint32_t nrecos = get_nr_economies(); | 1181 | const uint32_t nrecos = get_nr_economies(); |
3690 | 1179 | for (uint32_t i = 0; i < nrecos; ++i) { | 1182 | for (uint32_t i = 0; i < nrecos; ++i) { |
3693 | 1180 | const std::vector<Widelands::Warehouse *> & warehouses = | 1183 | const std::vector<Widelands::Storage *> & storages = |
3694 | 1181 | get_economy_by_number(i)->warehouses(); | 1184 | get_economy_by_number(i)->storages(); |
3695 | 1182 | 1185 | ||
3696 | 1183 | for | 1186 | for |
3700 | 1184 | (std::vector<Widelands::Warehouse *>::const_iterator it = | 1187 | (std::vector<Widelands::Storage *>::const_iterator it = |
3701 | 1185 | warehouses.begin(); | 1188 | storages.begin(); |
3702 | 1186 | it != warehouses.end(); | 1189 | it != storages.end(); |
3703 | 1187 | ++it) | 1190 | ++it) |
3704 | 1188 | { | 1191 | { |
3705 | 1189 | const Widelands::WareList & wares = (*it)->get_wares(); | 1192 | const Widelands::WareList & wares = (*it)->get_wares(); |
3706 | 1190 | 1193 | ||
3707 | === modified file 'src/logic/player.h' | |||
3708 | --- src/logic/player.h 2013-08-01 10:51:41 +0000 | |||
3709 | +++ src/logic/player.h 2013-08-10 10:53:03 +0000 | |||
3710 | @@ -638,7 +638,7 @@ | |||
3711 | 638 | std::vector< std::vector<uint32_t> > m_ware_consumptions; | 638 | std::vector< std::vector<uint32_t> > m_ware_consumptions; |
3712 | 639 | 639 | ||
3713 | 640 | /** | 640 | /** |
3715 | 641 | * Statistics of wares stored inside of warehouses over the | 641 | * Statistics of wares stored inside of storages over the |
3716 | 642 | * life of the game, indexed as | 642 | * life of the game, indexed as |
3717 | 643 | * m_ware_stocks[ware_id][time_index] | 643 | * m_ware_stocks[ware_id][time_index] |
3718 | 644 | */ | 644 | */ |
3719 | 645 | 645 | ||
3720 | === modified file 'src/logic/playercommand.cc' | |||
3721 | --- src/logic/playercommand.cc 2013-08-07 12:32:36 +0000 | |||
3722 | +++ src/logic/playercommand.cc 2013-08-10 10:53:03 +0000 | |||
3723 | @@ -525,7 +525,7 @@ | |||
3724 | 525 | PlayerCommand (0, des.Unsigned8()) | 525 | PlayerCommand (0, des.Unsigned8()) |
3725 | 526 | { | 526 | { |
3726 | 527 | serial = des.Unsigned32(); | 527 | serial = des.Unsigned32(); |
3728 | 528 | preference = des.Unsigned8(); | 528 | preference = static_cast<Garrison::SoldierPref>(des.Unsigned8()); |
3729 | 529 | } | 529 | } |
3730 | 530 | 530 | ||
3731 | 531 | void Cmd_MilitarySiteSetSoldierPreference::serialize (StreamWrite & ser) | 531 | void Cmd_MilitarySiteSetSoldierPreference::serialize (StreamWrite & ser) |
3732 | @@ -533,7 +533,7 @@ | |||
3733 | 533 | ser.Unsigned8 (PLCMD_MILITARYSITESETSOLDIERPREFERENCE); | 533 | ser.Unsigned8 (PLCMD_MILITARYSITESETSOLDIERPREFERENCE); |
3734 | 534 | ser.Unsigned8 (sender()); | 534 | ser.Unsigned8 (sender()); |
3735 | 535 | ser.Unsigned32(serial); | 535 | ser.Unsigned32(serial); |
3737 | 536 | ser.Unsigned8 (preference); | 536 | ser.Unsigned8 (static_cast<uint8_t>(preference)); |
3738 | 537 | } | 537 | } |
3739 | 538 | 538 | ||
3740 | 539 | void Cmd_MilitarySiteSetSoldierPreference::execute (Game & game) | 539 | void Cmd_MilitarySiteSetSoldierPreference::execute (Game & game) |
3741 | @@ -554,7 +554,7 @@ | |||
3742 | 554 | 554 | ||
3743 | 555 | // Now serial | 555 | // Now serial |
3744 | 556 | const Map_Object & obj = *egbase.objects().get_object(serial); | 556 | const Map_Object & obj = *egbase.objects().get_object(serial); |
3746 | 557 | fw.Unsigned8(preference); | 557 | fw.Unsigned8(static_cast<uint8_t>(preference)); |
3747 | 558 | fw.Unsigned32(mos.get_object_file_index(obj)); | 558 | fw.Unsigned32(mos.get_object_file_index(obj)); |
3748 | 559 | } | 559 | } |
3749 | 560 | 560 | ||
3750 | @@ -566,7 +566,7 @@ | |||
3751 | 566 | const uint16_t packet_version = fr.Unsigned16(); | 566 | const uint16_t packet_version = fr.Unsigned16(); |
3752 | 567 | if (packet_version == PLAYER_CMD_SOLDIERPREFERENCE_VERSION) { | 567 | if (packet_version == PLAYER_CMD_SOLDIERPREFERENCE_VERSION) { |
3753 | 568 | PlayerCommand::Read(fr, egbase, mol); | 568 | PlayerCommand::Read(fr, egbase, mol); |
3755 | 569 | preference = fr.Unsigned8(); | 569 | preference = static_cast<Garrison::SoldierPref>(fr.Unsigned8()); |
3756 | 570 | const uint32_t building_serial = fr.Unsigned32(); | 570 | const uint32_t building_serial = fr.Unsigned32(); |
3757 | 571 | try { | 571 | try { |
3758 | 572 | serial = mol.get<Map_Object>(building_serial).serial(); | 572 | serial = mol.get<Map_Object>(building_serial).serial(); |
3759 | @@ -1724,8 +1724,8 @@ | |||
3760 | 1724 | { | 1724 | { |
3761 | 1725 | if (upcast(Building, building, game.objects().get_object(serial))) | 1725 | if (upcast(Building, building, game.objects().get_object(serial))) |
3762 | 1726 | if (&building->owner() == game.get_player(sender())) | 1726 | if (&building->owner() == game.get_player(sender())) |
3765 | 1727 | if (upcast(SoldierControl, ctrl, building)) | 1727 | if (upcast(GarrisonOwner, go, building)) |
3766 | 1728 | ctrl->changeSoldierCapacity(val); | 1728 | go->get_garrison()->changeSoldierCapacity(val); |
3767 | 1729 | } | 1729 | } |
3768 | 1730 | 1730 | ||
3769 | 1731 | void Cmd_ChangeSoldierCapacity::serialize (StreamWrite & ser) | 1731 | void Cmd_ChangeSoldierCapacity::serialize (StreamWrite & ser) |
3770 | @@ -2023,18 +2023,18 @@ | |||
3771 | 2023 | /*** struct Cmd_SetStockPolicy ***/ | 2023 | /*** struct Cmd_SetStockPolicy ***/ |
3772 | 2024 | Cmd_SetStockPolicy::Cmd_SetStockPolicy | 2024 | Cmd_SetStockPolicy::Cmd_SetStockPolicy |
3773 | 2025 | (int32_t time, Player_Number p, | 2025 | (int32_t time, Player_Number p, |
3776 | 2026 | Warehouse & wh, bool isworker, Ware_Index ware, | 2026 | StorageOwner & storage_owner, bool isworker, Ware_Index ware, |
3777 | 2027 | Warehouse::StockPolicy policy) | 2027 | Storage::StockPolicy policy) |
3778 | 2028 | : PlayerCommand(time, p) | 2028 | : PlayerCommand(time, p) |
3779 | 2029 | { | 2029 | { |
3781 | 2030 | m_warehouse = wh.serial(); | 2030 | m_storage_owner = storage_owner.get_building()->serial(); |
3782 | 2031 | m_isworker = isworker; | 2031 | m_isworker = isworker; |
3783 | 2032 | m_ware = ware; | 2032 | m_ware = ware; |
3784 | 2033 | m_policy = policy; | 2033 | m_policy = policy; |
3785 | 2034 | } | 2034 | } |
3786 | 2035 | 2035 | ||
3787 | 2036 | Cmd_SetStockPolicy::Cmd_SetStockPolicy() | 2036 | Cmd_SetStockPolicy::Cmd_SetStockPolicy() |
3789 | 2037 | : PlayerCommand(), m_warehouse(0), m_isworker(false), m_policy() | 2037 | : PlayerCommand(), m_storage_owner(0), m_isworker(false), m_policy() |
3790 | 2038 | { | 2038 | { |
3791 | 2039 | } | 2039 | } |
3792 | 2040 | 2040 | ||
3793 | @@ -2047,20 +2047,20 @@ | |||
3794 | 2047 | { | 2047 | { |
3795 | 2048 | // Sanitize data that could have come from the network | 2048 | // Sanitize data that could have come from the network |
3796 | 2049 | if (Player * plr = game.get_player(sender())) { | 2049 | if (Player * plr = game.get_player(sender())) { |
3798 | 2050 | if (upcast(Warehouse, warehouse, game.objects().get_object(m_warehouse))) | 2050 | if (upcast(StorageOwner, storage_owner, game.objects().get_object(m_storage_owner))) |
3799 | 2051 | { | 2051 | { |
3801 | 2052 | if (&warehouse->owner() != plr) { | 2052 | if (&storage_owner->get_building()->owner() != plr) { |
3802 | 2053 | log | 2053 | log |
3805 | 2054 | ("Cmd_SetStockPolicy: sender %u, but warehouse owner %u\n", | 2054 | ("Cmd_SetStockPolicy: sender %u, but storage owner %u\n", |
3806 | 2055 | sender(), warehouse->owner().player_number()); | 2055 | sender(), storage_owner->get_building()->owner().player_number()); |
3807 | 2056 | return; | 2056 | return; |
3808 | 2057 | } | 2057 | } |
3809 | 2058 | 2058 | ||
3810 | 2059 | switch (m_policy) { | 2059 | switch (m_policy) { |
3815 | 2060 | case Warehouse::SP_Normal: | 2060 | case Storage::StockPolicy::Normal: |
3816 | 2061 | case Warehouse::SP_Prefer: | 2061 | case Storage::StockPolicy::Prefer: |
3817 | 2062 | case Warehouse::SP_DontStock: | 2062 | case Storage::StockPolicy::DontStock: |
3818 | 2063 | case Warehouse::SP_Remove: | 2063 | case Storage::StockPolicy::Remove: |
3819 | 2064 | break; | 2064 | break; |
3820 | 2065 | default: | 2065 | default: |
3821 | 2066 | log | 2066 | log |
3822 | @@ -2069,7 +2069,7 @@ | |||
3823 | 2069 | return; | 2069 | return; |
3824 | 2070 | } | 2070 | } |
3825 | 2071 | 2071 | ||
3827 | 2072 | const Tribe_Descr & tribe = warehouse->tribe(); | 2072 | const Tribe_Descr & tribe = storage_owner->get_building()->tribe(); |
3828 | 2073 | if (m_isworker) { | 2073 | if (m_isworker) { |
3829 | 2074 | if (!(m_ware < tribe.get_nrworkers())) { | 2074 | if (!(m_ware < tribe.get_nrworkers())) { |
3830 | 2075 | log | 2075 | log |
3831 | @@ -2077,7 +2077,7 @@ | |||
3832 | 2077 | sender(), m_ware.value()); | 2077 | sender(), m_ware.value()); |
3833 | 2078 | return; | 2078 | return; |
3834 | 2079 | } | 2079 | } |
3836 | 2080 | warehouse->set_worker_policy(m_ware, m_policy); | 2080 | storage_owner->get_storage()->set_worker_policy(m_ware, m_policy); |
3837 | 2081 | } else { | 2081 | } else { |
3838 | 2082 | if (!(m_ware < tribe.get_nrwares())) { | 2082 | if (!(m_ware < tribe.get_nrwares())) { |
3839 | 2083 | log | 2083 | log |
3840 | @@ -2085,7 +2085,7 @@ | |||
3841 | 2085 | sender(), m_ware.value()); | 2085 | sender(), m_ware.value()); |
3842 | 2086 | return; | 2086 | return; |
3843 | 2087 | } | 2087 | } |
3845 | 2088 | warehouse->set_ware_policy(m_ware, m_policy); | 2088 | storage_owner->get_storage()->set_ware_policy(m_ware, m_policy); |
3846 | 2089 | } | 2089 | } |
3847 | 2090 | } | 2090 | } |
3848 | 2091 | } | 2091 | } |
3849 | @@ -2094,20 +2094,20 @@ | |||
3850 | 2094 | Cmd_SetStockPolicy::Cmd_SetStockPolicy(StreamRead & des) | 2094 | Cmd_SetStockPolicy::Cmd_SetStockPolicy(StreamRead & des) |
3851 | 2095 | : PlayerCommand(0, des.Unsigned8()) | 2095 | : PlayerCommand(0, des.Unsigned8()) |
3852 | 2096 | { | 2096 | { |
3854 | 2097 | m_warehouse = des.Unsigned32(); | 2097 | m_storage_owner = des.Unsigned32(); |
3855 | 2098 | m_isworker = des.Unsigned8(); | 2098 | m_isworker = des.Unsigned8(); |
3856 | 2099 | m_ware = Ware_Index(des.Unsigned8()); | 2099 | m_ware = Ware_Index(des.Unsigned8()); |
3858 | 2100 | m_policy = static_cast<Warehouse::StockPolicy>(des.Unsigned8()); | 2100 | m_policy = static_cast<Storage::StockPolicy>(des.Unsigned8()); |
3859 | 2101 | } | 2101 | } |
3860 | 2102 | 2102 | ||
3861 | 2103 | void Cmd_SetStockPolicy::serialize(StreamWrite & ser) | 2103 | void Cmd_SetStockPolicy::serialize(StreamWrite & ser) |
3862 | 2104 | { | 2104 | { |
3863 | 2105 | ser.Unsigned8(PLCMD_SETSTOCKPOLICY); | 2105 | ser.Unsigned8(PLCMD_SETSTOCKPOLICY); |
3864 | 2106 | ser.Unsigned8(sender()); | 2106 | ser.Unsigned8(sender()); |
3866 | 2107 | ser.Unsigned32(m_warehouse); | 2107 | ser.Unsigned32(m_storage_owner); |
3867 | 2108 | ser.Unsigned8(m_isworker); | 2108 | ser.Unsigned8(m_isworker); |
3868 | 2109 | ser.Unsigned8(m_ware.value()); | 2109 | ser.Unsigned8(m_ware.value()); |
3870 | 2110 | ser.Unsigned8(m_policy); | 2110 | ser.Unsigned8(static_cast<uint8_t>(m_policy)); |
3871 | 2111 | } | 2111 | } |
3872 | 2112 | 2112 | ||
3873 | 2113 | #define PLAYER_CMD_SETSTOCKPOLICY_VERSION 1 | 2113 | #define PLAYER_CMD_SETSTOCKPOLICY_VERSION 1 |
3874 | @@ -2119,10 +2119,10 @@ | |||
3875 | 2119 | if (version != PLAYER_CMD_SETSTOCKPOLICY_VERSION) | 2119 | if (version != PLAYER_CMD_SETSTOCKPOLICY_VERSION) |
3876 | 2120 | throw game_data_error("unknown/unhandled version %u", version); | 2120 | throw game_data_error("unknown/unhandled version %u", version); |
3877 | 2121 | PlayerCommand::Read(fr, egbase, mol); | 2121 | PlayerCommand::Read(fr, egbase, mol); |
3879 | 2122 | m_warehouse = fr.Unsigned32(); | 2122 | m_storage_owner = fr.Unsigned32(); |
3880 | 2123 | m_isworker = fr.Unsigned8(); | 2123 | m_isworker = fr.Unsigned8(); |
3881 | 2124 | m_ware = Ware_Index(fr.Unsigned8()); | 2124 | m_ware = Ware_Index(fr.Unsigned8()); |
3883 | 2125 | m_policy = static_cast<Warehouse::StockPolicy>(fr.Unsigned8()); | 2125 | m_policy = static_cast<Storage::StockPolicy>(fr.Unsigned8()); |
3884 | 2126 | } catch (const std::exception & e) { | 2126 | } catch (const std::exception & e) { |
3885 | 2127 | throw game_data_error("Cmd_SetStockPolicy: %s", e.what()); | 2127 | throw game_data_error("Cmd_SetStockPolicy: %s", e.what()); |
3886 | 2128 | } | 2128 | } |
3887 | @@ -2133,10 +2133,10 @@ | |||
3888 | 2133 | { | 2133 | { |
3889 | 2134 | fw.Unsigned8(PLAYER_CMD_SETSTOCKPOLICY_VERSION); | 2134 | fw.Unsigned8(PLAYER_CMD_SETSTOCKPOLICY_VERSION); |
3890 | 2135 | PlayerCommand::Write(fw, egbase, mos); | 2135 | PlayerCommand::Write(fw, egbase, mos); |
3892 | 2136 | fw.Unsigned32(m_warehouse); | 2136 | fw.Unsigned32(m_storage_owner); |
3893 | 2137 | fw.Unsigned8(m_isworker); | 2137 | fw.Unsigned8(m_isworker); |
3894 | 2138 | fw.Unsigned8(m_ware.value()); | 2138 | fw.Unsigned8(m_ware.value()); |
3896 | 2139 | fw.Unsigned8(m_policy); | 2139 | fw.Unsigned8(static_cast<uint8_t>(m_policy)); |
3897 | 2140 | } | 2140 | } |
3898 | 2141 | 2141 | ||
3899 | 2142 | } | 2142 | } |
3900 | 2143 | 2143 | ||
3901 | === modified file 'src/logic/playercommand.h' | |||
3902 | --- src/logic/playercommand.h 2013-08-05 14:05:21 +0000 | |||
3903 | +++ src/logic/playercommand.h 2013-08-10 10:53:03 +0000 | |||
3904 | @@ -24,8 +24,8 @@ | |||
3905 | 24 | #include "economy/flag.h" | 24 | #include "economy/flag.h" |
3906 | 25 | #include "logic/message_id.h" | 25 | #include "logic/message_id.h" |
3907 | 26 | #include "logic/path.h" | 26 | #include "logic/path.h" |
3908 | 27 | #include "logic/storage.h" | ||
3909 | 27 | #include "logic/trainingsite.h" | 28 | #include "logic/trainingsite.h" |
3910 | 28 | #include "logic/warehouse.h" | ||
3911 | 29 | #include "logic/worker.h" | 29 | #include "logic/worker.h" |
3912 | 30 | 30 | ||
3913 | 31 | namespace Widelands { | 31 | namespace Widelands { |
3914 | @@ -196,7 +196,8 @@ | |||
3915 | 196 | 196 | ||
3916 | 197 | struct Cmd_MilitarySiteSetSoldierPreference : public PlayerCommand { | 197 | struct Cmd_MilitarySiteSetSoldierPreference : public PlayerCommand { |
3917 | 198 | Cmd_MilitarySiteSetSoldierPreference() : PlayerCommand(), serial(0) {} // For savegame loading | 198 | Cmd_MilitarySiteSetSoldierPreference() : PlayerCommand(), serial(0) {} // For savegame loading |
3919 | 199 | Cmd_MilitarySiteSetSoldierPreference (const int32_t t, const Player_Number p, Building & b, uint8_t prefs) | 199 | Cmd_MilitarySiteSetSoldierPreference |
3920 | 200 | (const int32_t t, const Player_Number p, Building & b, Garrison::SoldierPref prefs) | ||
3921 | 200 | : PlayerCommand(t, p), serial(b.serial()), preference(prefs) | 201 | : PlayerCommand(t, p), serial(b.serial()), preference(prefs) |
3922 | 201 | {} | 202 | {} |
3923 | 202 | 203 | ||
3924 | @@ -212,7 +213,7 @@ | |||
3925 | 212 | 213 | ||
3926 | 213 | private: | 214 | private: |
3927 | 214 | Serial serial; | 215 | Serial serial; |
3929 | 215 | uint8_t preference; | 216 | Garrison::SoldierPref preference; |
3930 | 216 | }; | 217 | }; |
3931 | 217 | struct Cmd_StartOrCancelExpedition : public PlayerCommand { | 218 | struct Cmd_StartOrCancelExpedition : public PlayerCommand { |
3932 | 218 | Cmd_StartOrCancelExpedition() : PlayerCommand() {} // For savegame loading | 219 | Cmd_StartOrCancelExpedition() : PlayerCommand() {} // For savegame loading |
3933 | @@ -764,13 +765,13 @@ | |||
3934 | 764 | }; | 765 | }; |
3935 | 765 | 766 | ||
3936 | 766 | /** | 767 | /** |
3938 | 767 | * Command to change the stock policy for a ware or worker in a warehouse. | 768 | * Command to change the stock policy for a ware or worker in a storage. |
3939 | 768 | */ | 769 | */ |
3940 | 769 | struct Cmd_SetStockPolicy : PlayerCommand { | 770 | struct Cmd_SetStockPolicy : PlayerCommand { |
3941 | 770 | Cmd_SetStockPolicy | 771 | Cmd_SetStockPolicy |
3942 | 771 | (int32_t time, Player_Number p, | 772 | (int32_t time, Player_Number p, |
3945 | 772 | Warehouse & wh, bool isworker, Ware_Index ware, | 773 | StorageOwner & storage_owner, bool isworker, Ware_Index ware, |
3946 | 773 | Warehouse::StockPolicy policy); | 774 | Storage::StockPolicy policy); |
3947 | 774 | 775 | ||
3948 | 775 | virtual uint8_t id() const; | 776 | virtual uint8_t id() const; |
3949 | 776 | 777 | ||
3950 | @@ -786,10 +787,10 @@ | |||
3951 | 786 | void Read (FileRead &, Editor_Game_Base &, Map_Map_Object_Loader &); | 787 | void Read (FileRead &, Editor_Game_Base &, Map_Map_Object_Loader &); |
3952 | 787 | 788 | ||
3953 | 788 | private: | 789 | private: |
3955 | 789 | Serial m_warehouse; | 790 | Serial m_storage_owner; |
3956 | 790 | bool m_isworker; | 791 | bool m_isworker; |
3957 | 791 | Ware_Index m_ware; | 792 | Ware_Index m_ware; |
3959 | 792 | Warehouse::StockPolicy m_policy; | 793 | Storage::StockPolicy m_policy; |
3960 | 793 | }; | 794 | }; |
3961 | 794 | 795 | ||
3962 | 795 | } | 796 | } |
3963 | 796 | 797 | ||
3964 | === modified file 'src/logic/production_program.cc' | |||
3965 | --- src/logic/production_program.cc 2013-08-08 19:55:12 +0000 | |||
3966 | +++ src/logic/production_program.cc 2013-08-10 10:53:03 +0000 | |||
3967 | @@ -32,12 +32,12 @@ | |||
3968 | 32 | #include "logic/findnode.h" | 32 | #include "logic/findnode.h" |
3969 | 33 | #include "logic/game.h" | 33 | #include "logic/game.h" |
3970 | 34 | #include "logic/game_data_error.h" | 34 | #include "logic/game_data_error.h" |
3971 | 35 | #include "logic/garrison.h" | ||
3972 | 35 | #include "logic/mapregion.h" | 36 | #include "logic/mapregion.h" |
3973 | 36 | #include "logic/message_queue.h" | 37 | #include "logic/message_queue.h" |
3974 | 37 | #include "logic/player.h" | 38 | #include "logic/player.h" |
3975 | 38 | #include "logic/productionsite.h" | 39 | #include "logic/productionsite.h" |
3976 | 39 | #include "logic/soldier.h" | 40 | #include "logic/soldier.h" |
3977 | 40 | #include "logic/soldiercontrol.h" | ||
3978 | 41 | #include "logic/trainingsite.h" | 41 | #include "logic/trainingsite.h" |
3979 | 42 | #include "logic/tribe.h" | 42 | #include "logic/tribe.h" |
3980 | 43 | #include "logic/worker_program.h" | 43 | #include "logic/worker_program.h" |
3981 | @@ -1274,8 +1274,13 @@ | |||
3982 | 1274 | void ProductionProgram::ActCheck_Soldier::execute | 1274 | void ProductionProgram::ActCheck_Soldier::execute |
3983 | 1275 | (Game & game, ProductionSite & ps) const | 1275 | (Game & game, ProductionSite & ps) const |
3984 | 1276 | { | 1276 | { |
3987 | 1277 | SoldierControl & ctrl = dynamic_cast<SoldierControl &>(ps); | 1277 | GarrisonOwner * go = dynamic_cast<GarrisonOwner *>(&ps); |
3988 | 1278 | const std::vector<Soldier *> soldiers = ctrl.presentSoldiers(); | 1278 | if (!go) { |
3989 | 1279 | log("CGH no garrison owner for %s %u\n", ps.descr().descname().c_str(), ps.serial()); | ||
3990 | 1280 | return; | ||
3991 | 1281 | } | ||
3992 | 1282 | Garrison* ga = go->get_garrison(); | ||
3993 | 1283 | const std::vector<Soldier *> soldiers = ga->presentSoldiers(); | ||
3994 | 1279 | const std::vector<Soldier *>::const_iterator soldiers_end = soldiers.end(); | 1284 | const std::vector<Soldier *>::const_iterator soldiers_end = soldiers.end(); |
3995 | 1280 | 1285 | ||
3996 | 1281 | ps.molog(" Checking soldier (%u) level %d)\n", attribute, level); | 1286 | ps.molog(" Checking soldier (%u) level %d)\n", attribute, level); |
3997 | @@ -1360,8 +1365,10 @@ | |||
3998 | 1360 | void ProductionProgram::ActTrain::execute | 1365 | void ProductionProgram::ActTrain::execute |
3999 | 1361 | (Game & game, ProductionSite & ps) const | 1366 | (Game & game, ProductionSite & ps) const |
4000 | 1362 | { | 1367 | { |
4003 | 1363 | SoldierControl & ctrl = dynamic_cast<SoldierControl &>(ps); | 1368 | GarrisonOwner * go = dynamic_cast<GarrisonOwner *>(&ps); |
4004 | 1364 | const std::vector<Soldier *> soldiers = ctrl.presentSoldiers(); | 1369 | assert(go); |
4005 | 1370 | const Garrison* ga = go->get_garrison(); | ||
4006 | 1371 | const std::vector<Soldier *> soldiers = ga->presentSoldiers(); | ||
4007 | 1365 | const std::vector<Soldier *>::const_iterator soldiers_end = | 1372 | const std::vector<Soldier *>::const_iterator soldiers_end = |
4008 | 1366 | soldiers.end(); | 1373 | soldiers.end(); |
4009 | 1367 | std::vector<Soldier *>::const_iterator it = soldiers.begin(); | 1374 | std::vector<Soldier *>::const_iterator it = soldiers.begin(); |
4010 | 1368 | 1375 | ||
4011 | === modified file 'src/logic/productionsite.cc' | |||
4012 | --- src/logic/productionsite.cc 2013-07-26 20:19:36 +0000 | |||
4013 | +++ src/logic/productionsite.cc 2013-08-10 10:53:03 +0000 | |||
4014 | @@ -113,7 +113,7 @@ | |||
4015 | 113 | } catch (const _wexception & e) { | 113 | } catch (const _wexception & e) { |
4016 | 114 | throw wexception("%s=\"%s\": %s", v->get_name(), v->get_string(), e.what()); | 114 | throw wexception("%s=\"%s\": %s", v->get_name(), v->get_string(), e.what()); |
4017 | 115 | } | 115 | } |
4019 | 116 | if (working_positions().empty() and not global_s.has_val("max_soldiers")) | 116 | if (working_positions().empty() and prof.get_section("garrison") == nullptr) |
4020 | 117 | throw wexception("no working/soldier positions"); | 117 | throw wexception("no working/soldier positions"); |
4021 | 118 | 118 | ||
4022 | 119 | // Get programs | 119 | // Get programs |
4023 | 120 | 120 | ||
4024 | === modified file 'src/logic/soldier.cc' | |||
4025 | --- src/logic/soldier.cc 2013-08-07 03:51:32 +0000 | |||
4026 | +++ src/logic/soldier.cc 2013-08-10 10:53:03 +0000 | |||
4027 | @@ -28,7 +28,6 @@ | |||
4028 | 28 | #include "graphic/graphic.h" | 28 | #include "graphic/graphic.h" |
4029 | 29 | #include "graphic/rendertarget.h" | 29 | #include "graphic/rendertarget.h" |
4030 | 30 | #include "helper.h" | 30 | #include "helper.h" |
4031 | 31 | #include "logic/attackable.h" | ||
4032 | 32 | #include "logic/battle.h" | 31 | #include "logic/battle.h" |
4033 | 33 | #include "logic/building.h" | 32 | #include "logic/building.h" |
4034 | 34 | #include "logic/checkstep.h" | 33 | #include "logic/checkstep.h" |
4035 | @@ -38,11 +37,11 @@ | |||
4036 | 38 | #include "logic/findnode.h" | 37 | #include "logic/findnode.h" |
4037 | 39 | #include "logic/game.h" | 38 | #include "logic/game.h" |
4038 | 40 | #include "logic/game_data_error.h" | 39 | #include "logic/game_data_error.h" |
4039 | 40 | #include "logic/garrison.h" | ||
4040 | 41 | #include "logic/message_queue.h" | 41 | #include "logic/message_queue.h" |
4041 | 42 | #include "logic/militarysite.h" | 42 | #include "logic/militarysite.h" |
4042 | 43 | #include "logic/player.h" | 43 | #include "logic/player.h" |
4043 | 44 | #include "logic/tribe.h" | 44 | #include "logic/tribe.h" |
4044 | 45 | #include "logic/warehouse.h" | ||
4045 | 46 | #include "map_io/widelands_map_map_object_loader.h" | 45 | #include "map_io/widelands_map_map_object_loader.h" |
4046 | 47 | #include "map_io/widelands_map_map_object_saver.h" | 46 | #include "map_io/widelands_map_map_object_saver.h" |
4047 | 48 | #include "profile/profile.h" | 47 | #include "profile/profile.h" |
4048 | @@ -764,7 +763,11 @@ | |||
4049 | 764 | struct FindNodeOwned { | 763 | struct FindNodeOwned { |
4050 | 765 | FindNodeOwned(Player_Number owner) : m_owner(owner) | 764 | FindNodeOwned(Player_Number owner) : m_owner(owner) |
4051 | 766 | {}; | 765 | {}; |
4052 | 766 | <<<<<<< TREE | ||
4053 | 767 | bool accept(const Map&, const FCoords& coords) const { | 767 | bool accept(const Map&, const FCoords& coords) const { |
4054 | 768 | ======= | ||
4055 | 769 | bool accept(const Map &, const FCoords & coords) const { | ||
4056 | 770 | >>>>>>> MERGE-SOURCE | ||
4057 | 768 | return (coords.field->get_owned_by() == m_owner); | 771 | return (coords.field->get_owned_by() == m_owner); |
4058 | 769 | } | 772 | } |
4059 | 770 | private: | 773 | private: |
4060 | @@ -789,8 +792,6 @@ | |||
4061 | 789 | void Soldier::start_task_attack | 792 | void Soldier::start_task_attack |
4062 | 790 | (Game & game, Building & building, uint8_t retreat) | 793 | (Game & game, Building & building, uint8_t retreat) |
4063 | 791 | { | 794 | { |
4064 | 792 | //dynamic_cast<const Attackable &>(building); | ||
4065 | 793 | |||
4066 | 794 | push_task(game, taskAttack); | 795 | push_task(game, taskAttack); |
4067 | 795 | State & state = top_state(); | 796 | State & state = top_state(); |
4068 | 796 | state.objvar1 = &building; | 797 | state.objvar1 = &building; |
4069 | @@ -960,13 +961,8 @@ | |||
4070 | 960 | 961 | ||
4071 | 961 | // Count remaining defenders | 962 | // Count remaining defenders |
4072 | 962 | if (enemy) { | 963 | if (enemy) { |
4080 | 963 | if (upcast(MilitarySite, ms, enemy)) { | 964 | if (upcast(GarrisonOwner, garrison_owner, enemy)) { |
4081 | 964 | defenders = ms->presentSoldiers().size(); | 965 | defenders = garrison_owner->get_garrison()->presentSoldiers().size(); |
4075 | 965 | } | ||
4076 | 966 | if (upcast(Warehouse, wh, enemy)) { | ||
4077 | 967 | Requirements noreq; | ||
4078 | 968 | defenders = wh->count_workers | ||
4079 | 969 | (game, wh->tribe().worker_index("soldier"), noreq); | ||
4082 | 970 | } | 966 | } |
4083 | 971 | // Any enemy soldier at baseflag count as defender. | 967 | // Any enemy soldier at baseflag count as defender. |
4084 | 972 | std::vector<Bob *> soldiers; | 968 | std::vector<Bob *> soldiers; |
4085 | @@ -996,6 +992,7 @@ | |||
4086 | 996 | BaseImmovable * const newimm = game.map()[state.coords].get_immovable(); | 992 | BaseImmovable * const newimm = game.map()[state.coords].get_immovable(); |
4087 | 997 | upcast(MilitarySite, newsite, newimm); | 993 | upcast(MilitarySite, newsite, newimm); |
4088 | 998 | if (newsite and (&newsite->owner() == &owner())) { | 994 | if (newsite and (&newsite->owner() == &owner())) { |
4089 | 995 | <<<<<<< TREE | ||
4090 | 999 | if (upcast(SoldierControl, ctrl, newsite)) { | 996 | if (upcast(SoldierControl, ctrl, newsite)) { |
4091 | 1000 | state.objvar1 = 0; | 997 | state.objvar1 = 0; |
4092 | 1001 | // We may also have our location destroyed in between | 998 | // We may also have our location destroyed in between |
4093 | @@ -1011,6 +1008,20 @@ | |||
4094 | 1011 | newsite->update_soldier_request(); | 1008 | newsite->update_soldier_request(); |
4095 | 1012 | return schedule_act(game, 10); | 1009 | return schedule_act(game, 10); |
4096 | 1013 | } | 1010 | } |
4097 | 1011 | ======= | ||
4098 | 1012 | state.objvar1 = 0; | ||
4099 | 1013 | if | ||
4100 | 1014 | (newsite->get_garrison()->stationedSoldiers().size() | ||
4101 | 1015 | < newsite->get_garrison()->soldierCapacity() and | ||
4102 | 1016 | location->base_flag().get_position() | ||
4103 | 1017 | != | ||
4104 | 1018 | newsite ->base_flag().get_position()) | ||
4105 | 1019 | { | ||
4106 | 1020 | molog("[attack] enemy belongs to us now, move in\n"); | ||
4107 | 1021 | pop_task(game); | ||
4108 | 1022 | set_location(newsite); | ||
4109 | 1023 | return schedule_act(game, 10); | ||
4110 | 1024 | >>>>>>> MERGE-SOURCE | ||
4111 | 1014 | } | 1025 | } |
4112 | 1015 | } | 1026 | } |
4113 | 1016 | } | 1027 | } |
4114 | @@ -1040,12 +1051,12 @@ | |||
4115 | 1040 | } | 1051 | } |
4116 | 1041 | } | 1052 | } |
4117 | 1042 | 1053 | ||
4120 | 1043 | upcast(Attackable, attackable, enemy); | 1054 | upcast(GarrisonOwner, garrison_o, enemy); |
4121 | 1044 | assert(attackable); | 1055 | assert(garrison_o); |
4122 | 1045 | 1056 | ||
4123 | 1046 | molog("[attack] attacking target building\n"); | 1057 | molog("[attack] attacking target building\n"); |
4124 | 1047 | // give the enemy soldier some time to act | 1058 | // give the enemy soldier some time to act |
4126 | 1048 | schedule_act(game, attackable->attack(*this) ? 1000 : 10); | 1059 | schedule_act(game, garrison_o->get_garrison()->attack(*this) ? 1000 : 10); |
4127 | 1049 | } | 1060 | } |
4128 | 1050 | 1061 | ||
4129 | 1051 | void Soldier::attack_pop(Game & game, State &) | 1062 | void Soldier::attack_pop(Game & game, State &) |
4130 | @@ -1789,13 +1800,17 @@ | |||
4131 | 1789 | CheckStepWalkOn(descr().movecaps(), false), | 1800 | CheckStepWalkOn(descr().movecaps(), false), |
4132 | 1790 | FindImmovableAttackable()); | 1801 | FindImmovableAttackable()); |
4133 | 1791 | 1802 | ||
4135 | 1792 | container_iterate_const(std::vector<BaseImmovable *>, attackables, i) | 1803 | container_iterate_const(std::vector<BaseImmovable *>, attackables, i) { |
4136 | 1804 | const BaseImmovable* base_imm = *i.current; | ||
4137 | 1793 | if | 1805 | if |
4143 | 1794 | (ref_cast<PlayerImmovable const, BaseImmovable const>(**i.current) | 1806 | (ref_cast<PlayerImmovable const, BaseImmovable const>(*base_imm) |
4144 | 1795 | .get_owner()->player_number() | 1807 | .get_owner()->player_number() == land_owner) |
4145 | 1796 | == | 1808 | { |
4146 | 1797 | land_owner) | 1809 | if (upcast(const GarrisonOwner, go, base_imm)) { |
4147 | 1798 | dynamic_cast<Attackable &>(**i.current).aggressor(*this); | 1810 | go->get_garrison()->aggressor(*this); |
4148 | 1811 | } | ||
4149 | 1812 | } | ||
4150 | 1813 | } | ||
4151 | 1799 | } | 1814 | } |
4152 | 1800 | } | 1815 | } |
4153 | 1801 | 1816 | ||
4154 | 1802 | 1817 | ||
4155 | === removed file 'src/logic/soldiercontrol.h' | |||
4156 | --- src/logic/soldiercontrol.h 2012-02-15 21:25:34 +0000 | |||
4157 | +++ src/logic/soldiercontrol.h 1970-01-01 00:00:00 +0000 | |||
4158 | @@ -1,119 +0,0 @@ | |||
4159 | 1 | /* | ||
4160 | 2 | * Copyright (C) 2008 by the Widelands Development Team | ||
4161 | 3 | * | ||
4162 | 4 | * This program is free software; you can redistribute it and/or | ||
4163 | 5 | * modify it under the terms of the GNU General Public License | ||
4164 | 6 | * as published by the Free Software Foundation; either version 2 | ||
4165 | 7 | * of the License, or (at your option) any later version. | ||
4166 | 8 | * | ||
4167 | 9 | * This program is distributed in the hope that it will be useful, | ||
4168 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4169 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4170 | 12 | * GNU General Public License for more details. | ||
4171 | 13 | * | ||
4172 | 14 | * You should have received a copy of the GNU General Public License | ||
4173 | 15 | * along with this program; if not, write to the Free Software | ||
4174 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
4175 | 17 | * | ||
4176 | 18 | */ | ||
4177 | 19 | |||
4178 | 20 | #ifndef SOLDIERCONTROL_H | ||
4179 | 21 | #define SOLDIERCONTROL_H | ||
4180 | 22 | |||
4181 | 23 | #include <vector> | ||
4182 | 24 | |||
4183 | 25 | namespace Widelands { | ||
4184 | 26 | |||
4185 | 27 | class Soldier; | ||
4186 | 28 | |||
4187 | 29 | /** | ||
4188 | 30 | * This interface is implemented by buildings that explicitly house soldiers. | ||
4189 | 31 | * | ||
4190 | 32 | * It is used to implement queries for building UI and to implement commands | ||
4191 | 33 | * that change the soldiers stationed in a building. | ||
4192 | 34 | * | ||
4193 | 35 | * Soldiers are \em stationed in a building if that building is their | ||
4194 | 36 | * \ref Worker::location. Stationed soldiers are \em present in a building | ||
4195 | 37 | * if their current position is inside the building. So for a TrainingSite, | ||
4196 | 38 | * the two concepts are equal. However, they're different for a MilitarySite, | ||
4197 | 39 | * where soldiers can be outside in combat. | ||
4198 | 40 | */ | ||
4199 | 41 | struct SoldierControl { | ||
4200 | 42 | /** | ||
4201 | 43 | * \return a list of soldiers that are currently present in the building. | ||
4202 | 44 | */ | ||
4203 | 45 | virtual std::vector<Soldier *> presentSoldiers() const = 0; | ||
4204 | 46 | |||
4205 | 47 | /** | ||
4206 | 48 | * \return a list of soldiers that are currently stationed in the building. | ||
4207 | 49 | */ | ||
4208 | 50 | virtual std::vector<Soldier *> stationedSoldiers() const = 0; | ||
4209 | 51 | |||
4210 | 52 | /** | ||
4211 | 53 | * \return the minimum number of soldiers that this building can be | ||
4212 | 54 | * configured to hold. | ||
4213 | 55 | */ | ||
4214 | 56 | virtual uint32_t minSoldierCapacity() const = 0; | ||
4215 | 57 | |||
4216 | 58 | /** | ||
4217 | 59 | * \return the maximum number of soldiers that this building can be | ||
4218 | 60 | * configured to hold. | ||
4219 | 61 | */ | ||
4220 | 62 | virtual uint32_t maxSoldierCapacity() const = 0; | ||
4221 | 63 | |||
4222 | 64 | /** | ||
4223 | 65 | * \return the number of soldiers this building is configured to hold | ||
4224 | 66 | * right now. | ||
4225 | 67 | */ | ||
4226 | 68 | virtual uint32_t soldierCapacity() const = 0; | ||
4227 | 69 | |||
4228 | 70 | /** | ||
4229 | 71 | * Sets the capacity for soldiers of this building. | ||
4230 | 72 | * | ||
4231 | 73 | * New soldiers will be requested and old soldiers will be evicted | ||
4232 | 74 | * as necessary. | ||
4233 | 75 | */ | ||
4234 | 76 | virtual void setSoldierCapacity(uint32_t capacity) = 0; | ||
4235 | 77 | |||
4236 | 78 | void changeSoldierCapacity(int32_t const difference) { | ||
4237 | 79 | uint32_t const old_capacity = soldierCapacity(); | ||
4238 | 80 | uint32_t const new_capacity = | ||
4239 | 81 | std::min | ||
4240 | 82 | (static_cast<uint32_t> | ||
4241 | 83 | (std::max | ||
4242 | 84 | (static_cast<int32_t>(old_capacity) + difference, | ||
4243 | 85 | static_cast<int32_t>(minSoldierCapacity()))), | ||
4244 | 86 | maxSoldierCapacity()); | ||
4245 | 87 | if (old_capacity != new_capacity) | ||
4246 | 88 | setSoldierCapacity(new_capacity); | ||
4247 | 89 | } | ||
4248 | 90 | |||
4249 | 91 | /** | ||
4250 | 92 | * Evict the given soldier from the building immediately, | ||
4251 | 93 | * without changing the building's capacity. | ||
4252 | 94 | * | ||
4253 | 95 | * \note This has no effect if the soldier is currently involved in a battle | ||
4254 | 96 | * or otherwise blocked from leaving the building. | ||
4255 | 97 | */ | ||
4256 | 98 | virtual void dropSoldier(Soldier &) = 0; | ||
4257 | 99 | |||
4258 | 100 | /** | ||
4259 | 101 | * Add a new soldier into this site. Returns -1 if there is no space | ||
4260 | 102 | * for him, 0 on success | ||
4261 | 103 | */ | ||
4262 | 104 | virtual int incorporateSoldier(Editor_Game_Base &, Soldier &) = 0; | ||
4263 | 105 | |||
4264 | 106 | /** | ||
4265 | 107 | * Remove a soldier from the internal list. Most SoldierControls will be | ||
4266 | 108 | * informed by the soldier when it is removed, but WareHouses for example | ||
4267 | 109 | * will not. | ||
4268 | 110 | */ | ||
4269 | 111 | virtual int outcorporateSoldier(Editor_Game_Base &, Soldier &) {return 0;} | ||
4270 | 112 | |||
4271 | 113 | protected: | ||
4272 | 114 | virtual ~SoldierControl() {} | ||
4273 | 115 | }; | ||
4274 | 116 | |||
4275 | 117 | } | ||
4276 | 118 | |||
4277 | 119 | #endif // SOLDIERCONTROL_H | ||
4278 | 120 | 0 | ||
4279 | === added file 'src/logic/storage.h' | |||
4280 | --- src/logic/storage.h 1970-01-01 00:00:00 +0000 | |||
4281 | +++ src/logic/storage.h 2013-08-10 10:53:03 +0000 | |||
4282 | @@ -0,0 +1,195 @@ | |||
4283 | 1 | /* | ||
4284 | 2 | * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team | ||
4285 | 3 | * | ||
4286 | 4 | * This program is free software; you can redistribute it and/or | ||
4287 | 5 | * modify it under the terms of the GNU General Public License | ||
4288 | 6 | * as published by the Free Software Foundation; either version 2 | ||
4289 | 7 | * of the License, or (at your option) any later version. | ||
4290 | 8 | * | ||
4291 | 9 | * This program is distributed in the hope that it will be useful, | ||
4292 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4293 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4294 | 12 | * GNU General Public License for more details. | ||
4295 | 13 | * | ||
4296 | 14 | * You should have received a copy of the GNU General Public License | ||
4297 | 15 | * along with this program; if not, write to the Free Software | ||
4298 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
4299 | 17 | * | ||
4300 | 18 | */ | ||
4301 | 19 | |||
4302 | 20 | #ifndef STORAGE_H | ||
4303 | 21 | #define STORAGE_H | ||
4304 | 22 | |||
4305 | 23 | #include <vector> | ||
4306 | 24 | |||
4307 | 25 | #include "logic/requirements.h" | ||
4308 | 26 | #include "logic/wareworker.h" | ||
4309 | 27 | #include "logic/widelands.h" | ||
4310 | 28 | |||
4311 | 29 | namespace Widelands { | ||
4312 | 30 | |||
4313 | 31 | class Building; | ||
4314 | 32 | class Worker; | ||
4315 | 33 | class Editor_Game_Base; | ||
4316 | 34 | class Game; | ||
4317 | 35 | class WareInstance; | ||
4318 | 36 | class WareList; | ||
4319 | 37 | class Player; | ||
4320 | 38 | |||
4321 | 39 | /** | ||
4322 | 40 | * A storage represents wares and workers stocks. It is owned by StrorageOwner buildings. | ||
4323 | 41 | * This interface contains various method used to deal with wares requests, prioriies | ||
4324 | 42 | * and disponibility. | ||
4325 | 43 | */ | ||
4326 | 44 | class Storage { | ||
4327 | 45 | public: | ||
4328 | 46 | /** | ||
4329 | 47 | * Each ware and worker type has an associated per-storage | ||
4330 | 48 | * stock policy that defines whether it will be stocked by this | ||
4331 | 49 | * warehouse. | ||
4332 | 50 | * | ||
4333 | 51 | * \note The values of this enum are written directly into savegames, | ||
4334 | 52 | * so be careful when changing them. | ||
4335 | 53 | */ | ||
4336 | 54 | enum class StockPolicy : uint8_t { | ||
4337 | 55 | /** | ||
4338 | 56 | * The default policy allows stocking wares without any special priority. | ||
4339 | 57 | */ | ||
4340 | 58 | Normal = 0, | ||
4341 | 59 | |||
4342 | 60 | /** | ||
4343 | 61 | * As long as there are warehouses with this policy for a ware, all | ||
4344 | 62 | * available unstocked supplies will be transferred to warehouses | ||
4345 | 63 | * with this policy. | ||
4346 | 64 | */ | ||
4347 | 65 | Prefer = 1, | ||
4348 | 66 | |||
4349 | 67 | /** | ||
4350 | 68 | * If a ware has this stock policy, no new items of this ware will enter | ||
4351 | 69 | * the warehouse. | ||
4352 | 70 | */ | ||
4353 | 71 | DontStock = 2, | ||
4354 | 72 | |||
4355 | 73 | /** | ||
4356 | 74 | * Like \ref SP_DontStock, but in addition, existing stock of this ware | ||
4357 | 75 | * will be transported out of the warehouse over time. | ||
4358 | 76 | */ | ||
4359 | 77 | Remove = 3, | ||
4360 | 78 | }; | ||
4361 | 79 | |||
4362 | 80 | /** | ||
4363 | 81 | * \return the player that own this storage | ||
4364 | 82 | */ | ||
4365 | 83 | virtual Player & owner() const = 0; | ||
4366 | 84 | /** | ||
4367 | 85 | * \return the wares present in this storage | ||
4368 | 86 | */ | ||
4369 | 87 | virtual const WareList & get_wares() const = 0; | ||
4370 | 88 | /** | ||
4371 | 89 | * \return the workers present in this storage | ||
4372 | 90 | */ | ||
4373 | 91 | virtual const WareList & get_workers() const = 0; | ||
4374 | 92 | /** | ||
4375 | 93 | * Increase the stock of the specified ware type | ||
4376 | 94 | */ | ||
4377 | 95 | virtual void insert_wares (Ware_Index, uint32_t count) = 0; | ||
4378 | 96 | /** | ||
4379 | 97 | * Decrease the stock of the specified ware type | ||
4380 | 98 | */ | ||
4381 | 99 | virtual void remove_wares (Ware_Index, uint32_t count) = 0; | ||
4382 | 100 | /** | ||
4383 | 101 | * Increase the stock of the specified worker type | ||
4384 | 102 | */ | ||
4385 | 103 | virtual void insert_workers(Ware_Index, uint32_t count) = 0; | ||
4386 | 104 | /** | ||
4387 | 105 | * Decrease the stock of the specified worker type | ||
4388 | 106 | */ | ||
4389 | 107 | virtual void remove_workers(Ware_Index, uint32_t count) = 0; | ||
4390 | 108 | /** | ||
4391 | 109 | * Get a specified ware from the storage. | ||
4392 | 110 | * \return the wareinstance | ||
4393 | 111 | */ | ||
4394 | 112 | virtual WareInstance & launch_ware(Game &, Ware_Index) = 0; | ||
4395 | 113 | /** | ||
4396 | 114 | * Launch a ware already instanciated | ||
4397 | 115 | */ | ||
4398 | 116 | virtual void do_launch_ware(Game &, WareInstance&) = 0; | ||
4399 | 117 | /** | ||
4400 | 118 | * Adds the specified ware to the storage. The ware might | ||
4401 | 119 | * be removed from the game following this call. | ||
4402 | 120 | */ | ||
4403 | 121 | virtual void incorporate_ware(Editor_Game_Base &, WareInstance &) = 0; | ||
4404 | 122 | /** | ||
4405 | 123 | * Get the specified worker from the storage. | ||
4406 | 124 | * \return the worker | ||
4407 | 125 | */ | ||
4408 | 126 | virtual Worker & launch_worker(Game &, Ware_Index, const Requirements & = Requirements()) = 0; | ||
4409 | 127 | /** | ||
4410 | 128 | * Adds the specified worker to the storage. The worker might | ||
4411 | 129 | * be removed from the game following this call. | ||
4412 | 130 | */ | ||
4413 | 131 | virtual void incorporate_worker(Editor_Game_Base &, Worker &) = 0; | ||
4414 | 132 | /** | ||
4415 | 133 | * \return the storage stock policy for the specified ware | ||
4416 | 134 | */ | ||
4417 | 135 | virtual StockPolicy get_ware_policy(Ware_Index ware) const = 0; | ||
4418 | 136 | /** | ||
4419 | 137 | * \return the storage stock policy for the specified worker | ||
4420 | 138 | */ | ||
4421 | 139 | virtual StockPolicy get_worker_policy(Ware_Index ware) const = 0; | ||
4422 | 140 | /** | ||
4423 | 141 | * \return the sotrage stock policy for the specified ware or worker | ||
4424 | 142 | */ | ||
4425 | 143 | virtual StockPolicy get_stock_policy(WareWorker waretype, Ware_Index wareindex) const = 0; | ||
4426 | 144 | /** | ||
4427 | 145 | * Set the storage stock policy for the specified ware | ||
4428 | 146 | */ | ||
4429 | 147 | virtual void set_ware_policy(Ware_Index ware, StockPolicy policy) = 0; | ||
4430 | 148 | /** | ||
4431 | 149 | * Set the storage stock policy for the specified worker | ||
4432 | 150 | */ | ||
4433 | 151 | virtual void set_worker_policy(Ware_Index ware, StockPolicy policy) = 0; | ||
4434 | 152 | /** | ||
4435 | 153 | * Return true if the storage has all requirement in stock to create | ||
4436 | 154 | * the specified worker | ||
4437 | 155 | */ | ||
4438 | 156 | virtual bool can_create_worker(Game& game, Ware_Index ware_index) = 0; | ||
4439 | 157 | /** | ||
4440 | 158 | * Create a worker. | ||
4441 | 159 | */ | ||
4442 | 160 | virtual void create_worker(Game& game, Ware_Index worker_idx) = 0; | ||
4443 | 161 | /** | ||
4444 | 162 | * Return the amount of planned worker of the given worker idx | ||
4445 | 163 | */ | ||
4446 | 164 | virtual uint32_t get_planned_workers(Game &, Ware_Index index) const = 0; | ||
4447 | 165 | /** | ||
4448 | 166 | * Plan to create the specified workers | ||
4449 | 167 | */ | ||
4450 | 168 | virtual void plan_workers(Game &, Ware_Index index, uint32_t amount) = 0; | ||
4451 | 169 | /** | ||
4452 | 170 | * Calculate the supply of wares available to this warehouse in each of the | ||
4453 | 171 | * buildcost items for the given worker. | ||
4454 | 172 | * | ||
4455 | 173 | * This is the current stock plus any incoming transfers. | ||
4456 | 174 | */ | ||
4457 | 175 | virtual std::vector<uint32_t> calc_available_for_worker(Game &, Ware_Index index) const = 0; | ||
4458 | 176 | }; | ||
4459 | 177 | |||
4460 | 178 | /** | ||
4461 | 179 | * A Storage owner holds a sorage instance. | ||
4462 | 180 | */ | ||
4463 | 181 | class StorageOwner { | ||
4464 | 182 | public: | ||
4465 | 183 | /** | ||
4466 | 184 | * Return the storage instance | ||
4467 | 185 | */ | ||
4468 | 186 | virtual Storage* get_storage() const = 0; | ||
4469 | 187 | /** | ||
4470 | 188 | * Return the building owning the storage | ||
4471 | 189 | */ | ||
4472 | 190 | virtual Building* get_building() = 0; | ||
4473 | 191 | }; | ||
4474 | 192 | |||
4475 | 193 | } | ||
4476 | 194 | |||
4477 | 195 | #endif | ||
4478 | 0 | 196 | ||
4479 | === added file 'src/logic/storagehandler.cc' | |||
4480 | --- src/logic/storagehandler.cc 1970-01-01 00:00:00 +0000 | |||
4481 | +++ src/logic/storagehandler.cc 2013-08-10 10:53:03 +0000 | |||
4482 | @@ -0,0 +1,1127 @@ | |||
4483 | 1 | /* | ||
4484 | 2 | * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team | ||
4485 | 3 | * | ||
4486 | 4 | * This program is free software; you can redistribute it and/or | ||
4487 | 5 | * modify it under the terms of the GNU General Public License | ||
4488 | 6 | * as published by the Free Software Foundation; either version 2 | ||
4489 | 7 | * of the License, or (at your option) any later version. | ||
4490 | 8 | * | ||
4491 | 9 | * This program is distributed in the hope that it will be useful, | ||
4492 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4493 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4494 | 12 | * GNU General Public License for more details. | ||
4495 | 13 | * | ||
4496 | 14 | * You should have received a copy of the GNU General Public License | ||
4497 | 15 | * along with this program; if not, write to the Free Software | ||
4498 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
4499 | 17 | * | ||
4500 | 18 | */ | ||
4501 | 19 | |||
4502 | 20 | #include "logic/storagehandler.h" | ||
4503 | 21 | |||
4504 | 22 | #include <utility> | ||
4505 | 23 | |||
4506 | 24 | #include <boost/foreach.hpp> | ||
4507 | 25 | |||
4508 | 26 | #include "economy/economy.h" | ||
4509 | 27 | #include "economy/flag.h" | ||
4510 | 28 | #include "helper.h" | ||
4511 | 29 | #include "logic/player.h" | ||
4512 | 30 | #include "logic/soldier.h" | ||
4513 | 31 | #include "upcast.h" | ||
4514 | 32 | |||
4515 | 33 | namespace Widelands { | ||
4516 | 34 | |||
4517 | 35 | //************************************************************ | ||
4518 | 36 | // CLASS Storage Handler | ||
4519 | 37 | //************************************************************ | ||
4520 | 38 | |||
4521 | 39 | StorageHandler::StorageHandler(Building& building) | ||
4522 | 40 | : m_building(building), | ||
4523 | 41 | m_supply(new StorageSupply(this)) | ||
4524 | 42 | { | ||
4525 | 43 | } | ||
4526 | 44 | |||
4527 | 45 | StorageHandler::~StorageHandler() | ||
4528 | 46 | { | ||
4529 | 47 | } | ||
4530 | 48 | |||
4531 | 49 | |||
4532 | 50 | void StorageHandler::init(Editor_Game_Base&) | ||
4533 | 51 | { | ||
4534 | 52 | Ware_Index const nr_wares = owner().tribe().get_nrwares (); | ||
4535 | 53 | Ware_Index const nr_workers = owner().tribe().get_nrworkers(); | ||
4536 | 54 | m_supply->set_nrwares (nr_wares); | ||
4537 | 55 | m_supply->set_nrworkers(nr_workers); | ||
4538 | 56 | m_ware_policy.resize(nr_wares.value(), Storage::StockPolicy::Normal); | ||
4539 | 57 | m_worker_policy.resize(nr_workers.value(), Storage::StockPolicy::Normal); | ||
4540 | 58 | |||
4541 | 59 | // Init autospawn | ||
4542 | 60 | const std::vector <Widelands::Ware_Index> worker_types_without_cost = | ||
4543 | 61 | owner().tribe().worker_types_without_cost(); | ||
4544 | 62 | BOOST_FOREACH(Ware_Index idx, worker_types_without_cost) { | ||
4545 | 63 | const Worker_Descr & worker_descr = *owner().tribe().get_worker_descr(idx); | ||
4546 | 64 | if (not worker_descr.is_buildable()) { | ||
4547 | 65 | continue; | ||
4548 | 66 | } | ||
4549 | 67 | if (!owner().is_worker_type_allowed(idx)) { | ||
4550 | 68 | continue; | ||
4551 | 69 | } | ||
4552 | 70 | if (worker_descr.buildcost().empty()) { | ||
4553 | 71 | // Workers of this type can be spawned in warehouses. Start it. | ||
4554 | 72 | add_worker_spawn(idx); | ||
4555 | 73 | } | ||
4556 | 74 | } | ||
4557 | 75 | } | ||
4558 | 76 | |||
4559 | 77 | void StorageHandler::load_finish(Editor_Game_Base&) | ||
4560 | 78 | { | ||
4561 | 79 | // Ensure consistency of PlannedWorker requests | ||
4562 | 80 | uint32_t pwidx = 0; | ||
4563 | 81 | while (pwidx < m_planned_workers.size()) { | ||
4564 | 82 | if (!load_finish_planned_workers(m_planned_workers[pwidx])) { | ||
4565 | 83 | m_planned_workers[pwidx].cleanup(); | ||
4566 | 84 | m_planned_workers.erase(m_planned_workers.begin() + pwidx); | ||
4567 | 85 | } else { | ||
4568 | 86 | pwidx++; | ||
4569 | 87 | } | ||
4570 | 88 | } | ||
4571 | 89 | // Verify autospawning for free workers | ||
4572 | 90 | const std::vector <Widelands::Ware_Index> worker_types_without_cost = | ||
4573 | 91 | owner().tribe().worker_types_without_cost(); | ||
4574 | 92 | BOOST_FOREACH(Ware_Index idx, worker_types_without_cost) { | ||
4575 | 93 | if (!owner().is_worker_type_allowed(idx)) { | ||
4576 | 94 | continue; | ||
4577 | 95 | } | ||
4578 | 96 | if (is_worker_spawn_set(idx)) { | ||
4579 | 97 | continue; | ||
4580 | 98 | } | ||
4581 | 99 | add_worker_spawn(idx); | ||
4582 | 100 | log | ||
4583 | 101 | ("WARNING: player %u is allowed to create worker type %s but his " | ||
4584 | 102 | "%s %u at (%i, %i) does not have spawning set for that " | ||
4585 | 103 | "worker type; setting it to default values\n", | ||
4586 | 104 | owner().player_number(), | ||
4587 | 105 | owner().tribe().get_worker_descr(idx)->descname().c_str(), | ||
4588 | 106 | m_building.descname().c_str(), m_building.serial(), | ||
4589 | 107 | m_building.get_position().x, m_building.get_position().y); | ||
4590 | 108 | } | ||
4591 | 109 | } | ||
4592 | 110 | |||
4593 | 111 | |||
4594 | 112 | void StorageHandler::cleanup(Editor_Game_Base&) | ||
4595 | 113 | { | ||
4596 | 114 | while (!m_planned_workers.empty()) { | ||
4597 | 115 | m_planned_workers.back().cleanup(); | ||
4598 | 116 | m_planned_workers.pop_back(); | ||
4599 | 117 | } | ||
4600 | 118 | } | ||
4601 | 119 | |||
4602 | 120 | //TODO return a value so the owner can schedule_act | ||
4603 | 121 | uint32_t StorageHandler::act(Game& game) | ||
4604 | 122 | { | ||
4605 | 123 | uint32_t gametime = static_cast<uint32_t>(game.get_gametime()); | ||
4606 | 124 | uint32_t spawn_act = update_spawns(game, gametime); | ||
4607 | 125 | uint32_t removal_act = update_removals(game, gametime); | ||
4608 | 126 | // Update planned workers; this is to update the request amounts and | ||
4609 | 127 | // check because whether we suddenly can produce a requested worker. This | ||
4610 | 128 | // is mostly previously available wares may become unavailable due to | ||
4611 | 129 | // secondary requests. | ||
4612 | 130 | update_all_planned_workers(game); | ||
4613 | 131 | // Act in 5 sec, or before if timers will run down | ||
4614 | 132 | uint32_t min_act = 5000; | ||
4615 | 133 | if (spawn_act > 0 && spawn_act < min_act) { | ||
4616 | 134 | min_act = spawn_act; | ||
4617 | 135 | } | ||
4618 | 136 | if (removal_act > 0 && removal_act < min_act) { | ||
4619 | 137 | min_act = removal_act; | ||
4620 | 138 | } | ||
4621 | 139 | return min_act; | ||
4622 | 140 | } | ||
4623 | 141 | |||
4624 | 142 | void StorageHandler::set_economy(Economy* economy) | ||
4625 | 143 | { | ||
4626 | 144 | Economy * const old = m_building.get_economy(); | ||
4627 | 145 | |||
4628 | 146 | if (old == economy) { | ||
4629 | 147 | return; | ||
4630 | 148 | } | ||
4631 | 149 | |||
4632 | 150 | if (old) { | ||
4633 | 151 | old->remove_storage(*this); | ||
4634 | 152 | } | ||
4635 | 153 | |||
4636 | 154 | m_supply->set_economy(economy); | ||
4637 | 155 | |||
4638 | 156 | container_iterate_const(std::vector<PlannedWorkers>, m_planned_workers, pw_it) { | ||
4639 | 157 | container_iterate_const(std::vector<Request *>, pw_it.current->requests, req_it) { | ||
4640 | 158 | (*req_it.current)->set_economy(economy); | ||
4641 | 159 | } | ||
4642 | 160 | } | ||
4643 | 161 | |||
4644 | 162 | if (economy) { | ||
4645 | 163 | economy->add_storage(*this); | ||
4646 | 164 | } | ||
4647 | 165 | } | ||
4648 | 166 | |||
4649 | 167 | uint32_t StorageHandler::count_workers(Game& game, Ware_Index idx, const Requirements& req) | ||
4650 | 168 | { | ||
4651 | 169 | uint32_t stock = m_supply->stock_workers(idx); | ||
4652 | 170 | if (stock <= 0) { | ||
4653 | 171 | return stock; | ||
4654 | 172 | } | ||
4655 | 173 | uint32_t matching = 0; | ||
4656 | 174 | // Get list of those for which we stored the attributes | ||
4657 | 175 | // This is similar logic than in launch_worker | ||
4658 | 176 | std::vector<const StockedWorkerAtr*> workers_with_atr; | ||
4659 | 177 | BOOST_FOREACH(StockedWorkerAtr& atr, m_stocked_workers_atr) { | ||
4660 | 178 | if (atr.index == idx) { | ||
4661 | 179 | workers_with_atr.push_back(&atr); | ||
4662 | 180 | } | ||
4663 | 181 | } | ||
4664 | 182 | // First check those without atr | ||
4665 | 183 | Worker* w; | ||
4666 | 184 | bool checkpass = false; | ||
4667 | 185 | const Worker_Descr & workerdescr = *owner().tribe().get_worker_descr(idx); | ||
4668 | 186 | if (stock > workers_with_atr.size()) { | ||
4669 | 187 | w = &workerdescr.create(game, owner(), &m_building, m_building.get_position()); | ||
4670 | 188 | checkpass = req.check(*w); | ||
4671 | 189 | if (checkpass) { | ||
4672 | 190 | matching += stock - workers_with_atr.size(); | ||
4673 | 191 | } | ||
4674 | 192 | w->remove(game); | ||
4675 | 193 | } | ||
4676 | 194 | // Check with our atr | ||
4677 | 195 | // TODO CGH use smarter way of storing atr, maybe with map | ||
4678 | 196 | BOOST_FOREACH(const StockedWorkerAtr* atr, workers_with_atr) { | ||
4679 | 197 | w = create_with_atr(game, *atr); | ||
4680 | 198 | checkpass = req.check(*w); | ||
4681 | 199 | if (checkpass) { | ||
4682 | 200 | matching++; | ||
4683 | 201 | } | ||
4684 | 202 | w->remove(game); | ||
4685 | 203 | } | ||
4686 | 204 | return matching; | ||
4687 | 205 | } | ||
4688 | 206 | |||
4689 | 207 | |||
4690 | 208 | void StorageHandler::launch_all_workers(Game & game, bool exp_only, const WareList& excluded) | ||
4691 | 209 | { | ||
4692 | 210 | if (!exp_only) { | ||
4693 | 211 | for (Ware_Index id = Ware_Index::First(); id < m_supply->get_workers().get_nrwareids(); ++id) { | ||
4694 | 212 | if (excluded.stock(id)) { | ||
4695 | 213 | continue; | ||
4696 | 214 | } | ||
4697 | 215 | const uint32_t stock = m_supply->get_workers().stock(id); | ||
4698 | 216 | if (stock > 0) { | ||
4699 | 217 | for (uint32_t i = 0; i < stock; ++i) { | ||
4700 | 218 | launch_worker(game, id).start_task_leavebuilding(game, true); | ||
4701 | 219 | } | ||
4702 | 220 | } | ||
4703 | 221 | } | ||
4704 | 222 | return; | ||
4705 | 223 | } | ||
4706 | 224 | BOOST_FOREACH(StockedWorkerAtr atr, m_stocked_workers_atr) { | ||
4707 | 225 | if (excluded.stock(atr.index)) { | ||
4708 | 226 | continue; | ||
4709 | 227 | } | ||
4710 | 228 | if (m_supply->get_workers().stock(atr.index) <= 0) { | ||
4711 | 229 | continue; | ||
4712 | 230 | } | ||
4713 | 231 | Worker* w = create_with_atr(game, atr); | ||
4714 | 232 | w->start_task_leavebuilding(game, true); | ||
4715 | 233 | m_supply->remove_workers(atr.index, 1); | ||
4716 | 234 | } | ||
4717 | 235 | } | ||
4718 | 236 | |||
4719 | 237 | void StorageHandler::add_ware_spawn | ||
4720 | 238 | (const Ware_Index idx, uint32_t interval, uint32_t stock_max, uint32_t counter, bool dont_exceed) | ||
4721 | 239 | { | ||
4722 | 240 | if (m_spawn_wares.count(idx)) { | ||
4723 | 241 | remove_ware_spawn(idx); | ||
4724 | 242 | } | ||
4725 | 243 | if (dont_exceed) { | ||
4726 | 244 | std::vector<uint32_t> values = {interval, interval, stock_max}; | ||
4727 | 245 | m_spawn_wares.insert(std::make_pair(idx, values)); | ||
4728 | 246 | } else { | ||
4729 | 247 | std::vector<uint32_t> values = {interval, interval, stock_max, counter}; | ||
4730 | 248 | m_spawn_wares.insert(std::make_pair(idx, values)); | ||
4731 | 249 | } | ||
4732 | 250 | } | ||
4733 | 251 | |||
4734 | 252 | void StorageHandler::remove_ware_spawn(const Ware_Index idx) | ||
4735 | 253 | { | ||
4736 | 254 | m_spawn_wares.erase(idx); | ||
4737 | 255 | } | ||
4738 | 256 | bool StorageHandler::is_ware_spawn_set(Ware_Index idx) | ||
4739 | 257 | { | ||
4740 | 258 | return m_spawn_wares.count(idx); | ||
4741 | 259 | } | ||
4742 | 260 | |||
4743 | 261 | |||
4744 | 262 | void StorageHandler::add_worker_spawn | ||
4745 | 263 | (const Ware_Index idx, uint32_t interval, uint32_t stock_max, uint32_t counter, bool dont_exceed) | ||
4746 | 264 | { | ||
4747 | 265 | if (m_spawn_workers.count(idx)) { | ||
4748 | 266 | remove_worker_spawn(idx); | ||
4749 | 267 | } | ||
4750 | 268 | if (dont_exceed) { | ||
4751 | 269 | std::vector<uint32_t> values = {interval, interval, stock_max}; | ||
4752 | 270 | m_spawn_workers.insert(std::make_pair(idx, values)); | ||
4753 | 271 | } else { | ||
4754 | 272 | std::vector<uint32_t> values = {interval, interval, stock_max, counter}; | ||
4755 | 273 | m_spawn_workers.insert(std::make_pair(idx, values)); | ||
4756 | 274 | } | ||
4757 | 275 | } | ||
4758 | 276 | |||
4759 | 277 | void StorageHandler::remove_worker_spawn(const Ware_Index idx) | ||
4760 | 278 | { | ||
4761 | 279 | m_spawn_workers.erase(idx); | ||
4762 | 280 | } | ||
4763 | 281 | bool StorageHandler::is_worker_spawn_set(Ware_Index idx) | ||
4764 | 282 | { | ||
4765 | 283 | return m_spawn_workers.count(idx); | ||
4766 | 284 | } | ||
4767 | 285 | |||
4768 | 286 | // | ||
4769 | 287 | // | ||
4770 | 288 | // Storage implementation | ||
4771 | 289 | // | ||
4772 | 290 | // | ||
4773 | 291 | |||
4774 | 292 | Player& StorageHandler::owner() const | ||
4775 | 293 | { | ||
4776 | 294 | return m_building.owner(); | ||
4777 | 295 | } | ||
4778 | 296 | |||
4779 | 297 | const WareList& StorageHandler::get_wares() const | ||
4780 | 298 | { | ||
4781 | 299 | return m_supply->get_wares(); | ||
4782 | 300 | } | ||
4783 | 301 | |||
4784 | 302 | const WareList& StorageHandler::get_workers() const | ||
4785 | 303 | { | ||
4786 | 304 | return m_supply->get_workers(); | ||
4787 | 305 | } | ||
4788 | 306 | |||
4789 | 307 | void StorageHandler::insert_wares(Ware_Index idx, uint32_t count) | ||
4790 | 308 | { | ||
4791 | 309 | m_supply->add_wares(idx, count); | ||
4792 | 310 | } | ||
4793 | 311 | |||
4794 | 312 | void StorageHandler::remove_wares(Ware_Index idx, uint32_t count) | ||
4795 | 313 | { | ||
4796 | 314 | m_supply->remove_wares(idx, count); | ||
4797 | 315 | } | ||
4798 | 316 | |||
4799 | 317 | void StorageHandler::insert_workers(Ware_Index idx, uint32_t count) | ||
4800 | 318 | { | ||
4801 | 319 | m_supply->add_workers(idx, count); | ||
4802 | 320 | } | ||
4803 | 321 | |||
4804 | 322 | void StorageHandler::remove_workers(Ware_Index idx, uint32_t count) | ||
4805 | 323 | { | ||
4806 | 324 | m_supply->remove_workers(idx, count); | ||
4807 | 325 | } | ||
4808 | 326 | |||
4809 | 327 | WareInstance& StorageHandler::launch_ware(Game& game, Ware_Index idx) | ||
4810 | 328 | { | ||
4811 | 329 | WareInstance & item = *new WareInstance(idx, owner().tribe().get_ware_descr(idx)); | ||
4812 | 330 | item.init(game); | ||
4813 | 331 | do_launch_ware(game, item); | ||
4814 | 332 | |||
4815 | 333 | m_supply->remove_wares(idx, 1); | ||
4816 | 334 | |||
4817 | 335 | return item; | ||
4818 | 336 | } | ||
4819 | 337 | |||
4820 | 338 | |||
4821 | 339 | void StorageHandler::do_launch_ware(Game& game, WareInstance& ware_inst) | ||
4822 | 340 | { | ||
4823 | 341 | // Create a carrier | ||
4824 | 342 | Ware_Index const carrierid = owner().tribe().worker_index("carrier"); | ||
4825 | 343 | const Worker_Descr & workerdescr = *owner().tribe().get_worker_descr(carrierid); | ||
4826 | 344 | |||
4827 | 345 | Worker & worker = workerdescr.create(game, owner(), &m_building, m_building.get_position()); | ||
4828 | 346 | |||
4829 | 347 | // Yup, this is cheating. | ||
4830 | 348 | if (m_supply->stock_workers(carrierid)) | ||
4831 | 349 | m_supply->remove_workers(carrierid, 1); | ||
4832 | 350 | |||
4833 | 351 | // Setup the carrier | ||
4834 | 352 | worker.start_task_dropoff(game, ware_inst); | ||
4835 | 353 | } | ||
4836 | 354 | |||
4837 | 355 | |||
4838 | 356 | void StorageHandler::incorporate_ware(Editor_Game_Base& egbase, WareInstance& item) | ||
4839 | 357 | { | ||
4840 | 358 | m_supply->add_wares(item.descr_index(), 1); | ||
4841 | 359 | return item.destroy(egbase); | ||
4842 | 360 | } | ||
4843 | 361 | |||
4844 | 362 | Worker& StorageHandler::launch_worker(Game& game, Ware_Index idx, const Requirements& req) | ||
4845 | 363 | { | ||
4846 | 364 | do { | ||
4847 | 365 | uint32_t stock = m_supply->stock_workers(idx); | ||
4848 | 366 | if (stock > 0) { | ||
4849 | 367 | // Get list of those for which we stored the attributes, as pointers to actual objects | ||
4850 | 368 | // TODO smarter storage for atrs | ||
4851 | 369 | std::vector<const StockedWorkerAtr*> workers_with_atr; | ||
4852 | 370 | for | ||
4853 | 371 | (std::vector<StockedWorkerAtr>::iterator it = m_stocked_workers_atr.begin(); | ||
4854 | 372 | it != m_stocked_workers_atr.end(); ++it) | ||
4855 | 373 | { | ||
4856 | 374 | if (it->index == idx) { | ||
4857 | 375 | workers_with_atr.push_back(&(*it)); | ||
4858 | 376 | } | ||
4859 | 377 | } | ||
4860 | 378 | // First check if one without atr is enough | ||
4861 | 379 | Worker* w; | ||
4862 | 380 | if (stock > workers_with_atr.size()) { | ||
4863 | 381 | const Worker_Descr & workerdescr = *owner().tribe().get_worker_descr(idx); | ||
4864 | 382 | w = &workerdescr.create(game, owner(), &m_building, m_building.get_position()); | ||
4865 | 383 | if (req.check(*w)) { | ||
4866 | 384 | m_supply->remove_workers(idx, 1); | ||
4867 | 385 | return *w; | ||
4868 | 386 | } | ||
4869 | 387 | } | ||
4870 | 388 | // Check with our atr | ||
4871 | 389 | BOOST_FOREACH(const StockedWorkerAtr* atr, workers_with_atr) { | ||
4872 | 390 | w = create_with_atr(game, *atr); | ||
4873 | 391 | if (req.check(*w)) { | ||
4874 | 392 | // We need to find back our atr in original vector to erase it | ||
4875 | 393 | bool removed = false; | ||
4876 | 394 | for | ||
4877 | 395 | (std::vector<StockedWorkerAtr>::iterator it = m_stocked_workers_atr.begin(); | ||
4878 | 396 | it != m_stocked_workers_atr.end(); ++it) | ||
4879 | 397 | { | ||
4880 | 398 | if (&(*it) == atr) { | ||
4881 | 399 | m_stocked_workers_atr.erase(it); | ||
4882 | 400 | removed = true; | ||
4883 | 401 | break; | ||
4884 | 402 | } | ||
4885 | 403 | } | ||
4886 | 404 | assert(removed); | ||
4887 | 405 | m_supply->remove_workers(idx, 1); | ||
4888 | 406 | return *w; | ||
4889 | 407 | } | ||
4890 | 408 | } | ||
4891 | 409 | } | ||
4892 | 410 | // Check if we got the tools to create a new one | ||
4893 | 411 | if (can_create_worker(game, idx)) { | ||
4894 | 412 | // don't want to use an upgraded worker, so create new one. | ||
4895 | 413 | create_worker(game, idx); | ||
4896 | 414 | } else { | ||
4897 | 415 | idx = owner().tribe().get_worker_descr(idx)->becomes(); | ||
4898 | 416 | } | ||
4899 | 417 | } while (idx != Ware_Index::Null()); | ||
4900 | 418 | |||
4901 | 419 | throw wexception | ||
4902 | 420 | ("StorageHandler::launch_worker: worker does not actually exist"); | ||
4903 | 421 | } | ||
4904 | 422 | |||
4905 | 423 | void StorageHandler::incorporate_worker(Editor_Game_Base& egbase, Worker& w) | ||
4906 | 424 | { | ||
4907 | 425 | assert(w.get_owner() == &owner()); | ||
4908 | 426 | // Rescue carried ware | ||
4909 | 427 | if (WareInstance * const item = w.fetch_carried_item(egbase)) { | ||
4910 | 428 | incorporate_ware(egbase, *item); | ||
4911 | 429 | } | ||
4912 | 430 | // Add to supply | ||
4913 | 431 | Ware_Index worker_index = owner().tribe().worker_index(w.name().c_str()); | ||
4914 | 432 | m_supply->add_workers(worker_index, 1); | ||
4915 | 433 | |||
4916 | 434 | // Store the attributes. | ||
4917 | 435 | // FIXME CGH handle soldiers : hp & healing | ||
4918 | 436 | StockedWorkerAtr* atr = store_worker_atr(w); | ||
4919 | 437 | if (atr != nullptr) { | ||
4920 | 438 | m_stocked_workers_atr.push_back(*atr); | ||
4921 | 439 | } | ||
4922 | 440 | // Destroy the instance | ||
4923 | 441 | w.remove(egbase); | ||
4924 | 442 | } | ||
4925 | 443 | |||
4926 | 444 | Storage::StockPolicy StorageHandler::get_ware_policy(Ware_Index ware) const | ||
4927 | 445 | { | ||
4928 | 446 | assert(ware.value() < m_ware_policy.size()); | ||
4929 | 447 | return m_ware_policy[ware.value()]; | ||
4930 | 448 | } | ||
4931 | 449 | |||
4932 | 450 | Storage::StockPolicy StorageHandler::get_worker_policy(Ware_Index ware) const | ||
4933 | 451 | { | ||
4934 | 452 | assert(ware.value() < m_worker_policy.size()); | ||
4935 | 453 | return m_worker_policy[ware.value()]; | ||
4936 | 454 | } | ||
4937 | 455 | |||
4938 | 456 | Storage::StockPolicy StorageHandler::get_stock_policy(WareWorker waretype, Ware_Index wareindex) const | ||
4939 | 457 | { | ||
4940 | 458 | if (waretype == wwWORKER) | ||
4941 | 459 | return get_worker_policy(wareindex); | ||
4942 | 460 | else | ||
4943 | 461 | return get_ware_policy(wareindex); | ||
4944 | 462 | } | ||
4945 | 463 | |||
4946 | 464 | void StorageHandler::set_ware_policy(Ware_Index ware, Storage::StockPolicy policy) | ||
4947 | 465 | { | ||
4948 | 466 | assert(ware.value() < m_ware_policy.size()); | ||
4949 | 467 | m_ware_policy[ware.value()] = policy; | ||
4950 | 468 | } | ||
4951 | 469 | |||
4952 | 470 | void StorageHandler::set_worker_policy(Ware_Index ware, Storage::StockPolicy policy) | ||
4953 | 471 | { | ||
4954 | 472 | assert(ware.value() < m_worker_policy.size()); | ||
4955 | 473 | m_worker_policy[ware.value()] = policy; | ||
4956 | 474 | } | ||
4957 | 475 | |||
4958 | 476 | bool StorageHandler::can_create_worker(Game&, Ware_Index worker_idx) | ||
4959 | 477 | { | ||
4960 | 478 | if (not (worker_idx < m_supply->get_workers().get_nrwareids())) { | ||
4961 | 479 | throw wexception | ||
4962 | 480 | ("worker type %d does not exists (max is %d)", | ||
4963 | 481 | worker_idx.value(), m_supply->get_workers().get_nrwareids().value()); | ||
4964 | 482 | } | ||
4965 | 483 | |||
4966 | 484 | const Worker_Descr & w_desc = *owner().tribe().get_worker_descr(worker_idx); | ||
4967 | 485 | assert(&w_desc); | ||
4968 | 486 | if (not w_desc.is_buildable()) { | ||
4969 | 487 | return false; | ||
4970 | 488 | } | ||
4971 | 489 | |||
4972 | 490 | // see if we have the resources | ||
4973 | 491 | const Worker_Descr::Buildcost & buildcost = w_desc.buildcost(); | ||
4974 | 492 | container_iterate_const(Worker_Descr::Buildcost, buildcost, it) { | ||
4975 | 493 | const std::string & input_name = it.current->first; | ||
4976 | 494 | if (Ware_Index id_w = owner().tribe().ware_index(input_name)) { | ||
4977 | 495 | if (m_supply->stock_wares (id_w) < it.current->second) | ||
4978 | 496 | return false; | ||
4979 | 497 | } else if ((id_w = owner().tribe().worker_index(input_name))) { | ||
4980 | 498 | if (m_supply->stock_workers(id_w) < it.current->second) | ||
4981 | 499 | return false; | ||
4982 | 500 | } else | ||
4983 | 501 | throw wexception | ||
4984 | 502 | ("worker type %s needs \"%s\" to be built but that is neither " | ||
4985 | 503 | "a ware type nor a worker type defined in the tribe %s", | ||
4986 | 504 | w_desc.descname().c_str(), input_name.c_str(), | ||
4987 | 505 | owner().tribe().name().c_str()); | ||
4988 | 506 | } | ||
4989 | 507 | return true; | ||
4990 | 508 | } | ||
4991 | 509 | |||
4992 | 510 | void StorageHandler::create_worker(Game& game, Ware_Index worker_idx) | ||
4993 | 511 | { | ||
4994 | 512 | assert(can_create_worker (game, worker_idx)); | ||
4995 | 513 | |||
4996 | 514 | const Worker_Descr & w_desc = *owner().tribe().get_worker_descr(worker_idx); | ||
4997 | 515 | const Worker_Descr::Buildcost & buildcost = w_desc.buildcost(); | ||
4998 | 516 | container_iterate_const(Worker_Descr::Buildcost, buildcost, i) { | ||
4999 | 517 | const std::string & input = i.current->first; | ||
5000 | 518 | if (Ware_Index const id_ware = owner().tribe().ware_index(input)) { |
that is a lot of code. I will review after I am done with the log_messages one.