Merge lp:~widelands-dev/widelands/bug-987510 into lp:widelands

Proposed by GunChleoc
Status: Merged
Merged at revision: 7339
Proposed branch: lp:~widelands-dev/widelands/bug-987510
Merge into: lp:widelands
Diff against target: 3767 lines (+1236/-756)
24 files modified
src/logic/building.cc (+2/-2)
src/logic/building.h (+2/-1)
src/logic/cmd_luacoroutine.cc (+1/-1)
src/logic/message.h (+53/-16)
src/logic/message_queue.h (+21/-21)
src/logic/militarysite.cc (+4/-4)
src/logic/player.cc (+7/-7)
src/logic/player.h (+1/-1)
src/logic/playercommand.cc (+2/-2)
src/logic/productionsite.cc (+1/-1)
src/logic/ship.cc (+402/-377)
src/logic/ship.h (+1/-2)
src/logic/soldier.cc (+2/-2)
src/logic/warehouse.cc (+388/-233)
src/logic/worker.cc (+14/-2)
src/map_io/map_players_messages_packet.cc (+14/-14)
src/scripting/lua_game.cc (+14/-31)
src/scripting/lua_game.h (+0/-1)
src/wui/game_message_menu.cc (+283/-28)
src/wui/game_message_menu.h (+14/-0)
src/wui/interactive_player.cc (+1/-1)
test/maps/lua_persistence.wmf/scripting/test_persistence.lua (+1/-2)
test/maps/lua_testsuite.wmf/scripting/messages.lua (+0/-5)
txts/README.lua (+8/-2)
To merge this branch: bzr merge lp:~widelands-dev/widelands/bug-987510
Reviewer Review Type Date Requested Status
GunChleoc Needs Resubmitting
Review via email: mp+236231@code.launchpad.net

Description of the change

Messages can be filtered by category now. Added new buttons for 5 categories and an icon on the bottom right of each message to show its message type. Added keyboard shortcuts and tooltips.

To post a comment you must log in.
Revision history for this message
TiborB (tiborb95) wrote :

I understand the design was discussed under bug report, but still 2 comments:

1. Current design is "one category only" - what about enabling and disabling freely? I mean you could be able to enable any number of categories.

2 mode "0: show all messages" shows a flag on the bottom and it is symbol of economy messages. I think "all messages" should have own icon, or no icon, or icons of all categories.

But generally it works as supposed....

Revision history for this message
TiborB (tiborb95) wrote :

question about shortcuts - numbers before categories (in tooltips) indicate shortcuts? I could not make them work. Is it '$number' or 'ctrl+$number'?

Revision history for this message
GunChleoc (gunchleoc) wrote :

Hotkeys work just fine with me, the toggle on/off. Is it '$number'.

1. That would make the filter harder to implement - I just went with the easy option.

2. The flag on the bottom is not the currently selected category, but the category of the current message. Maybe the tooltip should be clearer - "Type of this message: " maybe?

Revision history for this message
Hans Joachim Desserud (hjd) wrote :

Speaking of the hotkeys, how do they work together with the "area bookmarks" we have currently? At the moment I can use Ctrl+number to store a location, then later go back to it by pressing the number. How will we tell whether the user wish to toggle filtering in the news window or go to another place on the map? (Might be a question discussed in the bug report rather than the review)

Please resolve the conflicts mentioned at the top.

Revision history for this message
TiborB (tiborb95) wrote :

Probably hotkey does not work on my (linux) at all - but no problem now

> The flag on the bottom is not the currently selected category, but the category of the current message.

Oh yes, I did not got it, now it makes sense

Also you can consider "Type of selected message" or "Type of highlighted message"

Or even better, but probably more work for you - remove that flag on the bottom and add new column that would contain a particular flag for the message.

And yet another comment - will users understand that number on the beginning of tip is a shortcut?

Revision history for this message
GunChleoc (gunchleoc) wrote :

I overlooked that we already have the hotkeys 1-9 in use. I willcome up with different hotkeys.

> Or even better, but probably more work for you - remove that flag on the
> bottom and add new column that would contain a particular flag for the
> message.

This column would need a header and eat up space - we are already tight on width there. The translations need more space than the English strings. The message titles also need a lot of space-

> And yet another comment - will users understand that number on the beginning
> of tip is a shortcut?

I thought this would be nice for the user, but if you think it is confusing, I can remove these easily without messing up translations.

Revision history for this message
TiborB (tiborb95) wrote :

if the hotkeys will be like Ctrl+1, then it will be obvious that they are hotkeys and no confusion for user

Revision history for this message
wl-zocker (wl-zocker) wrote :

I have not tested it in the game, but some ideas based on these comments:
- I imagined that when the news window is open, 1-5 would act on it (6-0 should do nothing). When it is not open, they work as location marker. Ctrl+number is also already used. I do not know if Widelands currently supports this. The problem is that many keys are already used (g = geologist/GoTo, s = seafaring/statistics) and that they would make no sense in translation.
- Why not simply write "Hotkey: %s"? That should avoid any confusion.

Revision history for this message
GunChleoc (gunchleoc) wrote :

I found some letters that are included somewhere in the English strings for the hotkeys. Since we don't have localizable hotkeys, we will have to live with other languages not matching. But we have thet problem anyway with all hotkeys that are letters.

> - Why not simply write "Hotkey: %s"? That should avoid any confusion.

Good idea, done.

Revision history for this message
SirVer (sirver) wrote :

Using the same keys is fine: the mail window will have the focus for the keyboard when it is clicked or just opened, so the keys will do what the user expects.

Revision history for this message
TiborB (tiborb95) wrote :

Looks good now, and shortcuts works on my PC now :)

Revision history for this message
GunChleoc (gunchleoc) wrote :

So, what are the preferred hotkeys for you guys: 0-5, or the letters I'm using right now?

Revision history for this message
TiborB (tiborb95) wrote :

As letters does not match first letter of particular world, perhaps numbers could be better ( 0 for all), but personally I dont care much...
I think users might live happily with both approaches...

Revision history for this message
SirVer (sirver) wrote :

+1 for numbers.

Revision history for this message
SirVer (sirver) :
Revision history for this message
GunChleoc (gunchleoc) wrote :

Will do the numbers then.

The discinct message types are needed elsewhere, see the diff comment for details.

Revision history for this message
GunChleoc (gunchleoc) wrote :

All done. Hotkeys work as SirVer described.

review: Needs Resubmitting

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'pics/message_archive.png'
2Binary files pics/message_archive.png 2010-01-14 18:22:23 +0000 and pics/message_archive.png 2014-12-28 17:03:29 +0000 differ
3=== modified file 'pics/message_archived.png'
4Binary files pics/message_archived.png 2010-01-14 18:22:23 +0000 and pics/message_archived.png 2014-12-28 17:03:29 +0000 differ
5=== added file 'pics/message_clear_selection.png'
6Binary files pics/message_clear_selection.png 1970-01-01 00:00:00 +0000 and pics/message_clear_selection.png 2014-12-28 17:03:29 +0000 differ
7=== modified file 'pics/message_restore.png'
8Binary files pics/message_restore.png 2010-01-14 18:22:23 +0000 and pics/message_restore.png 2014-12-28 17:03:29 +0000 differ
9=== added file 'pics/message_selection_invert.png'
10Binary files pics/message_selection_invert.png 1970-01-01 00:00:00 +0000 and pics/message_selection_invert.png 2014-12-28 17:03:29 +0000 differ
11=== added file 'pics/messages_warfare.png'
12Binary files pics/messages_warfare.png 1970-01-01 00:00:00 +0000 and pics/messages_warfare.png 2014-12-28 17:03:29 +0000 differ
13=== modified file 'src/logic/building.cc'
14--- src/logic/building.cc 2014-12-11 12:38:10 +0000
15+++ src/logic/building.cc 2014-12-28 17:03:29 +0000
16@@ -880,7 +880,7 @@
17 */
18 void Building::send_message
19 (Game & game,
20- const std::string & msgsender,
21+ const Message::Type msgtype,
22 const std::string & title,
23 const std::string & description,
24 bool link_to_building_lifetime,
25@@ -910,7 +910,7 @@
26 % rt_description % description).str();
27
28 Message * msg = new Message
29- (msgsender, game.get_gametime(), title, rt_description,
30+ (msgtype, game.get_gametime(), title, rt_description,
31 get_position(), (link_to_building_lifetime ? m_serial : 0));
32
33 if (throttle_time)
34
35=== modified file 'src/logic/building.h'
36--- src/logic/building.h 2014-09-14 11:31:58 +0000
37+++ src/logic/building.h 2014-12-28 17:03:29 +0000
38@@ -31,6 +31,7 @@
39 #include "logic/bill_of_materials.h"
40 #include "logic/buildcost.h"
41 #include "logic/immovable.h"
42+#include "logic/message.h"
43 #include "logic/soldier_counts.h"
44 #include "logic/wareworker.h"
45 #include "logic/widelands.h"
46@@ -259,7 +260,7 @@
47
48 void send_message
49 (Game & game,
50- const std::string & msgsender,
51+ const Message::Type msgtype,
52 const std::string & title,
53 const std::string & description,
54 bool link_to_building_lifetime = true,
55
56=== modified file 'src/logic/cmd_luacoroutine.cc'
57--- src/logic/cmd_luacoroutine.cc 2014-09-20 09:37:47 +0000
58+++ src/logic/cmd_luacoroutine.cc 2014-12-28 17:03:29 +0000
59@@ -50,7 +50,7 @@
60 for (int i = 1; i <= game.map().get_nrplayers(); i++) {
61 Widelands::Message & msg =
62 *new Widelands::Message
63- ("Game Logic", game.get_gametime(), "Lua Coroutine Failed", e.what());
64+ (Message::Type::kGameLogic, game.get_gametime(), "Lua Coroutine Failed", e.what());
65 game.player(i).add_message(game, msg, true);
66 }
67 game.game_controller()->set_desired_speed(0);
68
69=== modified file 'src/logic/message.h'
70--- src/logic/message.h 2014-09-19 12:54:54 +0000
71+++ src/logic/message.h 2014-12-28 17:03:29 +0000
72@@ -29,10 +29,30 @@
73 namespace Widelands {
74
75 struct Message {
76- enum Status {New, Read, Archived};
77+ enum class Status: uint8_t {kNew, kRead, kArchived};
78+ enum class Type: uint8_t {
79+ kNoMessages,
80+ kAllMessages,
81+ kGameLogic,
82+ kGeologists,
83+ kGeologistsCoal,
84+ kGeologistsGold,
85+ kGeologistsGranite,
86+ kGeologistsIron,
87+ kGeologistsWater,
88+ kScenario,
89+ kSeafaring,
90+ kEconomy, // economy
91+ kEconomySiteOccupied, // economy
92+ kWarfare, // everything starting from here is warfare
93+ kWarfareSiteDefeated,
94+ kWarfareSiteLost,
95+ kWarfareUnderAttack
96+ };
97+
98 /**
99 * A new message to be displayed to the player
100- * \param msgsender The message sender
101+ * \param msgtype The type of message (economy, geologists, etc.)
102 * \param sent_time The (game) time at which the message is sent
103 * \param t The message title
104 * \param b The message body
105@@ -43,16 +63,16 @@
106 * \param s The message status. Defaults to Status::New
107 */
108 Message
109- (const std::string & msgsender,
110+ (Message::Type msgtype,
111 uint32_t sent_time,
112 const std::string & t,
113 const std::string & b,
114 Widelands::Coords const c = Coords::null(),
115 Widelands::Serial ser = 0,
116- Status s = New)
117+ Status s = Status::kNew)
118 :
119- m_sender(msgsender),
120- m_title(t),
121+ m_type (msgtype),
122+ m_title (t),
123 m_body (b),
124 m_sent (sent_time),
125 m_position(c),
126@@ -60,18 +80,35 @@
127 m_status (s)
128 {}
129
130- const std::string & sender() const {return m_sender;}
131- uint32_t sent () const {return m_sent;}
132- const std::string & title() const {return m_title;}
133- const std::string & body () const {return m_body;}
134- Widelands::Coords position() const {return m_position;}
135- Widelands::Serial serial() const {return m_serial;}
136- Status status () const {return m_status;}
137- Status set_status(Status const s) {return m_status = s;}
138+ Message::Type type () const {return m_type;}
139+ uint32_t sent () const {return m_sent;}
140+ const std::string & title () const {return m_title;}
141+ const std::string & body () const {return m_body;}
142+ Widelands::Coords position() const {return m_position;}
143+ Widelands::Serial serial () const {return m_serial;}
144+ Status status () const {return m_status;}
145+ Status set_status(Status const s) {return m_status = s;}
146+
147+ /**
148+ * Returns the main type for the message's sub type
149+ */
150+ Message::Type message_type_category() const {
151+ if (m_type >= Widelands::Message::Type::kWarfare) {
152+ return Widelands::Message::Type::kWarfare;
153+
154+ } else if (m_type >= Widelands::Message::Type::kEconomy &&
155+ m_type <= Widelands::Message::Type::kEconomySiteOccupied) {
156+ return Widelands::Message::Type::kEconomy;
157+ } else if (m_type >= Widelands::Message::Type::kGeologists &&
158+ m_type <= Widelands::Message::Type::kGeologistsWater) {
159+ return Widelands::Message::Type::kGeologists;
160+ }
161+ return m_type;
162+ }
163
164 private:
165- std::string m_sender;
166- std::string m_title;
167+ Message::Type m_type;
168+ std::string m_title;
169 std::string m_body;
170 uint32_t m_sent;
171 Widelands::Coords m_position;
172
173=== modified file 'src/logic/message_queue.h'
174--- src/logic/message_queue.h 2014-09-19 12:54:54 +0000
175+++ src/logic/message_queue.h 2014-12-28 17:03:29 +0000
176@@ -33,9 +33,9 @@
177 friend class MapPlayersMessagesPacket;
178
179 MessageQueue() {
180- m_counts[Message::New] = 0; // C++0x:
181- m_counts[Message::Read] = 0; // C++0x:
182- m_counts[Message::Archived] = 0; // C++0x:
183+ m_counts[static_cast<int>(Message::Status::kNew)] = 0; // C++0x:
184+ m_counts[static_cast<int>(Message::Status::kRead)] = 0; // C++0x:
185+ m_counts[static_cast<int>(Message::Status::kArchived)] = 0; // C++0x:
186 } // C++0x:
187
188 ~MessageQueue() {
189@@ -67,8 +67,8 @@
190 /// \returns the number of messages with the given status.
191 uint32_t nr_messages(Message::Status const status) const {
192 assert_counts();
193- assert(status < 3);
194- return m_counts[status];
195+ assert(static_cast<int>(status) < 3);
196+ return m_counts[static_cast<int>(status)];
197 }
198
199 /// Adds the message. Takes ownership of the message. Assumes that it has
200@@ -81,8 +81,8 @@
201 /// The loading code calls this function to add messages form the map file.
202 MessageId add_message(Message & message) {
203 assert_counts();
204- assert(message.status() < 3);
205- ++m_counts[message.status()];
206+ assert(static_cast<int>(message.status()) < 3);
207+ ++m_counts[static_cast<int>(message.status())];
208 insert
209 (std::map<MessageId, Message *>::end(),
210 std::pair<MessageId, Message *>(++m_current_message_id, &message));
211@@ -93,14 +93,14 @@
212 /// Sets the status of the message with the given id, if it exists.
213 void set_message_status(const MessageId& id, Message::Status const status) {
214 assert_counts();
215- assert(status < 3);
216+ assert(static_cast<int>(status) < 3);
217 MessageQueue::iterator const it = find(id);
218 if (it != end()) {
219 Message & message = *it->second;
220- assert(it->second->status() < 3);
221- assert(m_counts[message.status()]);
222- --m_counts[message.status ()];
223- ++m_counts[message.set_status(status)];
224+ assert(static_cast<int>(it->second->status()) < 3);
225+ assert(m_counts[static_cast<int>(message.status())]);
226+ --m_counts[static_cast<int>(message.status())];
227+ ++m_counts[static_cast<int>(message.set_status(status))];
228 }
229 assert_counts();
230 }
231@@ -117,9 +117,9 @@
232 return;
233 }
234 Message & message = *it->second;
235- assert(message.status() < 3);
236- assert(m_counts[message.status()]);
237- --m_counts[message.status()];
238+ assert(static_cast<int>(message.status()) < 3);
239+ assert(m_counts[static_cast<int>(message.status())]);
240+ --m_counts[static_cast<int>(message.status())];
241 delete &message;
242 erase(it);
243 assert_counts();
244@@ -143,9 +143,9 @@
245 void clear() {
246 assert_counts();
247 m_current_message_id = MessageId::null();
248- m_counts[Message::New] = 0;
249- m_counts[Message::Read] = 0;
250- m_counts[Message::Archived] = 0;
251+ m_counts[static_cast<int>(Message::Status::kNew)] = 0;
252+ m_counts[static_cast<int>(Message::Status::kRead)] = 0;
253+ m_counts[static_cast<int>(Message::Status::kArchived)] = 0;
254 std::map<MessageId, Message *>::clear();
255 assert_counts();
256 }
257@@ -161,9 +161,9 @@
258 void assert_counts() const {
259 assert
260 (size() ==
261- m_counts[Message::New] +
262- m_counts[Message::Read] +
263- m_counts[Message::Archived]);
264+ m_counts[static_cast<int>(Message::Status::kNew)] +
265+ m_counts[static_cast<int>(Message::Status::kRead)] +
266+ m_counts[static_cast<int>(Message::Status::kArchived)]);
267 }
268
269 DISALLOW_COPY_AND_ASSIGN(MessageQueue);
270
271=== modified file 'src/logic/militarysite.cc'
272--- src/logic/militarysite.cc 2014-11-30 18:49:38 +0000
273+++ src/logic/militarysite.cc 2014-12-28 17:03:29 +0000
274@@ -248,7 +248,7 @@
275 if (upcast(Game, game, &egbase)) {
276 send_message
277 (*game,
278- "site_occupied",
279+ Message::Type::kEconomySiteOccupied,
280 descr().descname(),
281 descr().m_occupied_str,
282 true);
283@@ -845,7 +845,7 @@
284 {
285 send_message
286 (game,
287- "site_lost",
288+ Message::Type::kWarfareSiteLost,
289 _("Militarysite lost!"),
290 descr().m_defeated_enemy_str,
291 false);
292@@ -899,7 +899,7 @@
293 // Of course we should inform the victorious player as well
294 newsite->send_message
295 (game,
296- "site_defeated",
297+ Message::Type::kWarfareSiteDefeated,
298 _("Enemy at site defeated!"),
299 newsite->descr().m_defeated_you_str,
300 true);
301@@ -949,7 +949,7 @@
302 // radius <= 5 near the current location in the last 60 seconds
303 send_message
304 (game,
305- "under_attack",
306+ Message::Type::kWarfareUnderAttack,
307 _("You are under attack"),
308 discovered ? descr().m_aggressor_str : descr().m_attack_str,
309 false,
310
311=== modified file 'src/logic/player.cc'
312--- src/logic/player.cc 2014-12-16 21:39:00 +0000
313+++ src/logic/player.cc 2014-12-28 17:03:29 +0000
314@@ -292,15 +292,15 @@
315 * Plays the corresponding sound when a message is received and if sound is
316 * enabled.
317 */
318-void Player::play_message_sound(const std::string & sender) {
319-#define MAYBE_PLAY(a, b) if (sender == a) { \
320- g_sound_handler.play_fx(b, 200, PRIO_ALWAYS_PLAY); \
321+void Player::play_message_sound(const Message::Type & msgtype) {
322+#define MAYBE_PLAY(type, file) if (msgtype == type) { \
323+ g_sound_handler.play_fx(file, 200, PRIO_ALWAYS_PLAY); \
324 return; \
325 }
326
327 if (g_options.pull_section("global").get_bool("sound_at_message", true)) {
328- MAYBE_PLAY("site_occupied", "sound/military/site_occupied");
329- MAYBE_PLAY("under_attack", "sound/military/under_attack");
330+ MAYBE_PLAY(Message::Type::kEconomySiteOccupied, "sound/military/site_occupied");
331+ MAYBE_PLAY(Message::Type::kWarfareUnderAttack, "sound/military/under_attack");
332
333 g_sound_handler.play_fx("sound/message", 200, PRIO_ALWAYS_PLAY);
334 }
335@@ -321,7 +321,7 @@
336 // Sound & popup
337 if (InteractivePlayer * const iplayer = game.get_ipl()) {
338 if (&iplayer->player() == this) {
339- play_message_sound(message.sender());
340+ play_message_sound(message.type());
341 if (popup)
342 iplayer->popup_message(id, message);
343 }
344@@ -339,7 +339,7 @@
345 Coords const position = m .position ();
346 for (std::pair<MessageId, Message *> tmp_message : messages()) {
347 if
348- (tmp_message.second->sender() == m.sender() &&
349+ (tmp_message.second->type() == m.type() &&
350 gametime < tmp_message.second->sent() + timeout &&
351 map.calc_distance(tmp_message.second->position(), position) <= radius)
352 {
353
354=== modified file 'src/logic/player.h'
355--- src/logic/player.h 2014-12-16 21:39:00 +0000
356+++ src/logic/player.h 2014-12-28 17:03:29 +0000
357@@ -521,7 +521,7 @@
358 BuildingStatsVector* get_mutable_building_statistics(const BuildingIndex& i);
359 void update_building_statistics(Building &, NoteImmovable::Ownership ownership);
360 void update_team_players();
361- void play_message_sound(const std::string & sender);
362+ void play_message_sound(const Message::Type & msgtype);
363 void _enhance_or_dismantle
364 (Building *, BuildingIndex const index_of_new_building);
365
366
367=== modified file 'src/logic/playercommand.cc'
368--- src/logic/playercommand.cc 2014-09-20 09:37:47 +0000
369+++ src/logic/playercommand.cc 2014-12-28 17:03:29 +0000
370@@ -1784,7 +1784,7 @@
371 void CmdMessageSetStatusRead::execute (Game & game)
372 {
373 game.player(sender()).messages().set_message_status
374- (message_id(), Message::Read);
375+ (message_id(), Message::Status::kRead);
376 }
377
378 void CmdMessageSetStatusRead::serialize (StreamWrite & ser)
379@@ -1800,7 +1800,7 @@
380 void CmdMessageSetStatusArchived::execute (Game & game)
381 {
382 game.player(sender()).messages().set_message_status
383- (message_id(), Message::Archived);
384+ (message_id(), Message::Status::kArchived);
385 }
386
387 void CmdMessageSetStatusArchived::serialize (StreamWrite & ser)
388
389=== modified file 'src/logic/productionsite.cc'
390--- src/logic/productionsite.cc 2014-12-06 12:22:35 +0000
391+++ src/logic/productionsite.cc 2014-12-28 17:03:29 +0000
392@@ -925,7 +925,7 @@
393 assert(!descr().out_of_resource_message().empty());
394 send_message
395 (game,
396- "produce",
397+ Message::Type::kEconomy,
398 descr().out_of_resource_title(),
399 descr().out_of_resource_message(),
400 true,
401
402=== modified file 'src/logic/ship.cc'
403--- src/logic/ship.cc 2014-12-12 22:59:39 +0000
404+++ src/logic/ship.cc 2014-12-28 17:03:29 +0000
405@@ -21,8 +21,6 @@
406
407 #include <memory>
408
409-#include <boost/format.hpp>
410-
411 #include "base/macros.h"
412 #include "economy/economy.h"
413 #include "economy/flag.h"
414@@ -51,24 +49,24 @@
415
416 namespace Widelands {
417
418-ShipDescr::ShipDescr(const char* given_name,
419- const char* gdescname,
420- const std::string& directory,
421- Profile& prof,
422- Section& global_s,
423- const TribeDescr& gtribe)
424- : BobDescr(MapObjectType::SHIP, given_name, gdescname, &gtribe) {
425- { // global options
426- Section& idle_s = prof.get_safe_section("idle");
427+ShipDescr::ShipDescr
428+ (const char * given_name, const char * gdescname,
429+ const std::string & directory, Profile & prof, Section & global_s,
430+ const TribeDescr & gtribe)
431+ :
432+ BobDescr(MapObjectType::SHIP, given_name, gdescname, &gtribe)
433+{
434+ { // global options
435+ Section & idle_s = prof.get_safe_section("idle");
436 add_animation("idle", g_gr->animations().load(directory, idle_s));
437 }
438 m_sail_anims.parse(*this, directory, prof, "sail");
439
440- Section* sinking_s = prof.get_section("sinking");
441+ Section * sinking_s = prof.get_section("sinking");
442 if (sinking_s)
443 add_animation("sinking", g_gr->animations().load(directory, *sinking_s));
444
445- m_capacity = global_s.get_natural("capacity", 20);
446+ m_capacity = global_s.get_natural("capacity", 20);
447 m_vision_range = global_s.get_natural("vision_range", 7);
448 }
449
450@@ -76,12 +74,18 @@
451 return MOVECAPS_SWIM;
452 }
453
454-Bob& ShipDescr::create_object() const {
455+Bob & ShipDescr::create_object() const {
456 return *new Ship(*this);
457 }
458
459-Ship::Ship(const ShipDescr& gdescr)
460- : Bob(gdescr), m_window(nullptr), m_fleet(nullptr), m_economy(nullptr), m_ship_state(TRANSPORT) {
461+
462+Ship::Ship(const ShipDescr & gdescr) :
463+ Bob(gdescr),
464+ m_window(nullptr),
465+ m_fleet(nullptr),
466+ m_economy(nullptr),
467+ m_ship_state(TRANSPORT)
468+{
469 }
470
471 Ship::~Ship() {
472@@ -100,11 +104,11 @@
473 return m_fleet;
474 }
475
476-void Ship::init_auto_task(Game& game) {
477+void Ship::init_auto_task(Game & game) {
478 start_task_ship(game);
479 }
480
481-void Ship::init(EditorGameBase& egbase) {
482+void Ship::init(EditorGameBase & egbase) {
483 Bob::init(egbase);
484 init_fleet(egbase);
485 }
486@@ -114,15 +118,15 @@
487 * The fleet code will automatically merge us into a larger
488 * fleet, if one is reachable.
489 */
490-void Ship::init_fleet(EditorGameBase& egbase) {
491+void Ship::init_fleet(EditorGameBase & egbase) {
492 assert(get_owner() != nullptr);
493- Fleet* fleet = new Fleet(*get_owner());
494+ Fleet * fleet = new Fleet(*get_owner());
495 fleet->add_ship(this);
496 fleet->init(egbase);
497 // fleet calls the set_fleet function appropriately
498 }
499
500-void Ship::cleanup(EditorGameBase& egbase) {
501+void Ship::cleanup(EditorGameBase & egbase) {
502 if (m_fleet) {
503 m_fleet->remove_ship(egbase, this);
504 }
505@@ -138,48 +142,52 @@
506 /**
507 * This function is to be called only by @ref Fleet.
508 */
509-void Ship::set_fleet(Fleet* fleet) {
510+void Ship::set_fleet(Fleet * fleet) {
511 m_fleet = fleet;
512 }
513
514-void Ship::wakeup_neighbours(Game& game) {
515+void Ship::wakeup_neighbours(Game & game) {
516 FCoords position = get_position();
517 Area<FCoords> area(position, 1);
518- std::vector<Bob*> ships;
519+ std::vector<Bob *> ships;
520 game.map().find_bobs(area, &ships, FindBobShip());
521
522- for (std::vector<Bob*>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
523+ for
524+ (std::vector<Bob *>::const_iterator it = ships.begin();
525+ it != ships.end(); ++it)
526+ {
527 if (*it == this)
528 continue;
529
530- static_cast<Ship*>(*it)->ship_wakeup(game);
531+ static_cast<Ship *>(*it)->ship_wakeup(game);
532 }
533 }
534
535+
536 /**
537 * Standard behaviour of ships.
538 *
539 * ivar1 = helper flag for coordination of mutual evasion of ships
540 */
541 const Bob::Task Ship::taskShip = {
542- "ship",
543- static_cast<Bob::Ptr>(&Ship::ship_update),
544- nullptr,
545- nullptr,
546- true // unique task
547+ "ship",
548+ static_cast<Bob::Ptr>(&Ship::ship_update),
549+ nullptr,
550+ nullptr,
551+ true // unique task
552 };
553
554-void Ship::start_task_ship(Game& game) {
555+void Ship::start_task_ship(Game & game) {
556 push_task(game, taskShip);
557 top_state().ivar1 = 0;
558 }
559
560-void Ship::ship_wakeup(Game& game) {
561+void Ship::ship_wakeup(Game & game) {
562 if (get_state(taskShip))
563 send_signal(game, "wakeup");
564 }
565
566-void Ship::ship_update(Game& game, Bob::State& state) {
567+void Ship::ship_update(Game & game, Bob::State & state) {
568 // Handle signals
569 std::string signal = get_signal();
570 if (!signal.empty()) {
571@@ -203,43 +211,44 @@
572 }
573
574 switch (m_ship_state) {
575- case TRANSPORT:
576- if (ship_update_transport(game, state))
577- return;
578- break;
579- case EXP_FOUNDPORTSPACE:
580- case EXP_SCOUTING:
581- case EXP_WAITING:
582- ship_update_expedition(game, state);
583- break;
584- case EXP_COLONIZING:
585- break;
586- case SINK_REQUEST:
587- if (descr().is_animation_known("sinking")) {
588- m_ship_state = SINK_ANIMATION;
589- start_task_idle(game, descr().get_animation("sinking"), 3000);
590- return;
591- }
592- log("Oh no... this ship has no sinking animation :(!\n");
593- // fall trough
594- case SINK_ANIMATION:
595- // The sink animation has been played, so finally remove the ship from the map
596- pop_task(game);
597- remove(game);
598- return;
599- default:
600- assert(false); // never here
601+ case TRANSPORT:
602+ if (ship_update_transport(game, state))
603+ return;
604+ break;
605+ case EXP_FOUNDPORTSPACE:
606+ case EXP_SCOUTING:
607+ case EXP_WAITING:
608+ ship_update_expedition(game, state);
609+ break;
610+ case EXP_COLONIZING:
611+ break;
612+ case SINK_REQUEST:
613+ if (descr().is_animation_known("sinking")) {
614+ m_ship_state = SINK_ANIMATION;
615+ start_task_idle(game, descr().get_animation("sinking"), 3000);
616+ return;
617+ }
618+ log("Oh no... this ship has no sinking animation :(!\n");
619+ // fall trough
620+ case SINK_ANIMATION:
621+ // The sink animation has been played, so finally remove the ship from the map
622+ pop_task(game);
623+ remove(game);
624+ return;
625+ default:
626+ assert(false); // never here
627 }
628
629 // if the real update function failed (e.g. nothing to transport), the ship goes idle
630 ship_update_idle(game, state);
631 }
632
633+
634 /// updates a ships tasks in transport mode \returns false if failed to update tasks
635-bool Ship::ship_update_transport(Game& game, Bob::State&) {
636- Map& map = game.map();
637+bool Ship::ship_update_transport(Game & game, Bob::State &) {
638+ Map & map = game.map();
639
640- PortDock* dst = get_destination(game);
641+ PortDock * dst = get_destination(game);
642 if (!dst) {
643 molog("ship_update: No destination anymore.\n");
644 if (m_items.empty())
645@@ -268,7 +277,7 @@
646
647 molog("ship_update: Go to dock %u\n", dst->serial());
648
649- PortDock* lastdock = m_lastdock.get(game);
650+ PortDock * lastdock = m_lastdock.get(game);
651 if (lastdock && lastdock != dst) {
652 molog("ship_update: Have lastdock %u\n", lastdock->serial());
653
654@@ -323,9 +332,10 @@
655 return true;
656 }
657
658+
659 /// updates a ships tasks in expedition mode
660-void Ship::ship_update_expedition(Game& game, Bob::State&) {
661- Map& map = game.map();
662+void Ship::ship_update_expedition(Game & game, Bob::State &) {
663+ Map & map = game.map();
664
665 assert(m_expedition);
666
667@@ -333,30 +343,30 @@
668 FCoords position = get_position();
669 for (Direction dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
670 m_expedition->swimable[dir - 1] =
671- map.get_neighbour(position, dir).field->nodecaps() & MOVECAPS_SWIM;
672+ map.get_neighbour(position, dir).field->nodecaps() & MOVECAPS_SWIM;
673 }
674
675 if (m_ship_state == EXP_SCOUTING) {
676 // Check surrounding fields for port buildspaces
677- std::unique_ptr<std::list<Coords>> temp_port_buildspaces(new std::list<Coords>());
678- MapRegion<Area<Coords>> mr(map, Area<Coords>(position, descr().vision_range()));
679+ std::unique_ptr<std::list<Coords> > temp_port_buildspaces(new std::list<Coords>());
680+ MapRegion<Area<Coords> > mr(map, Area<Coords>(position, descr().vision_range()));
681 bool new_port_space = false;
682 do {
683 if (map.is_port_space(mr.location())) {
684 FCoords fc = map.get_fcoords(mr.location());
685
686- // Check whether the maximum theoretical possible NodeCap of the field is of the size
687- // big
688+ // Check whether the maximum theoretical possible NodeCap of the field is of the size big
689 // and whether it can theoretically be a port space
690- if ((map.get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG ||
691- map.find_portdock(fc).empty()) {
692+ if
693+ ((map.get_max_nodecaps(game.world(), fc) & BUILDCAPS_SIZEMASK) != BUILDCAPS_BIG
694+ ||
695+ map.find_portdock(fc).empty())
696+ {
697 continue;
698 }
699
700- // NOTE This is the place to handle enemy territory and "clearing a port space from the
701- // enemy".
702- // NOTE There is a simple check for the current land owner to avoid placement of ports
703- // into enemy
704+ // NOTE This is the place to handle enemy territory and "clearing a port space from the enemy".
705+ // NOTE There is a simple check for the current land owner to avoid placement of ports into enemy
706 // NOTE territory, as "clearing" is not yet implemented.
707 // NOTE further it checks, whether there is a Player_immovable on one of the fields.
708 // TODO(unknown): handle this more gracefully concering opposing players
709@@ -368,7 +378,7 @@
710 invalid = true;
711 continue;
712 }
713- BaseImmovable* baim = coord.field->get_immovable();
714+ BaseImmovable * baim = coord.field->get_immovable();
715 if (baim)
716 if (is_a(PlayerImmovable, baim)) {
717 invalid = true;
718@@ -377,60 +387,60 @@
719
720 // Check all neighboured fields that will be used by the port
721 switch (step) {
722- case 0:
723- map.get_ln(fc, &coord);
724- break;
725- case 1:
726- map.get_tln(fc, &coord);
727- break;
728- case 2:
729- map.get_trn(fc, &coord);
730- break;
731- case 3:
732- // Flag coordinate
733- map.get_brn(fc, &coord);
734- break;
735- default:
736- break;
737+ case 0:
738+ map.get_ln(fc, &coord);
739+ break;
740+ case 1:
741+ map.get_tln(fc, &coord);
742+ break;
743+ case 2:
744+ map.get_trn(fc, &coord);
745+ break;
746+ case 3:
747+ // Flag coordinate
748+ map.get_brn(fc, &coord);
749+ break;
750+ default:
751+ break;
752 }
753 }
754 // Now check whether there is a flag in the surroundings of the flag position
755 FCoords neighb;
756 map.get_ln(coord, &neighb);
757 for (uint8_t step = 0; !invalid && step < 5; ++step) {
758- BaseImmovable* baim = neighb.field->get_immovable();
759+ BaseImmovable * baim = neighb.field->get_immovable();
760 if (baim)
761 if (is_a(Flag, baim)) {
762 invalid = true;
763 continue;
764 }
765- // Check all neighboured fields but not the one already checked for a
766- // PlayerImmovable.
767+ // Check all neighboured fields but not the one already checked for a PlayerImmovable.
768 switch (step) {
769- case 0:
770- map.get_bln(coord, &neighb);
771- break;
772- case 1:
773- map.get_brn(coord, &neighb);
774- break;
775- case 2:
776- map.get_rn(coord, &neighb);
777- break;
778- case 3:
779- map.get_trn(coord, &neighb);
780- break;
781- default:
782- break;
783+ case 0:
784+ map.get_bln(coord, &neighb);
785+ break;
786+ case 1:
787+ map.get_brn(coord, &neighb);
788+ break;
789+ case 2:
790+ map.get_rn(coord, &neighb);
791+ break;
792+ case 3:
793+ map.get_trn(coord, &neighb);
794+ break;
795+ default:
796+ break;
797 }
798 }
799 if (invalid)
800 continue;
801
802 bool pbs_saved = false;
803- for (std::list<Coords>::const_iterator it =
804- m_expedition->seen_port_buildspaces->begin();
805- it != m_expedition->seen_port_buildspaces->end() && !pbs_saved;
806- ++it) {
807+ for
808+ (std::list<Coords>::const_iterator it = m_expedition->seen_port_buildspaces->begin();
809+ it != m_expedition->seen_port_buildspaces->end() && !pbs_saved;
810+ ++it)
811+ {
812 // Check if the ship knows this port space already from its last check
813 if (*it == mr.location()) {
814 temp_port_buildspaces->push_back(mr.location());
815@@ -449,13 +459,13 @@
816 // Send a message to the player, that a new port space was found
817 std::string msg_head = _("Port Space Found");
818 std::string msg_body = _("An expedition ship found a new port build space.");
819- send_message(game, "exp_port_space", msg_head, msg_body, "port.png");
820+ send_message(game, msg_head, msg_body, "port.png");
821 }
822 m_expedition->seen_port_buildspaces.swap(temp_port_buildspaces);
823 }
824 }
825
826-void Ship::ship_update_idle(Game& game, Bob::State& state) {
827+void Ship::ship_update_idle(Game & game, Bob::State & state) {
828 if (state.ivar1) {
829 // We've just completed one step, so give neighbours
830 // a chance to move away first
831@@ -465,221 +475,214 @@
832 return;
833 }
834
835- // If we are waiting for the next transport job, check if we should move away from ships and
836- // shores
837+ // If we are waiting for the next transport job, check if we should move away from ships and shores
838 switch (m_ship_state) {
839- case TRANSPORT: {
840- FCoords position = get_position();
841- Map& map = game.map();
842- unsigned int dirs[LAST_DIRECTION + 1];
843- unsigned int dirmax = 0;
844-
845- for (Direction dir = 0; dir <= LAST_DIRECTION; ++dir) {
846- FCoords node = dir ? map.get_neighbour(position, dir) : position;
847- dirs[dir] = node.field->nodecaps() & MOVECAPS_WALK ? 10 : 0;
848-
849- Area<FCoords> area(node, 0);
850- std::vector<Bob*> ships;
851- map.find_bobs(area, &ships, FindBobShip());
852-
853- for (std::vector<Bob*>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
854- if (*it == this)
855- continue;
856-
857- dirs[dir] += 3;
858- }
859-
860- dirmax = std::max(dirmax, dirs[dir]);
861- }
862-
863- if (dirmax) {
864- unsigned int prob[LAST_DIRECTION + 1];
865- unsigned int totalprob = 0;
866-
867- // The probability for moving into a given direction is also
868- // affected by the "close" directions.
869+ case TRANSPORT: {
870+ FCoords position = get_position();
871+ Map & map = game.map();
872+ unsigned int dirs[LAST_DIRECTION + 1];
873+ unsigned int dirmax = 0;
874+
875 for (Direction dir = 0; dir <= LAST_DIRECTION; ++dir) {
876- prob[dir] = 10 * dirmax - 10 * dirs[dir];
877-
878- if (dir > 0) {
879- unsigned int delta =
880- std::min(prob[dir], dirs[(dir % 6) + 1] + dirs[1 + ((dir - 1) % 6)]);
881- prob[dir] -= delta;
882- }
883-
884- totalprob += prob[dir];
885- }
886-
887- if (totalprob == 0) {
888- start_task_idle(game, descr().main_animation(), 1500);
889- return;
890- }
891-
892- unsigned int rnd = game.logic_rand() % totalprob;
893- Direction dir = 0;
894- while (rnd >= prob[dir]) {
895- rnd -= prob[dir];
896- ++dir;
897- }
898-
899- if (dir == 0 || dir > LAST_DIRECTION) {
900- start_task_idle(game, descr().main_animation(), 1500);
901- return;
902- }
903-
904- FCoords neighbour = map.get_neighbour(position, dir);
905- if (!(neighbour.field->nodecaps() & MOVECAPS_SWIM)) {
906- start_task_idle(game, descr().main_animation(), 1500);
907- return;
908- }
909-
910- state.ivar1 = 1;
911- start_task_move(game, dir, descr().get_sail_anims(), false);
912+ FCoords node = dir ? map.get_neighbour(position, dir) : position;
913+ dirs[dir] = node.field->nodecaps() & MOVECAPS_WALK ? 10 : 0;
914+
915+ Area<FCoords> area(node, 0);
916+ std::vector<Bob *> ships;
917+ map.find_bobs(area, &ships, FindBobShip());
918+
919+ for (std::vector<Bob *>::const_iterator it = ships.begin(); it != ships.end(); ++it) {
920+ if (*it == this)
921+ continue;
922+
923+ dirs[dir] += 3;
924+ }
925+
926+ dirmax = std::max(dirmax, dirs[dir]);
927+ }
928+
929+ if (dirmax) {
930+ unsigned int prob[LAST_DIRECTION + 1];
931+ unsigned int totalprob = 0;
932+
933+ // The probability for moving into a given direction is also
934+ // affected by the "close" directions.
935+ for (Direction dir = 0; dir <= LAST_DIRECTION; ++dir) {
936+ prob[dir] = 10 * dirmax - 10 * dirs[dir];
937+
938+ if (dir > 0) {
939+ unsigned int delta = std::min(prob[dir], dirs[(dir % 6) + 1] + dirs[1 + ((dir - 1) % 6)]);
940+ prob[dir] -= delta;
941+ }
942+
943+ totalprob += prob[dir];
944+ }
945+
946+ if (totalprob == 0) {
947+ start_task_idle(game, descr().main_animation(), 1500);
948+ return;
949+ }
950+
951+ unsigned int rnd = game.logic_rand() % totalprob;
952+ Direction dir = 0;
953+ while (rnd >= prob[dir]) {
954+ rnd -= prob[dir];
955+ ++dir;
956+ }
957+
958+ if (dir == 0 || dir > LAST_DIRECTION) {
959+ start_task_idle(game, descr().main_animation(), 1500);
960+ return;
961+ }
962+
963+ FCoords neighbour = map.get_neighbour(position, dir);
964+ if (!(neighbour.field->nodecaps() & MOVECAPS_SWIM)) {
965+ start_task_idle(game, descr().main_animation(), 1500);
966+ return;
967+ }
968+
969+ state.ivar1 = 1;
970+ start_task_move(game, dir, descr().get_sail_anims(), false);
971+ return;
972+ }
973+ // No desire to move around, so sleep
974+ start_task_idle(game, descr().main_animation(), -1);
975 return;
976 }
977- // No desire to move around, so sleep
978- start_task_idle(game, descr().main_animation(), -1);
979- return;
980- }
981- case EXP_SCOUTING: {
982- if (m_expedition->island_exploration) { // Exploration of the island
983- if (exp_close_to_coast()) {
984- if (m_expedition->direction == 0) {
985- // Make sure we know the location of the coast and use it as initial direction we
986- // come from
987- m_expedition->direction = WALK_SE;
988- for (uint8_t secure = 0; exp_dir_swimable(m_expedition->direction); ++secure) {
989- assert(secure < 6);
990- m_expedition->direction = get_cw_neighbour(m_expedition->direction);
991+ case EXP_SCOUTING: {
992+ if (m_expedition->island_exploration) { // Exploration of the island
993+ if (exp_close_to_coast()) {
994+ if (m_expedition->direction == 0) {
995+ // Make sure we know the location of the coast and use it as initial direction we come from
996+ m_expedition->direction = WALK_SE;
997+ for (uint8_t secure = 0; exp_dir_swimable(m_expedition->direction); ++secure) {
998+ assert(secure < 6);
999+ m_expedition->direction = get_cw_neighbour(m_expedition->direction);
1000+ }
1001+ m_expedition->direction = get_backward_dir(m_expedition->direction);
1002+ // Save the position - this is where we start
1003+ m_expedition->exploration_start = get_position();
1004+ } else {
1005+ // Check whether the island was completely surrounded
1006+ if (get_position() == m_expedition->exploration_start) {
1007+ std::string msg_head = _("Island Circumnavigated");
1008+ std::string msg_body = _("An expedition ship sailed around its"
1009+ " island without any events.");
1010+ send_message(game, msg_head, msg_body,
1011+ "ship_explore_island_cw.png");
1012+ m_ship_state = EXP_WAITING;
1013+ return start_task_idle(game, descr().main_animation(), 1500);
1014+ }
1015 }
1016+ // The ship is supposed to follow the coast as close as possible, therefore the check for
1017+ // a swimable field begins at the neighbour field of the direction we came from.
1018 m_expedition->direction = get_backward_dir(m_expedition->direction);
1019- // Save the position - this is where we start
1020- m_expedition->exploration_start = get_position();
1021- } else {
1022- // Check whether the island was completely surrounded
1023- if (get_position() == m_expedition->exploration_start) {
1024- std::string msg_head = _("Island Circumnavigated");
1025- std::string msg_body = _("An expedition ship sailed around its"
1026- " island without any events.");
1027- send_message(
1028- game, "exp_island", msg_head, msg_body, "ship_explore_island_cw.png");
1029- m_ship_state = EXP_WAITING;
1030- return start_task_idle(game, descr().main_animation(), 1500);
1031- }
1032- }
1033- // The ship is supposed to follow the coast as close as possible, therefore the check
1034- // for
1035- // a swimable field begins at the neighbour field of the direction we came from.
1036- m_expedition->direction = get_backward_dir(m_expedition->direction);
1037- if (m_expedition->clockwise) {
1038- do {
1039- m_expedition->direction = get_ccw_neighbour(m_expedition->direction);
1040- } while (!exp_dir_swimable(m_expedition->direction));
1041- } else {
1042- do {
1043- m_expedition->direction = get_cw_neighbour(m_expedition->direction);
1044- } while (!exp_dir_swimable(m_expedition->direction));
1045- }
1046- state.ivar1 = 1;
1047- return start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
1048- } else {
1049- // The ship got the command to scout around an island, but is not close to any island
1050- // Most likely the command was send as the ship was on an exploration and just leaving
1051- // the island - therefore we try to find the island again.
1052- FCoords position = get_position();
1053- Map& map = game.map();
1054- for (uint8_t dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
1055- FCoords neighbour = map.get_neighbour(position, dir);
1056- for (uint8_t sur = FIRST_DIRECTION; sur <= LAST_DIRECTION; ++sur)
1057- if (!(map.get_neighbour(neighbour, sur).field->nodecaps() & MOVECAPS_SWIM)) {
1058- // Okay we found the next coast, so now the ship should go there.
1059- // However, we do neither save the position as starting position, nor do we
1060- // save
1061- // the direction we currently go. So the ship can start exploring normally
1062- state.ivar1 = 1;
1063- return start_task_move(game, dir, descr().get_sail_anims(), false);
1064- }
1065- }
1066- // if we are here, it seems something really strange happend.
1067- log("WARNING: ship was not able to start exploration. Entering WAIT mode.");
1068+ if (m_expedition->clockwise) {
1069+ do {
1070+ m_expedition->direction = get_ccw_neighbour(m_expedition->direction);
1071+ } while (!exp_dir_swimable(m_expedition->direction));
1072+ } else {
1073+ do {
1074+ m_expedition->direction = get_cw_neighbour(m_expedition->direction);
1075+ } while (!exp_dir_swimable(m_expedition->direction));
1076+ }
1077+ state.ivar1 = 1;
1078+ return start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
1079+ } else {
1080+ // The ship got the command to scout around an island, but is not close to any island
1081+ // Most likely the command was send as the ship was on an exploration and just leaving
1082+ // the island - therefore we try to find the island again.
1083+ FCoords position = get_position();
1084+ Map & map = game.map();
1085+ for (uint8_t dir = FIRST_DIRECTION; dir <= LAST_DIRECTION; ++dir) {
1086+ FCoords neighbour = map.get_neighbour(position, dir);
1087+ for (uint8_t sur = FIRST_DIRECTION; sur <= LAST_DIRECTION; ++sur)
1088+ if (!(map.get_neighbour(neighbour, sur).field->nodecaps() & MOVECAPS_SWIM)) {
1089+ // Okay we found the next coast, so now the ship should go there.
1090+ // However, we do neither save the position as starting position, nor do we save
1091+ // the direction we currently go. So the ship can start exploring normally
1092+ state.ivar1 = 1;
1093+ return start_task_move(game, dir, descr().get_sail_anims(), false);
1094+ }
1095+ }
1096+ // if we are here, it seems something really strange happend.
1097+ log("WARNING: ship was not able to start exploration. Entering WAIT mode.");
1098+ m_ship_state = EXP_WAITING;
1099+ return start_task_idle(game, descr().main_animation(), 1500);
1100+ }
1101+ } else { // scouting towards a specific direction
1102+ if (exp_dir_swimable(m_expedition->direction)) {
1103+ // the scouting direction is still free to move
1104+ state.ivar1 = 1;
1105+ start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
1106+ return;
1107+ }
1108+ // coast reached
1109 m_ship_state = EXP_WAITING;
1110- return start_task_idle(game, descr().main_animation(), 1500);
1111- }
1112- } else { // scouting towards a specific direction
1113- if (exp_dir_swimable(m_expedition->direction)) {
1114- // the scouting direction is still free to move
1115- state.ivar1 = 1;
1116- start_task_move(game, m_expedition->direction, descr().get_sail_anims(), false);
1117+ start_task_idle(game, descr().main_animation(), 1500);
1118+ // Send a message to the player, that a new coast was reached
1119+ std::string msg_head = _("Coast Reached");
1120+ std::string msg_body =
1121+ _("An expedition ship reached a coast and is waiting for further commands.");
1122+ send_message(game, msg_head, msg_body, "ship_explore_island_cw.png");
1123 return;
1124 }
1125- // coast reached
1126- m_ship_state = EXP_WAITING;
1127+ }
1128+ case EXP_COLONIZING: {
1129+ assert(m_expedition->seen_port_buildspaces && !m_expedition->seen_port_buildspaces->empty());
1130+ BaseImmovable * baim = game.map()[m_expedition->seen_port_buildspaces->front()].get_immovable();
1131+ assert(baim);
1132+ upcast(ConstructionSite, cs, baim);
1133+
1134+ for (int i = m_items.size() - 1; i >= 0; --i) {
1135+ WareInstance * ware;
1136+ Worker * worker;
1137+ m_items.at(i).get(game, &ware, &worker);
1138+ if (ware) {
1139+ // no, we don't transfer the wares, we create new ones out of air and remove the old ones ;)
1140+ WaresQueue & wq = cs->waresqueue(ware->descr_index());
1141+ const uint32_t max = wq.get_max_fill();
1142+ const uint32_t cur = wq.get_filled();
1143+ assert(max > cur);
1144+ wq.set_filled(cur + 1);
1145+ m_items.at(i).remove(game);
1146+ m_items.resize(i);
1147+ break;
1148+ } else {
1149+ assert(worker);
1150+ worker->set_economy(nullptr);
1151+ worker->set_location(cs);
1152+ worker->set_position(game, cs->get_position());
1153+ worker->reset_tasks(game);
1154+ PartiallyFinishedBuilding::request_builder_callback
1155+ (game, *cs->get_builder_request(), worker->descr().worker_index(), worker, *cs);
1156+ m_items.resize(i);
1157+ }
1158+ }
1159+ if (m_items.empty()) {
1160+ m_ship_state = TRANSPORT; // That's it, expedition finished
1161+
1162+ init_fleet(game);
1163+ m_expedition.reset(nullptr);
1164+
1165+ if (upcast(InteractiveGameBase, igb, game.get_ibase()))
1166+ refresh_window(*igb);
1167+ }
1168+ return start_task_idle(game, descr().main_animation(), 1500); // unload the next item
1169+ }
1170+
1171+ default: {
1172+ // wait for input
1173 start_task_idle(game, descr().main_animation(), 1500);
1174- // Send a message to the player, that a new coast was reached
1175- std::string msg_head = _("Coast Reached");
1176- std::string msg_body =
1177- _("An expedition ship reached a coast and is waiting for further commands.");
1178- send_message(game, "exp_coast", msg_head, msg_body, "ship_explore_island_cw.png");
1179 return;
1180 }
1181 }
1182- case EXP_COLONIZING: {
1183- assert(m_expedition->seen_port_buildspaces && !m_expedition->seen_port_buildspaces->empty());
1184- BaseImmovable* baim =
1185- game.map()[m_expedition->seen_port_buildspaces->front()].get_immovable();
1186- assert(baim);
1187- upcast(ConstructionSite, cs, baim);
1188-
1189- for (int i = m_items.size() - 1; i >= 0; --i) {
1190- WareInstance* ware;
1191- Worker* worker;
1192- m_items.at(i).get(game, &ware, &worker);
1193- if (ware) {
1194- // no, we don't transfer the wares, we create new ones out of air and remove the old
1195- // ones ;)
1196- WaresQueue& wq = cs->waresqueue(ware->descr_index());
1197- const uint32_t max = wq.get_max_fill();
1198- const uint32_t cur = wq.get_filled();
1199- assert(max > cur);
1200- wq.set_filled(cur + 1);
1201- m_items.at(i).remove(game);
1202- m_items.resize(i);
1203- break;
1204- } else {
1205- assert(worker);
1206- worker->set_economy(nullptr);
1207- worker->set_location(cs);
1208- worker->set_position(game, cs->get_position());
1209- worker->reset_tasks(game);
1210- PartiallyFinishedBuilding::request_builder_callback(
1211- game, *cs->get_builder_request(), worker->descr().worker_index(), worker, *cs);
1212- m_items.resize(i);
1213- }
1214- }
1215- if (m_items.empty()) {
1216- m_ship_state = TRANSPORT; // That's it, expedition finished
1217-
1218- init_fleet(game);
1219- m_expedition.reset(nullptr);
1220-
1221- if (upcast(InteractiveGameBase, igb, game.get_ibase()))
1222- refresh_window(*igb);
1223- }
1224- return start_task_idle(game, descr().main_animation(), 1500); // unload the next item
1225- }
1226-
1227- default: {
1228- // wait for input
1229- start_task_idle(game, descr().main_animation(), 1500);
1230- return;
1231- }
1232- }
1233
1234 // never here
1235- assert(false);
1236+ assert (false);
1237 }
1238
1239-void Ship::set_economy(Game& game, Economy* e) {
1240+void Ship::set_economy(Game & game, Economy * e) {
1241 // Do not check here that the economy actually changed, because on loading
1242 // we rely that wares really get reassigned our economy.
1243
1244@@ -694,23 +697,23 @@
1245 *
1246 * @note This is supposed to be called only from the scheduling code of @ref Fleet.
1247 */
1248-void Ship::set_destination(Game& game, PortDock& pd) {
1249+void Ship::set_destination(Game & game, PortDock & pd) {
1250 molog("set_destination to %u (currently %" PRIuS " items)\n", pd.serial(), m_items.size());
1251 m_destination = &pd;
1252 send_signal(game, "wakeup");
1253 }
1254
1255-void Ship::add_item(Game& game, const ShippingItem& item) {
1256+void Ship::add_item(Game & game, const ShippingItem & item) {
1257 assert(m_items.size() < descr().get_capacity());
1258
1259 m_items.push_back(item);
1260 m_items.back().set_location(game, this);
1261 }
1262
1263-void Ship::withdraw_items(Game& game, PortDock& pd, std::vector<ShippingItem>& items) {
1264+void Ship::withdraw_items(Game & game, PortDock & pd, std::vector<ShippingItem> & items) {
1265 uint32_t dst = 0;
1266 for (uint32_t src = 0; src < m_items.size(); ++src) {
1267- PortDock* destination = m_items[src].get_destination(game);
1268+ PortDock * destination = m_items[src].get_destination(game);
1269 if (!destination || destination == &pd) {
1270 items.push_back(m_items[src]);
1271 } else {
1272@@ -723,8 +726,8 @@
1273 /**
1274 * Find a path to the dock @p pd and follow it without using precomputed paths.
1275 */
1276-void Ship::start_task_movetodock(Game& game, PortDock& pd) {
1277- Map& map = game.map();
1278+void Ship::start_task_movetodock(Game & game, PortDock & pd) {
1279+ Map & map = game.map();
1280 StepEvalAStar se(pd.get_warehouse()->get_position());
1281 se.m_swim = true;
1282 se.m_conservative = false;
1283@@ -750,7 +753,7 @@
1284 }
1285
1286 /// Prepare everything for the coming exploration
1287-void Ship::start_task_expedition(Game& game) {
1288+void Ship::start_task_expedition(Game & game) {
1289 // Now we are waiting
1290 m_ship_state = EXP_WAITING;
1291 // Initialize a new, yet empty expedition
1292@@ -770,8 +773,8 @@
1293 set_economy(game, m_expedition->economy.get());
1294
1295 for (int i = m_items.size() - 1; i >= 0; --i) {
1296- WareInstance* ware;
1297- Worker* worker;
1298+ WareInstance * ware;
1299+ Worker * worker;
1300 m_items.at(i).get(game, &ware, &worker);
1301 if (worker) {
1302 worker->reset_tasks(game);
1303@@ -784,12 +787,12 @@
1304 // Send a message to the player, that an expedition is ready to go
1305 const std::string msg_head = _("Expedition Ready");
1306 const std::string msg_body = _("An expedition ship is waiting for your commands.");
1307- send_message(game, "exp_ready", msg_head, msg_body, "start_expedition.png");
1308+ send_message(game, msg_head, msg_body, "start_expedition.png");
1309 }
1310
1311 /// Initializes / changes the direction of scouting to @arg direction
1312 /// @note only called via player command
1313-void Ship::exp_scout_direction(Game&, uint8_t direction) {
1314+void Ship::exp_scout_direction(Game &, uint8_t direction) {
1315 assert(m_expedition);
1316 m_ship_state = EXP_SCOUTING;
1317 m_expedition->direction = direction;
1318@@ -798,7 +801,7 @@
1319
1320 /// Initializes the construction of a port at @arg c
1321 /// @note only called via player command
1322-void Ship::exp_construct_port(Game&, const Coords& c) {
1323+void Ship::exp_construct_port (Game &, const Coords& c) {
1324 assert(m_expedition);
1325 BuildingIndex port_idx = get_owner()->tribe().safe_building_index("port");
1326 get_owner()->force_csite(c, port_idx);
1327@@ -807,7 +810,7 @@
1328
1329 /// Initializes / changes the direction the island exploration in @arg clockwise direction
1330 /// @note only called via player command
1331-void Ship::exp_explore_island(Game&, bool clockwise) {
1332+void Ship::exp_explore_island (Game &, bool clockwise) {
1333 assert(m_expedition);
1334 m_ship_state = EXP_SCOUTING;
1335 m_expedition->clockwise = clockwise;
1336@@ -817,7 +820,7 @@
1337
1338 /// Cancels a currently running expedition
1339 /// @note only called via player command
1340-void Ship::exp_cancel(Game& game) {
1341+void Ship::exp_cancel (Game & game) {
1342 // Running colonization has the highest priority before cancelation
1343 // + cancelation only works if an expedition is actually running
1344 if ((m_ship_state == EXP_COLONIZING) || !state_is_expedition())
1345@@ -831,7 +834,7 @@
1346 // Theres nothing to be done for wares - they already changed
1347 // economy with us and the warehouse will make sure that they are
1348 // getting used.
1349- Worker* worker;
1350+ Worker * worker;
1351 for (ShippingItem& item : m_items) {
1352 item.get(game, nullptr, &worker);
1353 if (worker) {
1354@@ -856,7 +859,7 @@
1355
1356 /// Sinks the ship
1357 /// @note only called via player command
1358-void Ship::sink_ship(Game& game) {
1359+void Ship::sink_ship (Game & game) {
1360 // Running colonization has the highest priority + a sink request is only valid once
1361 if (!state_is_sinkable())
1362 return;
1363@@ -866,22 +869,25 @@
1364 close_window();
1365 }
1366
1367-void Ship::log_general_info(const EditorGameBase& egbase) {
1368+void Ship::log_general_info(const EditorGameBase & egbase)
1369+{
1370 Bob::log_general_info(egbase);
1371
1372- molog("Fleet: %u, destination: %u, lastdock: %u, carrying: %" PRIuS "\n",
1373- m_fleet ? m_fleet->serial() : 0,
1374- m_destination.serial(),
1375- m_lastdock.serial(),
1376- m_items.size());
1377+ molog
1378+ ("Fleet: %u, destination: %u, lastdock: %u, carrying: %" PRIuS "\n",
1379+ m_fleet? m_fleet->serial() : 0,
1380+ m_destination.serial(), m_lastdock.serial(),
1381+ m_items.size());
1382
1383 for (const ShippingItem& shipping_item : m_items) {
1384- molog(" IT %u, destination %u\n",
1385- shipping_item.m_object.serial(),
1386- shipping_item.m_destination_dock.serial());
1387+ molog
1388+ (" IT %u, destination %u\n",
1389+ shipping_item.m_object.serial(),
1390+ shipping_item.m_destination_dock.serial());
1391 }
1392 }
1393
1394+
1395 /**
1396 * Send a message to the owning player.
1397 *
1398@@ -889,31 +895,29 @@
1399 *
1400 * \param msgsender a computer-readable description of why the message was sent
1401 * \param title user-visible title of the message
1402- * \param description user-visible message body, will be placed in an appropriate rich-text
1403- *paragraph
1404+ * \param description user-visible message body, will be placed in an appropriate rich-text paragraph
1405 * \param picture picture name relative to the pics directory
1406 */
1407-void Ship::send_message(Game& game,
1408- const std::string& msgsender,
1409- const std::string& title,
1410- const std::string& description,
1411- const std::string& picture) {
1412+void Ship::send_message
1413+ (Game & game, const std::string & title, const std::string & description, const std::string & picture)
1414+{
1415 std::string rt_description;
1416 if (picture.size() > 3) {
1417- rt_description = (boost::format("<rt image=pics/%s><p font-face=serif font-size=14>")
1418- % picture).str();
1419- } else {
1420- rt_description = "<rt><p font-face=serif font-size=14>";
1421- }
1422+ rt_description = "<rt image=pics/";
1423+ rt_description += picture;
1424+ rt_description += "><p font-size=14 font-face=DejaVuSerif>";
1425+ } else
1426+ rt_description = "<rt><p font-size=14 font-face=DejaVuSerif>";
1427 rt_description += description;
1428 rt_description += "</p></rt>";
1429
1430- Message* msg =
1431- new Message(msgsender, game.get_gametime(), title, rt_description, get_position(), m_serial);
1432+ Message * msg = new Message
1433+ (Message::Type::kSeafaring, game.get_gametime(), title, rt_description, get_position(), m_serial);
1434
1435 get_owner()->add_message(game, *msg);
1436 }
1437
1438+
1439 /*
1440 ==============================
1441
1442@@ -924,16 +928,20 @@
1443
1444 #define SHIP_SAVEGAME_VERSION 4
1445
1446-Ship::Loader::Loader() : m_lastdock(0), m_destination(0) {
1447+Ship::Loader::Loader() :
1448+ m_lastdock(0),
1449+ m_destination(0)
1450+{
1451 }
1452
1453-const Bob::Task* Ship::Loader::get_task(const std::string& name) {
1454- if (name == "shipidle" || name == "ship")
1455- return &taskShip;
1456+const Bob::Task * Ship::Loader::get_task(const std::string & name)
1457+{
1458+ if (name == "shipidle" || name == "ship") return &taskShip;
1459 return Bob::Loader::get_task(name);
1460 }
1461
1462-void Ship::Loader::load(FileRead& fr, uint8_t version) {
1463+void Ship::Loader::load(FileRead & fr, uint8_t version)
1464+{
1465 Bob::Loader::load(fr);
1466
1467 if (version >= 2) {
1468@@ -942,8 +950,15 @@
1469 m_ship_state = fr.unsigned_8();
1470
1471 // Expedition specific data
1472- if (m_ship_state == EXP_SCOUTING || m_ship_state == EXP_WAITING ||
1473- m_ship_state == EXP_FOUNDPORTSPACE || m_ship_state == EXP_COLONIZING) {
1474+ if
1475+ (m_ship_state == EXP_SCOUTING
1476+ ||
1477+ m_ship_state == EXP_WAITING
1478+ ||
1479+ m_ship_state == EXP_FOUNDPORTSPACE
1480+ ||
1481+ m_ship_state == EXP_COLONIZING)
1482+ {
1483 m_expedition.reset(new Expedition());
1484 // Currently seen port build spaces
1485 m_expedition->seen_port_buildspaces.reset(new std::list<Coords>());
1486@@ -975,10 +990,11 @@
1487 }
1488 }
1489
1490-void Ship::Loader::load_pointers() {
1491+void Ship::Loader::load_pointers()
1492+{
1493 Bob::Loader::load_pointers();
1494
1495- Ship& ship = get<Ship>();
1496+ Ship & ship = get<Ship>();
1497
1498 if (m_lastdock)
1499 ship.m_lastdock = &mol().get<PortDock>(m_lastdock);
1500@@ -991,10 +1007,11 @@
1501 }
1502 }
1503
1504-void Ship::Loader::load_finish() {
1505+void Ship::Loader::load_finish()
1506+{
1507 Bob::Loader::load_finish();
1508
1509- Ship& ship = get<Ship>();
1510+ Ship & ship = get<Ship>();
1511
1512 // restore the state the ship is in
1513 ship.m_ship_state = m_ship_state;
1514@@ -1004,8 +1021,7 @@
1515 ship.m_expedition.swap(m_expedition);
1516 ship.m_expedition->economy.reset(new Economy(*ship.get_owner()));
1517 ship.m_economy = ship.m_expedition->economy.get();
1518- } else
1519- assert(m_ship_state == TRANSPORT);
1520+ } else assert(m_ship_state == TRANSPORT);
1521
1522 // Workers load code set their economy to the economy of their location
1523 // (which is a PlayerImmovable), that means that workers on ships do not get
1524@@ -1016,7 +1032,10 @@
1525 ship.set_economy(dynamic_cast<Game&>(egbase()), ship.m_economy);
1526 }
1527
1528-MapObject::Loader* Ship::load(EditorGameBase& egbase, MapObjectLoader& mol, FileRead& fr) {
1529+
1530+MapObject::Loader * Ship::load
1531+ (EditorGameBase & egbase, MapObjectLoader & mol, FileRead & fr)
1532+{
1533 std::unique_ptr<Loader> loader(new Loader);
1534
1535 try {
1536@@ -1026,28 +1045,32 @@
1537 if (1 <= version && version <= SHIP_SAVEGAME_VERSION) {
1538 std::string owner = fr.c_string();
1539 std::string name = fr.c_string();
1540- const ShipDescr* descr = nullptr;
1541+ const ShipDescr * descr = nullptr;
1542
1543 egbase.manually_load_tribe(owner);
1544
1545- if (const TribeDescr* tribe = egbase.get_tribe(owner))
1546- descr = dynamic_cast<const ShipDescr*>(tribe->get_bob_descr(name));
1547+ if (const TribeDescr * tribe = egbase.get_tribe(owner))
1548+ descr = dynamic_cast<const ShipDescr *>
1549+ (tribe->get_bob_descr(name));
1550
1551 if (!descr)
1552- throw GameDataError("undefined ship %s/%s", owner.c_str(), name.c_str());
1553+ throw GameDataError
1554+ ("undefined ship %s/%s", owner.c_str(), name.c_str());
1555
1556 loader->init(egbase, mol, descr->create_object());
1557 loader->load(fr, version);
1558 } else
1559 throw GameDataError("unknown/unhandled version %u", version);
1560- } catch (const std::exception& e) {
1561+ } catch (const std::exception & e) {
1562 throw wexception("loading ship: %s", e.what());
1563 }
1564
1565 return loader.release();
1566 }
1567
1568-void Ship::save(EditorGameBase& egbase, MapObjectSaver& mos, FileWrite& fw) {
1569+void Ship::save
1570+ (EditorGameBase & egbase, MapObjectSaver & mos, FileWrite & fw)
1571+{
1572 fw.unsigned_8(HeaderShip);
1573 fw.unsigned_8(SHIP_SAVEGAME_VERSION);
1574
1575@@ -1064,9 +1087,11 @@
1576 // currently seen port buildspaces
1577 assert(m_expedition->seen_port_buildspaces);
1578 fw.unsigned_8(m_expedition->seen_port_buildspaces->size());
1579- for (std::list<Coords>::const_iterator it = m_expedition->seen_port_buildspaces->begin();
1580- it != m_expedition->seen_port_buildspaces->end();
1581- ++it) {
1582+ for
1583+ (std::list<Coords>::const_iterator it = m_expedition->seen_port_buildspaces->begin();
1584+ it != m_expedition->seen_port_buildspaces->end();
1585+ ++it)
1586+ {
1587 write_coords_32(&fw, *it);
1588 }
1589 // swimability of the directions
1590@@ -1091,4 +1116,4 @@
1591 }
1592 }
1593
1594-} // namespace Widelands
1595+} // namespace Widelands
1596
1597=== modified file 'src/logic/ship.h'
1598--- src/logic/ship.h 2014-09-10 08:55:04 +0000
1599+++ src/logic/ship.h 2014-12-28 17:03:29 +0000
1600@@ -208,8 +208,7 @@
1601 void init_fleet(EditorGameBase &);
1602 void set_fleet(Fleet * fleet);
1603
1604- void send_message
1605- (Game &, const std::string &, const std::string &, const std::string &, const std::string &);
1606+ void send_message(Game &, const std::string &, const std::string &, const std::string &);
1607
1608 UI::Window * m_window;
1609
1610
1611=== modified file 'src/logic/soldier.cc'
1612--- src/logic/soldier.cc 2014-11-30 18:49:38 +0000
1613+++ src/logic/soldier.cc 2014-12-28 17:03:29 +0000
1614@@ -1571,7 +1571,7 @@
1615 owner().add_message
1616 (game,
1617 *new Message
1618- ("game engine",
1619+ (Message::Type::kGameLogic,
1620 game.get_gametime(),
1621 _("Logic error"),
1622 messagetext,
1623@@ -1580,7 +1580,7 @@
1624 opponent.owner().add_message
1625 (game,
1626 *new Message
1627- ("game engine",
1628+ (Message::Type::kGameLogic,
1629 game.get_gametime(),
1630 _("Logic error"),
1631 messagetext,
1632
1633=== modified file 'src/logic/warehouse.cc'
1634--- src/logic/warehouse.cc 2014-12-12 22:59:39 +0000
1635+++ src/logic/warehouse.cc 2014-12-28 17:03:29 +0000
1636@@ -50,7 +50,7 @@
1637
1638 namespace Widelands {
1639
1640-namespace {
1641+namespace {
1642
1643 static const uint32_t WORKER_WITHOUT_COST_SPAWN_INTERVAL = 2500;
1644
1645@@ -68,17 +68,19 @@
1646
1647 } // namespace
1648
1649-WarehouseSupply::~WarehouseSupply() {
1650+WarehouseSupply::~WarehouseSupply()
1651+{
1652 if (m_economy) {
1653- log("WarehouseSupply::~WarehouseSupply: Warehouse %u still belongs to "
1654- "an economy",
1655- m_warehouse->serial());
1656+ log
1657+ ("WarehouseSupply::~WarehouseSupply: Warehouse %u still belongs to "
1658+ "an economy",
1659+ m_warehouse->serial());
1660 set_economy(nullptr);
1661 }
1662
1663 // We're removed from the Economy. Therefore, the wares can simply
1664 // be cleared out. The global inventory will be okay.
1665- m_wares.clear();
1666+ m_wares .clear();
1667 m_workers.clear();
1668 }
1669
1670@@ -94,8 +96,10 @@
1671 m_workers.set_nrwares(i);
1672 }
1673
1674+
1675 /// Add and remove our wares and the Supply to the economies as necessary.
1676-void WarehouseSupply::set_economy(Economy* const e) {
1677+void WarehouseSupply::set_economy(Economy * const e)
1678+{
1679 if (e == m_economy)
1680 return;
1681
1682@@ -122,74 +126,87 @@
1683 }
1684 }
1685
1686+
1687 /// Add wares and update the economy.
1688-void WarehouseSupply::add_wares(WareIndex const id, uint32_t const count) {
1689+void WarehouseSupply::add_wares(WareIndex const id, uint32_t const count)
1690+{
1691 if (!count)
1692 return;
1693
1694- if (m_economy) // No economies in the editor
1695+ if (m_economy) // No economies in the editor
1696 m_economy->add_wares(id, count);
1697 m_wares.add(id, count);
1698 }
1699
1700+
1701 /// Remove wares and update the economy.
1702-void WarehouseSupply::remove_wares(WareIndex const id, uint32_t const count) {
1703+void WarehouseSupply::remove_wares(WareIndex const id, uint32_t const count)
1704+{
1705 if (!count)
1706 return;
1707
1708 m_wares.remove(id, count);
1709- if (m_economy) // No economies in the editor
1710+ if (m_economy) // No economies in the editor
1711 m_economy->remove_wares(id, count);
1712 }
1713
1714+
1715 /// Add workers and update the economy.
1716-void WarehouseSupply::add_workers(WareIndex const id, uint32_t const count) {
1717+void WarehouseSupply::add_workers(WareIndex const id, uint32_t const count)
1718+{
1719 if (!count)
1720 return;
1721
1722- if (m_economy) // No economies in the editor
1723+ if (m_economy) // No economies in the editor
1724 m_economy->add_workers(id, count);
1725 m_workers.add(id, count);
1726 }
1727
1728+
1729 /**
1730 * Remove workers and update the economy.
1731 * Comments see add_workers
1732 */
1733-void WarehouseSupply::remove_workers(WareIndex const id, uint32_t const count) {
1734+void WarehouseSupply::remove_workers(WareIndex const id, uint32_t const count)
1735+{
1736 if (!count)
1737 return;
1738
1739 m_workers.remove(id, count);
1740- if (m_economy) // No economies in the editor
1741+ if (m_economy) // No economies in the editor
1742 m_economy->remove_workers(id, count);
1743 }
1744
1745 /// Return the position of the Supply, i.e. the owning Warehouse.
1746-PlayerImmovable* WarehouseSupply::get_position(Game&) {
1747- return m_warehouse;
1748-}
1749+PlayerImmovable * WarehouseSupply::get_position(Game &) {return m_warehouse;}
1750+
1751
1752 /// Warehouse supplies are never active.
1753-bool WarehouseSupply::is_active() const {
1754- return false;
1755-}
1756+bool WarehouseSupply::is_active() const {return false;}
1757
1758-bool WarehouseSupply::has_storage() const {
1759+bool WarehouseSupply::has_storage() const
1760+{
1761 return true;
1762 }
1763
1764-void WarehouseSupply::get_ware_type(WareWorker& /* type */, WareIndex& /* ware */) const {
1765- throw wexception("WarehouseSupply::get_ware_type: calling this is nonsensical");
1766+void WarehouseSupply::get_ware_type(WareWorker & /* type */, WareIndex & /* ware */) const
1767+{
1768+ throw wexception
1769+ ("WarehouseSupply::get_ware_type: calling this is nonsensical");
1770 }
1771
1772-void WarehouseSupply::send_to_storage(Game&, Warehouse* /* wh */) {
1773+void WarehouseSupply::send_to_storage(Game &, Warehouse * /* wh */)
1774+{
1775 throw wexception("WarehouseSupply::send_to_storage: should never be called");
1776 }
1777
1778-uint32_t WarehouseSupply::nr_supplies(const Game& game, const Request& req) const {
1779+uint32_t WarehouseSupply::nr_supplies
1780+ (const Game & game, const Request & req) const
1781+{
1782 if (req.get_type() == wwWORKER)
1783- return m_warehouse->count_workers(game, req.get_index(), req.get_requirements());
1784+ return
1785+ m_warehouse->count_workers
1786+ (game, req.get_index(), req.get_requirements());
1787
1788 // Calculate how many wares can be sent out - it might be that we need them
1789 // ourselves. E.g. for hiring new soldiers.
1790@@ -199,16 +216,18 @@
1791 // of *this* warehouse + 1 (+1 is important, as else the ware would directly
1792 // be taken back to the warehouse as the request of the warehouse would be
1793 // highered and would have the same value as the original request)
1794- int32_t const y = x + (req.get_priority(0) / 100) -
1795- (m_warehouse->get_priority(wwWARE, req.get_index()) / 100) - 1;
1796+ int32_t const y =
1797+ x + (req.get_priority(0) / 100)
1798+ - (m_warehouse->get_priority(wwWARE, req.get_index()) / 100) - 1;
1799 // But the number should never be higher than the number of wares available
1800 if (y > x)
1801 return x;
1802 return (x > 0) ? x : 0;
1803 }
1804
1805+
1806 /// Launch a ware.
1807-WareInstance& WarehouseSupply::launch_ware(Game& game, const Request& req) {
1808+WareInstance & WarehouseSupply::launch_ware(Game & game, const Request & req) {
1809 if (req.get_type() != wwWARE)
1810 throw wexception("WarehouseSupply::launch_ware: called for non-ware request");
1811 if (!m_wares.stock(req.get_index()))
1812@@ -218,26 +237,29 @@
1813 }
1814
1815 /// Launch a ware as worker.
1816-Worker& WarehouseSupply::launch_worker(Game& game, const Request& req) {
1817- return m_warehouse->launch_worker(game, req.get_index(), req.get_requirements());
1818+Worker & WarehouseSupply::launch_worker(Game & game, const Request & req)
1819+{
1820+ return
1821+ m_warehouse->launch_worker
1822+ (game, req.get_index(), req.get_requirements());
1823 }
1824
1825+
1826 /*
1827 ==============================
1828 Warehouse Building
1829 ==============================
1830 */
1831
1832+
1833 /// Warehouse Descr
1834-WarehouseDescr::WarehouseDescr(char const* const _name,
1835- char const* const _descname,
1836- const std::string& directory,
1837- Profile& prof,
1838- Section& global_s,
1839- const TribeDescr& _tribe)
1840- : BuildingDescr(MapObjectType::WAREHOUSE, _name, _descname, directory, prof, global_s, _tribe),
1841- m_conquers(0),
1842- m_heal_per_second(0) {
1843+WarehouseDescr::WarehouseDescr
1844+ (char const* const _name, char const* const _descname,
1845+ const std::string& directory, Profile& prof, Section& global_s, const TribeDescr& _tribe)
1846+ : BuildingDescr(MapObjectType::WAREHOUSE, _name, _descname, directory, prof, global_s, _tribe),
1847+ m_conquers (0),
1848+ m_heal_per_second (0)
1849+{
1850 m_heal_per_second = global_s.get_safe_int("heal_per_second");
1851 if ((m_conquers = prof.get_safe_section("global").get_positive("conquers", 0)))
1852 m_workarea_info[m_conquers].insert(descname() + " conquer");
1853@@ -249,21 +271,25 @@
1854 ==============================
1855 */
1856
1857-Warehouse::Warehouse(const WarehouseDescr& warehouse_descr)
1858- : Building(warehouse_descr),
1859- m_supply(new WarehouseSupply(this)),
1860- m_next_military_act(0),
1861- m_portdock(nullptr) {
1862+Warehouse::Warehouse(const WarehouseDescr & warehouse_descr) :
1863+ Building(warehouse_descr),
1864+ m_supply(new WarehouseSupply(this)),
1865+ m_next_military_act(0),
1866+ m_portdock(nullptr)
1867+{
1868 uint8_t nr_worker_types_without_cost =
1869- warehouse_descr.tribe().worker_types_without_cost().size();
1870- m_next_worker_without_cost_spawn = new uint32_t[nr_worker_types_without_cost];
1871+ warehouse_descr.tribe().worker_types_without_cost().size();
1872+ m_next_worker_without_cost_spawn =
1873+ new uint32_t[nr_worker_types_without_cost];
1874 for (int i = 0; i < nr_worker_types_without_cost; ++i) {
1875 m_next_worker_without_cost_spawn[i] = never();
1876 }
1877 m_next_stock_remove_act = 0;
1878 }
1879
1880-Warehouse::~Warehouse() {
1881+
1882+Warehouse::~Warehouse()
1883+{
1884 delete m_supply;
1885 delete[] m_next_worker_without_cost_spawn;
1886 }
1887@@ -272,19 +298,22 @@
1888 * Try to bring the given \ref PlannedWorkers up to date with our game data.
1889 * Return \c false if \p pw cannot be salvaged.
1890 */
1891-bool Warehouse::_load_finish_planned_worker(PlannedWorkers& pw) {
1892+bool Warehouse::_load_finish_planned_worker(PlannedWorkers & pw)
1893+{
1894 if (pw.index == INVALID_INDEX || !(pw.index < m_supply->get_workers().get_nrwareids()))
1895 return false;
1896
1897- const WorkerDescr* w_desc = descr().tribe().get_worker_descr(pw.index);
1898+ const WorkerDescr * w_desc = descr().tribe().get_worker_descr(pw.index);
1899 if (!w_desc || !w_desc->is_buildable())
1900 return false;
1901
1902- const WorkerDescr::Buildcost& cost = w_desc->buildcost();
1903+ const WorkerDescr::Buildcost & cost = w_desc->buildcost();
1904 uint32_t idx = 0;
1905
1906- for (WorkerDescr::Buildcost::const_iterator cost_it = cost.begin(); cost_it != cost.end();
1907- ++cost_it, ++idx) {
1908+ for
1909+ (WorkerDescr::Buildcost::const_iterator cost_it = cost.begin();
1910+ cost_it != cost.end(); ++cost_it, ++idx)
1911+ {
1912 WareWorker type;
1913 WareIndex ware;
1914 ware = descr().tribe().ware_index(cost_it->first);
1915@@ -296,10 +325,13 @@
1916 return false;
1917
1918 if (idx < pw.requests.size()) {
1919- if (pw.requests[idx]->get_type() == type && pw.requests[idx]->get_index() == ware)
1920+ if
1921+ (pw.requests[idx]->get_type() == type &&
1922+ pw.requests[idx]->get_index() == ware)
1923 continue;
1924
1925- std::vector<Request*>::iterator req_it = pw.requests.begin() + idx + 1;
1926+ std::vector<Request *>::iterator req_it =
1927+ pw.requests.begin() + idx + 1;
1928 while (req_it != pw.requests.end()) {
1929 if ((*req_it)->get_type() == type && (*req_it)->get_index() == ware)
1930 break;
1931@@ -312,16 +344,19 @@
1932 }
1933 }
1934
1935- log("_load_finish_planned_worker: old savegame: "
1936- "need to create new request for '%s'\n",
1937- cost_it->first.c_str());
1938- pw.requests.insert(
1939- pw.requests.begin() + idx, new Request(*this, ware, &Warehouse::request_cb, type));
1940+ log
1941+ ("_load_finish_planned_worker: old savegame: "
1942+ "need to create new request for '%s'\n",
1943+ cost_it->first.c_str());
1944+ pw.requests.insert
1945+ (pw.requests.begin() + idx,
1946+ new Request(*this, ware, &Warehouse::request_cb, type));
1947 }
1948
1949 while (pw.requests.size() > idx) {
1950- log("_load_finish_planned_worker: old savegame: "
1951- "removing outdated request.\n");
1952+ log
1953+ ("_load_finish_planned_worker: old savegame: "
1954+ "removing outdated request.\n");
1955 delete pw.requests.back();
1956 pw.requests.pop_back();
1957 }
1958@@ -329,31 +364,30 @@
1959 return true;
1960 }
1961
1962-void Warehouse::load_finish(EditorGameBase& egbase) {
1963+void Warehouse::load_finish(EditorGameBase & egbase) {
1964 Building::load_finish(egbase);
1965
1966 uint32_t next_spawn = never();
1967- const std::vector<WareIndex>& worker_types_without_cost =
1968- descr().tribe().worker_types_without_cost();
1969+ const std::vector<WareIndex> & worker_types_without_cost =
1970+ descr().tribe().worker_types_without_cost();
1971 for (uint8_t i = worker_types_without_cost.size(); i;) {
1972 WareIndex const worker_index = worker_types_without_cost.at(--i);
1973- if (owner().is_worker_type_allowed(worker_index) &&
1974- m_next_worker_without_cost_spawn[i] == static_cast<uint32_t>(never())) {
1975+ if
1976+ (owner().is_worker_type_allowed(worker_index) &&
1977+ m_next_worker_without_cost_spawn[i] == static_cast<uint32_t>(never()))
1978+ {
1979 if (next_spawn == static_cast<uint32_t>(never())) {
1980- next_spawn =
1981- schedule_act(dynamic_cast<Game&>(egbase), WORKER_WITHOUT_COST_SPAWN_INTERVAL);
1982+ next_spawn = schedule_act(dynamic_cast<Game&>(egbase), WORKER_WITHOUT_COST_SPAWN_INTERVAL);
1983 }
1984 m_next_worker_without_cost_spawn[i] = next_spawn;
1985- log("WARNING: player %u is allowed to create worker type %s but his "
1986- "%s %u at (%i, %i) does not have a next_spawn time set for that "
1987- "worker type; setting it to %u\n",
1988- owner().player_number(),
1989- descr().tribe().get_worker_descr(worker_index)->descname().c_str(),
1990- descr().descname().c_str(),
1991- serial(),
1992- get_position().x,
1993- get_position().y,
1994- next_spawn);
1995+ log
1996+ ("WARNING: player %u is allowed to create worker type %s but his "
1997+ "%s %u at (%i, %i) does not have a next_spawn time set for that "
1998+ "worker type; setting it to %u\n",
1999+ owner().player_number(),
2000+ descr().tribe().get_worker_descr(worker_index)->descname().c_str(),
2001+ descr().descname().c_str(), serial(), get_position().x, get_position().y,
2002+ next_spawn);
2003 }
2004 }
2005
2006@@ -371,12 +405,13 @@
2007 }
2008 }
2009
2010-void Warehouse::init(EditorGameBase& egbase) {
2011+void Warehouse::init(EditorGameBase & egbase)
2012+{
2013 Building::init(egbase);
2014
2015- WareIndex const nr_wares = descr().tribe().get_nrwares();
2016+ WareIndex const nr_wares = descr().tribe().get_nrwares ();
2017 WareIndex const nr_workers = descr().tribe().get_nrworkers();
2018- m_supply->set_nrwares(nr_wares);
2019+ m_supply->set_nrwares (nr_wares);
2020 m_supply->set_nrworkers(nr_workers);
2021
2022 m_ware_policy.resize(nr_wares, SP_Normal);
2023@@ -385,15 +420,17 @@
2024 // Even though technically, a warehouse might be completely empty,
2025 // we let warehouse see always for simplicity's sake (since there's
2026 // almost always going to be a carrier inside, that shouldn't hurt).
2027- Player& player = owner();
2028+ Player & player = owner();
2029 if (upcast(Game, game, &egbase)) {
2030- player.see_area(
2031- Area<FCoords>(egbase.map().get_fcoords(get_position()), descr().vision_range()));
2032+ player.see_area
2033+ (Area<FCoords>
2034+ (egbase.map().get_fcoords(get_position()), descr().vision_range()));
2035
2036 {
2037- uint32_t const act_time = schedule_act(*game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
2038- const std::vector<WareIndex>& worker_types_without_cost =
2039- descr().tribe().worker_types_without_cost();
2040+ uint32_t const act_time = schedule_act
2041+ (*game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
2042+ const std::vector<WareIndex> & worker_types_without_cost =
2043+ descr().tribe().worker_types_without_cost();
2044
2045 for (size_t i = 0; i < worker_types_without_cost.size(); ++i) {
2046 if (owner().is_worker_type_allowed(worker_types_without_cost.at(i))) {
2047@@ -408,21 +445,38 @@
2048
2049 m_next_stock_remove_act = schedule_act(*game, 4000);
2050
2051- log("Message: adding (wh) (%s) %i \n",
2052- to_string(descr().type()).c_str(),
2053- player.player_number());
2054- send_message(*game,
2055- "warehouse",
2056- descr().descname(),
2057- (boost::format(_("A new %s was added to your economy.")) %
2058- descr().descname().c_str()).str(),
2059- true);
2060+ log("Message: adding (wh) (%s) %i \n", to_string(descr().type()).c_str(), player.player_number());
2061+
2062+ if (descr().name() == "port") {
2063+ send_message
2064+ (*game,
2065+ Message::Type::kSeafaring,
2066+ descr().descname(),
2067+ _("A new port was added to your economy."),
2068+ true);
2069+ } else if (descr().name() == "headquarters") {
2070+ send_message
2071+ (*game,
2072+ Message::Type::kEconomy,
2073+ descr().descname(),
2074+ _("A new headquarters was added to your economy."),
2075+ true);
2076+ } else {
2077+ send_message
2078+ (*game,
2079+ Message::Type::kEconomy,
2080+ descr().descname(),
2081+ _("A new warehouse was added to your economy."),
2082+ true);
2083+ }
2084 }
2085
2086 if (uint32_t const conquer_radius = descr().get_conquers())
2087- egbase.conquer_area(PlayerArea<Area<FCoords>>(
2088- player.player_number(),
2089- Area<FCoords>(egbase.map().get_fcoords(get_position()), conquer_radius)));
2090+ egbase.conquer_area
2091+ (PlayerArea<Area<FCoords> >
2092+ (player.player_number(),
2093+ Area<FCoords>
2094+ (egbase.map().get_fcoords(get_position()), conquer_radius)));
2095
2096 if (descr().get_isport())
2097 init_portdock(egbase);
2098@@ -432,10 +486,11 @@
2099 * Find a contiguous set of water fields close to the port for docking
2100 * and initialize the @ref PortDock instance.
2101 */
2102-void Warehouse::init_portdock(EditorGameBase& egbase) {
2103+void Warehouse::init_portdock(EditorGameBase & egbase)
2104+{
2105 molog("Setting up port dock fields\n");
2106
2107- Map& map = egbase.map();
2108+ Map & map = egbase.map();
2109 std::vector<Coords> dock = map.find_portdock(get_position());
2110 if (dock.empty()) {
2111 log("Attempting to setup port without neighboring water.\n");
2112@@ -456,12 +511,14 @@
2113 m_portdock->set_economy(get_economy());
2114 }
2115
2116-void Warehouse::destroy(EditorGameBase& egbase) {
2117+void Warehouse::destroy(EditorGameBase & egbase)
2118+{
2119 Building::destroy(egbase);
2120 }
2121
2122 /// Destroy the warehouse.
2123-void Warehouse::cleanup(EditorGameBase& egbase) {
2124+void Warehouse::cleanup(EditorGameBase & egbase)
2125+{
2126 if (egbase.objects().object_still_available(m_portdock)) {
2127 m_portdock->remove(egbase);
2128 m_portdock = nullptr;
2129@@ -488,18 +545,21 @@
2130
2131 Map& map = egbase.map();
2132 if (const uint32_t conquer_radius = descr().get_conquers())
2133- egbase.unconquer_area(
2134- PlayerArea<Area<FCoords>>(owner().player_number(),
2135- Area<FCoords>(map.get_fcoords(get_position()), conquer_radius)),
2136- m_defeating_player);
2137+ egbase.unconquer_area
2138+ (PlayerArea<Area<FCoords> >
2139+ (owner().player_number(),
2140+ Area<FCoords>(map.get_fcoords(get_position()), conquer_radius)),
2141+ m_defeating_player);
2142
2143 // Unsee the area that we started seeing in init()
2144- Player& player = owner();
2145- player.unsee_area(Area<FCoords>(map.get_fcoords(get_position()), descr().vision_range()));
2146+ Player & player = owner();
2147+ player.unsee_area
2148+ (Area<FCoords>(map.get_fcoords(get_position()), descr().vision_range()));
2149
2150 Building::cleanup(egbase);
2151 }
2152
2153+
2154 /// Act regularly to create workers of buildable types without cost. According
2155 /// to intelligence, this is some highly advanced technology. Not only do the
2156 /// settlers have no problems with birth control, they do not even need anybody
2157@@ -507,11 +567,12 @@
2158 /// what the hell are they doing, killing useless tribesmen! The Borg? Or just
2159 /// like Soylent Green? Or maybe I should just stop writing comments that late
2160 /// at night ;-)
2161-void Warehouse::act(Game& game, uint32_t const data) {
2162+void Warehouse::act(Game & game, uint32_t const data)
2163+{
2164 uint32_t const gametime = game.get_gametime();
2165 {
2166- const std::vector<WareIndex>& worker_types_without_cost =
2167- owner().tribe().worker_types_without_cost();
2168+ const std::vector<WareIndex> & worker_types_without_cost =
2169+ owner().tribe().worker_types_without_cost();
2170 for (size_t i = worker_types_without_cost.size(); i;)
2171 if (m_next_worker_without_cost_spawn[--i] <= gametime) {
2172 WareIndex const id = worker_types_without_cost.at(i);
2173@@ -529,7 +590,8 @@
2174 remove_workers(id, 1);
2175 }
2176
2177- m_next_worker_without_cost_spawn[i] = schedule_act(game, tdelta);
2178+ m_next_worker_without_cost_spawn[i] =
2179+ schedule_act(game, tdelta);
2180 } else
2181 m_next_worker_without_cost_spawn[i] = never();
2182 }
2183@@ -540,15 +602,19 @@
2184 WareIndex const ware = descr().tribe().safe_worker_index("soldier");
2185
2186 if (m_incorporated_workers.count(ware)) {
2187- WorkerList& soldiers = m_incorporated_workers[ware];
2188+ WorkerList & soldiers = m_incorporated_workers[ware];
2189
2190 uint32_t total_heal = descr().get_heal_per_second();
2191 // Using an explicit iterator, as we plan to erase some
2192 // of those guys
2193- for (WorkerList::iterator it = soldiers.begin(); it != soldiers.end(); ++it) {
2194+ for
2195+ (WorkerList::iterator it = soldiers.begin();
2196+ it != soldiers.end();
2197+ ++it)
2198+ {
2199 // This is a safe cast: we know only soldiers can land in this
2200 // slot in the incorporated array
2201- Soldier* soldier = static_cast<Soldier*>(*it);
2202+ Soldier * soldier = static_cast<Soldier *>(*it);
2203
2204 // Soldier dead ...
2205 if (!soldier || soldier->get_current_hitpoints() == 0) {
2206@@ -561,6 +627,7 @@
2207 soldier->heal(total_heal);
2208 continue;
2209 }
2210+
2211 }
2212 }
2213 m_next_military_act = schedule_act(game, 1000);
2214@@ -581,9 +648,11 @@
2215 Building::act(game, data);
2216 }
2217
2218+
2219 /// Transfer our registration to the new economy.
2220-void Warehouse::set_economy(Economy* const e) {
2221- Economy* const old = get_economy();
2222+void Warehouse::set_economy(Economy * const e)
2223+{
2224+ Economy * const old = get_economy();
2225
2226 if (old == e)
2227 return;
2228@@ -597,7 +666,7 @@
2229 Building::set_economy(e);
2230
2231 for (const PlannedWorkers& pw : m_planned_workers) {
2232- for (Request* req : pw.requests) {
2233+ for (Request * req : pw.requests) {
2234 req->set_economy(e);
2235 }
2236 }
2237@@ -609,62 +678,82 @@
2238 e->add_warehouse(*this);
2239 }
2240
2241-const WareList& Warehouse::get_wares() const {
2242+
2243+const WareList & Warehouse::get_wares() const
2244+{
2245 return m_supply->get_wares();
2246 }
2247
2248-const WareList& Warehouse::get_workers() const {
2249+
2250+const WareList & Warehouse::get_workers() const
2251+{
2252 return m_supply->get_workers();
2253 }
2254
2255-PlayerImmovable::Workers Warehouse::get_incorporated_workers() {
2256+PlayerImmovable::Workers Warehouse::get_incorporated_workers()
2257+{
2258 PlayerImmovable::Workers all_workers;
2259
2260 for (const std::pair<WareIndex, WorkerList>& worker_pair : m_incorporated_workers) {
2261- for (Worker* worker : worker_pair.second) {
2262+ for (Worker * worker : worker_pair.second) {
2263 all_workers.push_back(worker);
2264 }
2265 }
2266 return all_workers;
2267 }
2268
2269+
2270 /// Magically create wares in this warehouse. Updates the economy accordingly.
2271-void Warehouse::insert_wares(WareIndex const id, uint32_t const count) {
2272+void Warehouse::insert_wares(WareIndex const id, uint32_t const count)
2273+{
2274 m_supply->add_wares(id, count);
2275 }
2276
2277+
2278 /// Magically destroy wares.
2279-void Warehouse::remove_wares(WareIndex const id, uint32_t const count) {
2280+void Warehouse::remove_wares(WareIndex const id, uint32_t const count)
2281+{
2282 m_supply->remove_wares(id, count);
2283 }
2284
2285+
2286 /// Magically create workers in this warehouse. Updates the economy accordingly.
2287-void Warehouse::insert_workers(WareIndex const id, uint32_t const count) {
2288+void Warehouse::insert_workers(WareIndex const id, uint32_t const count)
2289+{
2290 m_supply->add_workers(id, count);
2291 }
2292
2293+
2294 /// Magically destroy workers.
2295-void Warehouse::remove_workers(WareIndex const id, uint32_t const count) {
2296+void Warehouse::remove_workers(WareIndex const id, uint32_t const count)
2297+{
2298 m_supply->remove_workers(id, count);
2299 }
2300
2301+
2302+
2303 /// Launch a carrier to fetch an ware from our flag.
2304-bool Warehouse::fetch_from_flag(Game& game) {
2305+bool Warehouse::fetch_from_flag(Game & game)
2306+{
2307 WareIndex const carrierid = descr().tribe().safe_worker_index("carrier");
2308
2309- if (!m_supply->stock_workers(carrierid)) // XXX yep, let's cheat
2310+ if (!m_supply->stock_workers(carrierid)) // XXX yep, let's cheat
2311 insert_workers(carrierid, 1);
2312
2313- launch_worker(game, carrierid, Requirements()).start_task_fetchfromflag(game);
2314+ launch_worker(game, carrierid, Requirements()).start_task_fetchfromflag
2315+ (game);
2316
2317 return true;
2318 }
2319
2320+
2321 /**
2322 * \return the number of workers that we can launch satisfying the given
2323 * requirements.
2324 */
2325-uint32_t Warehouse::count_workers(const Game& /* game */, WareIndex ware, const Requirements& req) {
2326+uint32_t Warehouse::count_workers
2327+ (const Game & /* game */, WareIndex ware, const Requirements & req)
2328+{
2329 uint32_t sum = 0;
2330
2331 do {
2332@@ -672,7 +761,7 @@
2333
2334 // NOTE: This code lies about the TrainingAttributes of non-instantiated workers.
2335 if (m_incorporated_workers.count(ware)) {
2336- for (Worker* worker : m_incorporated_workers[ware]) {
2337+ for (Worker * worker : m_incorporated_workers[ware]) {
2338 if (!req.check(*worker)) {
2339 // This is one of the workers in our sum.
2340 // But he is too stupid for this job
2341@@ -689,7 +778,9 @@
2342
2343 /// Start a worker of a given type. The worker will
2344 /// be assigned a job by the caller.
2345-Worker& Warehouse::launch_worker(Game& game, WareIndex ware, const Requirements& req) {
2346+Worker & Warehouse::launch_worker
2347+ (Game & game, WareIndex ware, const Requirements & req)
2348+{
2349 do {
2350 if (m_supply->stock_workers(ware)) {
2351 uint32_t unincorporated = m_supply->stock_workers(ware);
2352@@ -702,15 +793,15 @@
2353 remove_no_longer_existing_workers(game, &m_incorporated_workers[ware]);
2354 WorkerList& incorporated_workers = m_incorporated_workers[ware];
2355
2356- for (std::vector<Worker*>::iterator worker_iter = incorporated_workers.begin();
2357- worker_iter != incorporated_workers.end();
2358- ++worker_iter) {
2359+ for (std::vector<Worker *>::iterator worker_iter = incorporated_workers.begin();
2360+ worker_iter != incorporated_workers.end(); ++worker_iter)
2361+ {
2362 Worker* worker = *worker_iter;
2363 --unincorporated;
2364
2365 if (req.check(*worker)) {
2366- worker->reset_tasks(game); // forget everything you did
2367- worker->set_location(this); // back in a economy
2368+ worker->reset_tasks(game); // forget everything you did
2369+ worker->set_location(this); // back in a economy
2370 incorporated_workers.erase(worker_iter);
2371
2372 m_supply->remove_workers(ware, 1);
2373@@ -725,7 +816,7 @@
2374 // Create a new one
2375 // NOTE: This code lies about the TrainingAttributes of the new worker
2376 m_supply->remove_workers(ware, 1);
2377- const WorkerDescr& workerdescr = *descr().tribe().get_worker_descr(ware);
2378+ const WorkerDescr & workerdescr = *descr().tribe().get_worker_descr(ware);
2379 return workerdescr.create(game, owner(), this, m_position);
2380 }
2381 }
2382@@ -738,10 +829,13 @@
2383 }
2384 } while (ware != INVALID_INDEX);
2385
2386- throw wexception("Warehouse::launch_worker: worker does not actually exist");
2387+ throw wexception
2388+ ("Warehouse::launch_worker: worker does not actually exist");
2389 }
2390
2391-void Warehouse::incorporate_worker(EditorGameBase& egbase, Worker* w) {
2392+
2393+void Warehouse::incorporate_worker(EditorGameBase & egbase, Worker* w)
2394+{
2395 assert(w != nullptr);
2396 assert(w->get_owner() == &owner());
2397
2398@@ -767,10 +861,10 @@
2399
2400 // Incorporate the worker
2401 if (!m_incorporated_workers.count(worker_index))
2402- m_incorporated_workers[worker_index] = std::vector<Worker*>();
2403+ m_incorporated_workers[worker_index] = std::vector<Worker *>();
2404 m_incorporated_workers[worker_index].push_back(w);
2405
2406- w->set_location(nullptr); // no longer in an economy
2407+ w->set_location(nullptr); // no longer in an economy
2408
2409 if (upcast(Game, game, &egbase)) {
2410 // Bind the worker into this house, hide him on the map.
2411@@ -781,9 +875,9 @@
2412
2413 /// Create an instance of a ware and make sure it gets
2414 /// carried out of the warehouse.
2415-WareInstance& Warehouse::launch_ware(Game& game, WareIndex const ware_index) {
2416+WareInstance & Warehouse::launch_ware(Game & game, WareIndex const ware_index) {
2417 // Create the ware
2418- WareInstance& ware = *new WareInstance(ware_index, descr().tribe().get_ware_descr(ware_index));
2419+ WareInstance & ware = *new WareInstance(ware_index, descr().tribe().get_ware_descr(ware_index));
2420 ware.init(game);
2421 do_launch_ware(game, ware);
2422
2423@@ -792,13 +886,15 @@
2424 return ware;
2425 }
2426
2427+
2428 /// Get a carrier to actually move this ware out of the warehouse.
2429-void Warehouse::do_launch_ware(Game& game, WareInstance& ware) {
2430+void Warehouse::do_launch_ware(Game & game, WareInstance & ware)
2431+{
2432 // Create a carrier
2433 WareIndex const carrierid = descr().tribe().worker_index("carrier");
2434- const WorkerDescr& workerdescr = *descr().tribe().get_worker_descr(carrierid);
2435+ const WorkerDescr & workerdescr = *descr().tribe().get_worker_descr(carrierid);
2436
2437- Worker& worker = workerdescr.create(game, owner(), this, m_position);
2438+ Worker & worker = workerdescr.create(game, owner(), this, m_position);
2439
2440 // Yup, this is cheating.
2441 if (m_supply->stock_workers(carrierid))
2442@@ -808,15 +904,23 @@
2443 worker.start_task_dropoff(game, ware);
2444 }
2445
2446-void Warehouse::incorporate_ware(EditorGameBase& egbase, WareInstance* ware) {
2447+
2448+void Warehouse::incorporate_ware(EditorGameBase & egbase, WareInstance* ware)
2449+{
2450 m_supply->add_wares(ware->descr_index(), 1);
2451 ware->destroy(egbase);
2452 }
2453
2454+
2455 /// Called when a transfer for one of the idle Requests completes.
2456-void Warehouse::request_cb(
2457- Game& game, Request&, WareIndex const ware, Worker* const w, PlayerImmovable& target) {
2458- Warehouse& wh = dynamic_cast<Warehouse&>(target);
2459+void Warehouse::request_cb
2460+ (Game & game,
2461+ Request &,
2462+ WareIndex const ware,
2463+ Worker * const w,
2464+ PlayerImmovable & target)
2465+{
2466+ Warehouse & wh = dynamic_cast<Warehouse&>(target);
2467
2468 if (w) {
2469 w->schedule_incorporate(game);
2470@@ -833,35 +937,38 @@
2471 /**
2472 * Receive a ware from a transfer that was not associated to a \ref Request.
2473 */
2474-void Warehouse::receive_ware(Game& /* game */, WareIndex ware) {
2475+void Warehouse::receive_ware(Game & /* game */, WareIndex ware)
2476+{
2477 m_supply->add_wares(ware, 1);
2478 }
2479
2480 /**
2481 * Receive a worker from a transfer that was not associated to a \ref Request.
2482 */
2483-void Warehouse::receive_worker(Game& game, Worker& worker) {
2484+void Warehouse::receive_worker(Game & game, Worker & worker)
2485+{
2486 worker.schedule_incorporate(game);
2487 }
2488
2489-Building& WarehouseDescr::create_object() const {
2490+Building & WarehouseDescr::create_object() const {
2491 return *new Warehouse(*this);
2492 }
2493
2494-bool Warehouse::can_create_worker(Game&, WareIndex const worker) const {
2495+
2496+bool Warehouse::can_create_worker(Game &, WareIndex const worker) const {
2497 if (!(worker < m_supply->get_workers().get_nrwareids()))
2498- throw wexception("worker type %d does not exists (max is %d)",
2499- worker,
2500- m_supply->get_workers().get_nrwareids());
2501+ throw wexception
2502+ ("worker type %d does not exists (max is %d)",
2503+ worker, m_supply->get_workers().get_nrwareids());
2504
2505- const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(worker);
2506+ const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(worker);
2507 assert(&w_desc);
2508 if (!w_desc.is_buildable())
2509 return false;
2510
2511 // see if we have the resources
2512 for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
2513- const std::string& input_name = buildcost.first;
2514+ const std::string & input_name = buildcost.first;
2515 WareIndex id_w = descr().tribe().ware_index(input_name);
2516 if (id_w != INVALID_INDEX) {
2517 if (m_supply->stock_wares(id_w) < buildcost.second)
2518@@ -870,26 +977,27 @@
2519 if (m_supply->stock_workers(id_w) < buildcost.second)
2520 return false;
2521 } else
2522- throw wexception("worker type %s needs \"%s\" to be built but that is neither "
2523- "a ware type nor a worker type defined in the tribe %s",
2524- w_desc.descname().c_str(),
2525- input_name.c_str(),
2526- descr().tribe().name().c_str());
2527+ throw wexception
2528+ ("worker type %s needs \"%s\" to be built but that is neither "
2529+ "a ware type nor a worker type defined in the tribe %s",
2530+ w_desc.descname().c_str(), input_name.c_str(),
2531+ descr().tribe().name().c_str());
2532 }
2533 return true;
2534 }
2535
2536-void Warehouse::create_worker(Game& game, WareIndex const worker) {
2537- assert(can_create_worker(game, worker));
2538-
2539- const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(worker);
2540+
2541+void Warehouse::create_worker(Game & game, WareIndex const worker) {
2542+ assert(can_create_worker (game, worker));
2543+
2544+ const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(worker);
2545
2546 for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
2547- const std::string& input = buildcost.first;
2548+ const std::string & input = buildcost.first;
2549 WareIndex const id_ware = descr().tribe().ware_index(input);
2550 if (id_ware != INVALID_INDEX) {
2551- remove_wares(id_ware, buildcost.second);
2552- // update statistic accordingly
2553+ remove_wares (id_ware, buildcost.second);
2554+ //update statistic accordingly
2555 owner().ware_consumed(id_ware, buildcost.second);
2556 } else
2557 remove_workers(descr().tribe().safe_worker_index(input), buildcost.second);
2558@@ -911,7 +1019,8 @@
2559 * Return the number of workers of the given type that we plan to
2560 * create in this warehouse.
2561 */
2562-uint32_t Warehouse::get_planned_workers(Game& /* game */, WareIndex index) const {
2563+uint32_t Warehouse::get_planned_workers(Game & /* game */, WareIndex index) const
2564+{
2565 for (const PlannedWorkers& pw : m_planned_workers) {
2566 if (pw.index == index)
2567 return pw.amount;
2568@@ -925,21 +1034,23 @@
2569 *
2570 * This is the current stock plus any incoming transfers.
2571 */
2572-std::vector<uint32_t> Warehouse::calc_available_for_worker(Game& /* game */,
2573- WareIndex index) const {
2574- const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(index);
2575+std::vector<uint32_t> Warehouse::calc_available_for_worker
2576+ (Game & /* game */, WareIndex index) const
2577+{
2578+ const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(index);
2579 std::vector<uint32_t> available;
2580
2581 for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
2582- const std::string& input_name = buildcost.first;
2583+ const std::string & input_name = buildcost.first;
2584 WareIndex id_w = descr().tribe().ware_index(input_name);
2585 if (id_w != INVALID_INDEX) {
2586 available.push_back(get_wares().stock(id_w));
2587 } else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
2588 available.push_back(get_workers().stock(id_w));
2589 } else
2590- throw wexception(
2591- "Economy::_create_requested_worker: buildcost inconsistency '%s'", input_name.c_str());
2592+ throw wexception
2593+ ("Economy::_create_requested_worker: buildcost inconsistency '%s'",
2594+ input_name.c_str());
2595 }
2596
2597 for (const PlannedWorkers& pw : m_planned_workers) {
2598@@ -955,12 +1066,14 @@
2599 return available;
2600 }
2601
2602+
2603 /**
2604 * Set the amount of workers we plan to create
2605 * of the given \p index to \p amount.
2606 */
2607-void Warehouse::plan_workers(Game& game, WareIndex index, uint32_t amount) {
2608- PlannedWorkers* pw = nullptr;
2609+void Warehouse::plan_workers(Game & game, WareIndex index, uint32_t amount)
2610+{
2611+ PlannedWorkers * pw = nullptr;
2612
2613 for (PlannedWorkers& planned_worker : m_planned_workers) {
2614 if (planned_worker.index == index) {
2615@@ -978,17 +1091,22 @@
2616 pw->index = index;
2617 pw->amount = 0;
2618
2619- const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(pw->index);
2620+ const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(pw->index);
2621 for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
2622- const std::string& input_name = buildcost.first;
2623+ const std::string & input_name = buildcost.first;
2624
2625 WareIndex id_w = descr().tribe().ware_index(input_name);
2626 if (id_w != INVALID_INDEX) {
2627- pw->requests.push_back(new Request(*this, id_w, &Warehouse::request_cb, wwWARE));
2628+ pw->requests.push_back
2629+ (new Request
2630+ (*this, id_w, &Warehouse::request_cb, wwWARE));
2631 } else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
2632- pw->requests.push_back(new Request(*this, id_w, &Warehouse::request_cb, wwWORKER));
2633+ pw->requests.push_back
2634+ (new Request
2635+ (*this, id_w, &Warehouse::request_cb, wwWORKER));
2636 } else
2637- throw wexception("plan_workers: bad buildcost '%s'", input_name.c_str());
2638+ throw wexception
2639+ ("plan_workers: bad buildcost '%s'", input_name.c_str());
2640 }
2641 }
2642
2643@@ -1000,8 +1118,10 @@
2644 * See if we can create the workers of the given plan,
2645 * and update requests accordingly.
2646 */
2647-void Warehouse::_update_planned_workers(Game& game, Warehouse::PlannedWorkers& pw) {
2648- const WorkerDescr& w_desc = *descr().tribe().get_worker_descr(pw.index);
2649+void Warehouse::_update_planned_workers
2650+ (Game & game, Warehouse::PlannedWorkers & pw)
2651+{
2652+ const WorkerDescr & w_desc = *descr().tribe().get_worker_descr(pw.index);
2653
2654 while (pw.amount && can_create_worker(game, pw.index)) {
2655 create_worker(game, pw.index);
2656@@ -1010,7 +1130,7 @@
2657 uint32_t idx = 0;
2658 for (const std::pair<std::string, uint8_t>& buildcost : w_desc.buildcost()) {
2659
2660- const std::string& input_name = buildcost.first;
2661+ const std::string & input_name = buildcost.first;
2662 uint32_t supply;
2663
2664 WareIndex id_w = descr().tribe().ware_index(input_name);
2665@@ -1019,12 +1139,14 @@
2666 } else if ((id_w = descr().tribe().worker_index(input_name)) != INVALID_INDEX) {
2667 supply = m_supply->stock_workers(id_w);
2668 } else
2669- throw wexception("_update_planned_workers: bad buildcost '%s'", input_name.c_str());
2670+ throw wexception
2671+ ("_update_planned_workers: bad buildcost '%s'", input_name.c_str());
2672
2673 if (supply >= pw.amount * buildcost.second)
2674 pw.requests[idx]->set_count(0);
2675 else
2676- pw.requests[idx]->set_count(pw.amount * buildcost.second - supply);
2677+ pw.requests[idx]->set_count
2678+ (pw.amount * buildcost.second - supply);
2679 ++idx;
2680 }
2681
2682@@ -1040,7 +1162,8 @@
2683 * Needs to be called periodically, because some necessary supplies might arrive
2684 * due to idle transfers instead of by explicit request.
2685 */
2686-void Warehouse::_update_all_planned_workers(Game& game) {
2687+void Warehouse::_update_all_planned_workers(Game & game)
2688+{
2689 uint32_t idx = 0;
2690 while (idx < m_planned_workers.size()) {
2691 _update_planned_workers(game, m_planned_workers[idx]);
2692@@ -1054,35 +1177,51 @@
2693 }
2694 }
2695
2696-void Warehouse::enable_spawn(Game& game, uint8_t const worker_types_without_cost_index) {
2697- assert(m_next_worker_without_cost_spawn[worker_types_without_cost_index] ==
2698- static_cast<uint32_t>(never()));
2699+void Warehouse::enable_spawn
2700+ (Game & game, uint8_t const worker_types_without_cost_index)
2701+{
2702+ assert
2703+ (m_next_worker_without_cost_spawn[worker_types_without_cost_index]
2704+ ==
2705+ static_cast<uint32_t>(never()));
2706 m_next_worker_without_cost_spawn[worker_types_without_cost_index] =
2707- schedule_act(game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
2708+ schedule_act(game, WORKER_WITHOUT_COST_SPAWN_INTERVAL);
2709 }
2710-void Warehouse::disable_spawn(uint8_t const worker_types_without_cost_index) {
2711- assert(m_next_worker_without_cost_spawn[worker_types_without_cost_index] !=
2712- static_cast<uint32_t>(never()));
2713+void Warehouse::disable_spawn(uint8_t const worker_types_without_cost_index)
2714+{
2715+ assert
2716+ (m_next_worker_without_cost_spawn[worker_types_without_cost_index]
2717+ !=
2718+ static_cast<uint32_t>(never()));
2719 m_next_worker_without_cost_spawn[worker_types_without_cost_index] = never();
2720 }
2721
2722-bool Warehouse::can_attack() {
2723+
2724+bool Warehouse::can_attack()
2725+{
2726 return descr().get_conquers() > 0;
2727 }
2728
2729-void Warehouse::aggressor(Soldier& enemy) {
2730+void Warehouse::aggressor(Soldier & enemy)
2731+{
2732 if (!descr().get_conquers())
2733 return;
2734
2735- Game& game = dynamic_cast<Game&>(owner().egbase());
2736- Map& map = game.map();
2737- if (enemy.get_owner() == &owner() || enemy.get_battle() ||
2738- descr().get_conquers() <= map.calc_distance(enemy.get_position(), get_position()))
2739+ Game & game = dynamic_cast<Game&>(owner().egbase());
2740+ Map & map = game.map();
2741+ if
2742+ (enemy.get_owner() == &owner() ||
2743+ enemy.get_battle() ||
2744+ descr().get_conquers()
2745+ <=
2746+ map.calc_distance(enemy.get_position(), get_position()))
2747 return;
2748
2749- if (game.map().find_bobs(Area<FCoords>(map.get_fcoords(base_flag().get_position()), 2),
2750- nullptr,
2751- FindBobEnemySoldier(&owner())))
2752+ if
2753+ (game.map().find_bobs
2754+ (Area<FCoords>(map.get_fcoords(base_flag().get_position()), 2),
2755+ nullptr,
2756+ FindBobEnemySoldier(&owner())))
2757 return;
2758
2759 WareIndex const soldier_index = descr().tribe().worker_index("soldier");
2760@@ -1091,17 +1230,18 @@
2761 if (!count_workers(game, soldier_index, noreq))
2762 return;
2763
2764- Soldier& defender = dynamic_cast<Soldier&>(launch_worker(game, soldier_index, noreq));
2765+ Soldier & defender = dynamic_cast<Soldier&>(launch_worker(game, soldier_index, noreq));
2766 defender.start_task_defense(game, false);
2767 }
2768
2769-bool Warehouse::attack(Soldier& enemy) {
2770- Game& game = dynamic_cast<Game&>(owner().egbase());
2771+bool Warehouse::attack(Soldier & enemy)
2772+{
2773+ Game & game = dynamic_cast<Game&>(owner().egbase());
2774 WareIndex const soldier_index = descr().tribe().worker_index("soldier");
2775 Requirements noreq;
2776
2777 if (count_workers(game, soldier_index, noreq)) {
2778- Soldier& defender = dynamic_cast<Soldier&>(launch_worker(game, soldier_index, noreq));
2779+ Soldier & defender = dynamic_cast<Soldier&>(launch_worker(game, soldier_index, noreq));
2780 defender.start_task_defense(game, true);
2781 enemy.send_signal(game, "sleep");
2782 return true;
2783@@ -1112,36 +1252,45 @@
2784 return false;
2785 }
2786
2787-void Warehouse::PlannedWorkers::cleanup() {
2788+void Warehouse::PlannedWorkers::cleanup()
2789+{
2790 while (!requests.empty()) {
2791 delete requests.back();
2792 requests.pop_back();
2793 }
2794 }
2795
2796-Warehouse::StockPolicy Warehouse::get_ware_policy(WareIndex ware) const {
2797+Warehouse::StockPolicy Warehouse::get_ware_policy(WareIndex ware) const
2798+{
2799 assert(ware < m_ware_policy.size());
2800 return m_ware_policy[ware];
2801 }
2802
2803-Warehouse::StockPolicy Warehouse::get_worker_policy(WareIndex ware) const {
2804+Warehouse::StockPolicy Warehouse::get_worker_policy(WareIndex ware) const
2805+{
2806 assert(ware < m_worker_policy.size());
2807 return m_worker_policy[ware];
2808 }
2809
2810-Warehouse::StockPolicy Warehouse::get_stock_policy(WareWorker waretype, WareIndex wareindex) const {
2811+Warehouse::StockPolicy Warehouse::get_stock_policy
2812+ (WareWorker waretype, WareIndex wareindex) const
2813+{
2814 if (waretype == wwWORKER)
2815 return get_worker_policy(wareindex);
2816 else
2817 return get_ware_policy(wareindex);
2818 }
2819
2820-void Warehouse::set_ware_policy(WareIndex ware, Warehouse::StockPolicy policy) {
2821+
2822+void Warehouse::set_ware_policy(WareIndex ware, Warehouse::StockPolicy policy)
2823+{
2824 assert(ware < m_ware_policy.size());
2825 m_ware_policy[ware] = policy;
2826 }
2827
2828-void Warehouse::set_worker_policy(WareIndex ware, Warehouse::StockPolicy policy) {
2829+void Warehouse::set_worker_policy
2830+ (WareIndex ware, Warehouse::StockPolicy policy)
2831+{
2832 assert(ware < m_worker_policy.size());
2833 m_worker_policy[ware] = policy;
2834 }
2835@@ -1150,7 +1299,8 @@
2836 * Check if there are remaining wares with stock policy \ref SP_Remove,
2837 * and remove one of them if appropriate.
2838 */
2839-void Warehouse::check_remove_stock(Game& game) {
2840+void Warehouse::check_remove_stock(Game & game)
2841+{
2842 if (base_flag().current_wares() < base_flag().total_capacity() / 2) {
2843 for (WareIndex ware = 0; ware < m_ware_policy.size(); ++ware) {
2844 if (get_ware_policy(ware) != SP_Remove || !get_wares().stock(ware))
2845@@ -1165,7 +1315,7 @@
2846 if (get_worker_policy(widx) != SP_Remove || !get_workers().stock(widx))
2847 continue;
2848
2849- Worker& worker = launch_worker(game, widx, Requirements());
2850+ Worker & worker = launch_worker(game, widx, Requirements());
2851 worker.start_task_leavebuilding(game, true);
2852 break;
2853 }
2854@@ -1181,34 +1331,36 @@
2855 /*
2856 * SoldierControl implementations
2857 */
2858-std::vector<Soldier*> Warehouse::present_soldiers() const {
2859- std::vector<Soldier*> rv;
2860+std::vector<Soldier *> Warehouse::present_soldiers() const
2861+{
2862+ std::vector<Soldier *> rv;
2863
2864 WareIndex const ware = descr().tribe().safe_worker_index("soldier");
2865 IncorporatedWorkers::const_iterator sidx = m_incorporated_workers.find(ware);
2866
2867 if (sidx != m_incorporated_workers.end()) {
2868- const WorkerList& soldiers = sidx->second;
2869+ const WorkerList & soldiers = sidx->second;
2870
2871- for (Worker* temp_soldier : soldiers) {
2872- rv.push_back(static_cast<Soldier*>(temp_soldier));
2873+ for (Worker * temp_soldier: soldiers) {
2874+ rv.push_back(static_cast<Soldier *>(temp_soldier));
2875 }
2876 }
2877
2878 return rv;
2879 }
2880-int Warehouse::incorporate_soldier(EditorGameBase& egbase, Soldier& soldier) {
2881+int Warehouse::incorporate_soldier(EditorGameBase & egbase, Soldier & soldier) {
2882 incorporate_worker(egbase, &soldier);
2883 return 0;
2884 }
2885
2886-int Warehouse::outcorporate_soldier(EditorGameBase& /* egbase */, Soldier& soldier) {
2887+int Warehouse::outcorporate_soldier(EditorGameBase & /* egbase */, Soldier & soldier) {
2888
2889 WareIndex const ware = descr().tribe().safe_worker_index("soldier");
2890 if (m_incorporated_workers.count(ware)) {
2891- WorkerList& soldiers = m_incorporated_workers[ware];
2892+ WorkerList & soldiers = m_incorporated_workers[ware];
2893
2894- WorkerList::iterator i = std::find(soldiers.begin(), soldiers.end(), &soldier);
2895+ WorkerList::iterator i = std::find
2896+ (soldiers.begin(), soldiers.end(), &soldier);
2897
2898 soldiers.erase(i);
2899 m_supply->remove_workers(ware, 1);
2900@@ -1221,10 +1373,13 @@
2901 return 0;
2902 }
2903
2904-void Warehouse::log_general_info(const EditorGameBase& egbase) {
2905+void Warehouse::log_general_info(const EditorGameBase & egbase)
2906+{
2907 Building::log_general_info(egbase);
2908
2909 if (descr().get_isport())
2910 molog("Port dock: %u\n", m_portdock ? m_portdock->serial() : 0);
2911 }
2912+
2913+
2914 }
2915
2916=== modified file 'src/logic/worker.cc'
2917--- src/logic/worker.cc 2014-12-11 12:38:10 +0000
2918+++ src/logic/worker.cc 2014-12-28 17:03:29 +0000
2919@@ -938,12 +938,24 @@
2920 % rdescr->name().c_str()
2921 % _("A geologist found resources.")).str();
2922
2923+ Message::Type message_type = Message::Type::kGeologists;
2924+ if (rdescr->name() == "coal")
2925+ message_type = Message::Type::kGeologistsCoal;
2926+ else if (rdescr->name() == "gold")
2927+ message_type = Message::Type::kGeologistsGold;
2928+ else if (rdescr->name() == "granite")
2929+ message_type = Message::Type::kGeologistsGranite;
2930+ else if (rdescr->name() == "iron")
2931+ message_type = Message::Type::kGeologistsIron;
2932+ else if (rdescr->name() == "water")
2933+ message_type = Message::Type::kGeologistsWater;
2934+
2935 // We should add a message to the player's message queue - but only,
2936 // if there is not already a similar one in list.
2937 owner().add_message_with_timeout
2938 (game,
2939 *new Message
2940- ("geologist " + rdescr->name(), // e.g. "geologist gold"
2941+ (message_type,
2942 game.get_gametime(),
2943 rdescr->descname(),
2944 message,
2945@@ -1843,7 +1855,7 @@
2946 owner().add_message
2947 (game,
2948 *new Message
2949- ("game engine",
2950+ (Message::Type::kGameLogic,
2951 game.get_gametime(),
2952 _("Worker got lost!"),
2953 message,
2954
2955=== modified file 'src/map_io/map_players_messages_packet.cc'
2956--- src/map_io/map_players_messages_packet.cc 2014-10-27 10:14:10 +0000
2957+++ src/map_io/map_players_messages_packet.cc 2014-12-28 17:03:29 +0000
2958@@ -22,6 +22,7 @@
2959 #include <boost/format.hpp>
2960
2961 #include "logic/game_data_error.h"
2962+#include "logic/message.h"
2963 #include "logic/player.h"
2964 #include "map_io/coords_profile.h"
2965 #include "map_io/map_object_loader.h"
2966@@ -64,14 +65,14 @@
2967 "added it to the queue. This is only allowed during "
2968 "simulation, not at load. The following messge will be "
2969 "removed when the queue is reset:\n"
2970- "\tsender : %s\n"
2971+ "\tstype : %u\n"
2972 "\ttitle : %s\n"
2973 "\tsent : %u\n"
2974 "\tposition: (%i, %i)\n"
2975 "\tstatus : %u\n"
2976 "\tbody : %s\n",
2977 p,
2978- begin->second->sender ().c_str(),
2979+ begin->second->type (),
2980 begin->second->title ().c_str(),
2981 begin->second->sent (),
2982 begin->second->position().x, begin->second->position().y,
2983@@ -98,13 +99,13 @@
2984 "gametime is only %u",
2985 sent, gametime);
2986
2987- Message::Status status = Message::Archived; // default status
2988+ Message::Status status = Message::Status::kArchived; // default status
2989 if (char const * const status_string = s->get_string("status")) {
2990 try {
2991 if (!strcmp(status_string, "new"))
2992- status = Message::New;
2993+ status = Message::Status::kNew;
2994 else if (!strcmp(status_string, "read"))
2995- status = Message::Read;
2996+ status = Message::Status::kRead;
2997 else
2998 throw GameDataError
2999 ("expected %s but found \"%s\"",
3000@@ -123,7 +124,7 @@
3001
3002 messages.add_message
3003 (*new Message
3004- (s->get_string ("sender", ""),
3005+ (static_cast<Message::Type>(s->get_natural("type")),
3006 sent,
3007 s->get_name (),
3008 s->get_safe_string("body"),
3009@@ -159,20 +160,19 @@
3010 assert(message.sent() <= static_cast<uint32_t>(egbase.get_gametime()));
3011
3012 Section & s = prof.create_section_duplicate(message.title().c_str());
3013- if (message.sender().size())
3014- s.set_string("sender", message.sender ());
3015- s.set_int ("sent", message.sent ());
3016- s.set_string ("body", message.body ());
3017- if (Coords const c = message.position())
3018+ s.set_int ("type", static_cast<int32_t>(message.type()));
3019+ s.set_int ("sent", message.sent ());
3020+ s.set_string ("body", message.body ());
3021+ if (Coords const c = message.position())
3022 set_coords("position", c, &s);
3023 switch (message.status()) {
3024- case Message::New:
3025+ case Message::Status::kNew:
3026 s.set_string("status", "new");
3027 break;
3028- case Message::Read:
3029+ case Message::Status::kRead:
3030 s.set_string("status", "read");
3031 break;
3032- case Message::Archived: // The default status. Do not write.
3033+ case Message::Status::kArchived: // The default status. Do not write.
3034 break;
3035 default:
3036 assert(false);
3037
3038=== modified file 'src/scripting/lua_game.cc'
3039--- src/scripting/lua_game.cc 2014-11-18 19:30:39 +0000
3040+++ src/scripting/lua_game.cc 2014-12-28 17:03:29 +0000
3041@@ -28,6 +28,7 @@
3042 #include "logic/campaign_visibility.h"
3043 #include "logic/constants.h"
3044 #include "logic/game_controller.h"
3045+#include "logic/message.h"
3046 #include "logic/objective.h"
3047 #include "logic/path.h"
3048 #include "logic/player.h"
3049@@ -202,7 +203,7 @@
3050 lua_newtable(L);
3051 uint32_t cidx = 1;
3052 for (const std::pair<MessageId, Message *>& temp_message : p.messages()) {
3053- if (temp_message.second->status() == Message::Archived)
3054+ if (temp_message.second->status() == Message::Status::kArchived)
3055 continue;
3056
3057 lua_pushuint32(L, cidx ++);
3058@@ -276,9 +277,6 @@
3059 'archived'. Default: "new"
3060 :type status: :class:`string`
3061
3062- :arg sender: sender name of this string. Default: "ScriptingEngine"
3063- :type sender: :class:`string`
3064-
3065 :arg popup: should the message window be opened for this message or not.
3066 Default: :const:`false`
3067 :type popup: :class:`boolean`
3068@@ -291,8 +289,7 @@
3069 std::string title = luaL_checkstring(L, 2);
3070 std::string body = luaL_checkstring(L, 3);
3071 Coords c = Coords::null();
3072- Message::Status st = Message::New;
3073- std::string sender = "ScriptingEngine";
3074+ Message::Status st = Message::Status::kNew;
3075 bool popup = false;
3076
3077 if (n == 4) {
3078@@ -305,18 +302,13 @@
3079 lua_getfield(L, 4, "status");
3080 if (!lua_isnil(L, -1)) {
3081 std::string s = luaL_checkstring(L, -1);
3082- if (s == "new") st = Message::New;
3083- else if (s == "read") st = Message::Read;
3084- else if (s == "archived") st = Message::Archived;
3085+ if (s == "new") st = Message::Status::kNew;
3086+ else if (s == "read") st = Message::Status::kRead;
3087+ else if (s == "archived") st = Message::Status::kArchived;
3088 else report_error(L, "Unknown message status: %s", s.c_str());
3089 }
3090 lua_pop(L, 1);
3091
3092- lua_getfield(L, 4, "sender");
3093- if (!lua_isnil(L, -1))
3094- sender = luaL_checkstring(L, -1);
3095- lua_pop(L, 1);
3096-
3097 lua_getfield(L, 4, "popup");
3098 if (!lua_isnil(L, -1))
3099 popup = luaL_checkboolean(L, -1);
3100@@ -330,7 +322,7 @@
3101 plr.add_message
3102 (game,
3103 *new Message
3104- (sender,
3105+ (Message::Type::kScenario,
3106 game.get_gametime(),
3107 title,
3108 body,
3109@@ -1048,7 +1040,6 @@
3110 {nullptr, nullptr},
3111 };
3112 const PropertyType<LuaMessage> LuaMessage::Properties[] = {
3113- PROP_RO(LuaMessage, sender),
3114 PROP_RO(LuaMessage, title),
3115 PROP_RO(LuaMessage, body),
3116 PROP_RO(LuaMessage, sent),
3117@@ -1078,15 +1069,7 @@
3118 PROPERTIES
3119 ==========================================================
3120 */
3121-/* RST
3122- .. attribute:: sender
3123
3124- (RO) The name of the sender of this message
3125-*/
3126-int LuaMessage::get_sender(lua_State * L) {
3127- lua_pushstring(L, get(L, get_game(L)).sender());
3128- return 1;
3129-}
3130 /* RST
3131 .. attribute:: title
3132
3133@@ -1140,19 +1123,19 @@
3134 */
3135 int LuaMessage::get_status(lua_State * L) {
3136 switch (get(L, get_game(L)).status()) {
3137- case Message::New: lua_pushstring(L, "new"); break;
3138- case Message::Read: lua_pushstring(L, "read"); break;
3139- case Message::Archived: lua_pushstring(L, "archived"); break;
3140+ case Message::Status::kNew: lua_pushstring(L, "new"); break;
3141+ case Message::Status::kRead: lua_pushstring(L, "read"); break;
3142+ case Message::Status::kArchived: lua_pushstring(L, "archived"); break;
3143 default: report_error(L, "Unknown Message status encountered!");
3144 }
3145 return 1;
3146 }
3147 int LuaMessage::set_status(lua_State * L) {
3148- Message::Status status = Message::New;
3149+ Message::Status status = Message::Status::kNew;
3150 std::string s = luaL_checkstring(L, -1);
3151- if (s == "new") status = Message::New;
3152- else if (s == "read") status = Message::Read;
3153- else if (s == "archived") status = Message::Archived;
3154+ if (s == "new") status = Message::Status::kNew;
3155+ else if (s == "read") status = Message::Status::kRead;
3156+ else if (s == "archived") status = Message::Status::kArchived;
3157 else report_error(L, "Invalid message status <%s>!", s.c_str());
3158
3159 get_plr(L, get_game(L)).messages().set_message_status(m_mid, status);
3160
3161=== modified file 'src/scripting/lua_game.h'
3162--- src/scripting/lua_game.h 2014-09-18 18:56:20 +0000
3163+++ src/scripting/lua_game.h 2014-12-28 17:03:29 +0000
3164@@ -161,7 +161,6 @@
3165 /*
3166 * Properties
3167 */
3168- int get_sender(lua_State * L);
3169 int get_sent(lua_State * L);
3170 int get_title(lua_State * L);
3171 int get_body(lua_State * L);
3172
3173=== modified file 'src/wui/game_message_menu.cc'
3174--- src/wui/game_message_menu.cc 2014-11-30 18:49:38 +0000
3175+++ src/wui/game_message_menu.cc 2014-12-28 17:03:29 +0000
3176@@ -20,6 +20,7 @@
3177 #include "wui/game_message_menu.h"
3178
3179 #include <boost/bind.hpp>
3180+#include <boost/format.hpp>
3181
3182 #include "base/time_string.h"
3183 #include "graphic/graphic.h"
3184@@ -45,11 +46,12 @@
3185 (&plr, "messages", &registry, 580, 375, _("Messages: Inbox")),
3186 message_body
3187 (this,
3188- 5, 150, 570, 220,
3189+ 5, 154, 570, 216,
3190 "", UI::Align_Left, 1),
3191 mode(Inbox)
3192 {
3193- list = new UI::Table<uintptr_t>(this, 5, 35, 570, 110);
3194+
3195+ list = new UI::Table<uintptr_t>(this, 5, message_body.get_y() - 110, 570, 110);
3196 list->selected.connect(boost::bind(&GameMessageMenu::selected, this, _1));
3197 list->double_clicked.connect(boost::bind(&GameMessageMenu::double_clicked, this, _1));
3198 list->add_column (60, _("Select"), "", UI::Align_HCenter, true);
3199@@ -58,39 +60,105 @@
3200 list->add_column(120, _("Time sent"));
3201 list->focus();
3202
3203+ // Buttons for message types
3204+ m_geologistsbtn =
3205+ new UI::Button
3206+ (this, "filter_geologists_messages",
3207+ 5, 5, 34, 34,
3208+ g_gr->images().get("pics/but0.png"),
3209+ g_gr->images().get("pics/menu_geologist.png"),
3210+ "",
3211+ true);
3212+ m_geologistsbtn->sigclicked.connect
3213+ (boost::bind(&GameMessageMenu::filter_messages, this, Widelands::Message::Type::kGeologists));
3214+
3215+ m_economybtn =
3216+ new UI::Button
3217+ (this, "filter_economy_messages",
3218+ 2 * 5 + 34, 5, 34, 34,
3219+ g_gr->images().get("pics/but0.png"),
3220+ g_gr->images().get("pics/menu_build_flag.png"),
3221+ "",
3222+ true);
3223+ m_economybtn->sigclicked.connect
3224+ (boost::bind(&GameMessageMenu::filter_messages, this, Widelands::Message::Type::kEconomy));
3225+
3226+ m_seafaringbtn =
3227+ new UI::Button
3228+ (this, "filter_seafaring_messages",
3229+ 3 * 5 + 2 * 34, 5, 34, 34,
3230+ g_gr->images().get("pics/but0.png"),
3231+ g_gr->images().get("pics/start_expedition.png"),
3232+ "",
3233+ true);
3234+ m_seafaringbtn->sigclicked.connect
3235+ (boost::bind(&GameMessageMenu::filter_messages, this, Widelands::Message::Type::kSeafaring));
3236+
3237+ m_warfarebtn =
3238+ new UI::Button
3239+ (this, "filter_warfare_messages",
3240+ 4 * 5 + 3 * 34, 5, 34, 34,
3241+ g_gr->images().get("pics/but0.png"),
3242+ g_gr->images().get("pics/messages_warfare.png"),
3243+ "",
3244+ true);
3245+ m_warfarebtn->sigclicked.connect
3246+ (boost::bind(&GameMessageMenu::filter_messages, this, Widelands::Message::Type::kWarfare));
3247+
3248+ m_scenariobtn =
3249+ new UI::Button
3250+ (this, "filter_scenario_messages",
3251+ 5 * 5 + 4 * 34, 5, 34, 34,
3252+ g_gr->images().get("pics/but0.png"),
3253+ g_gr->images().get("pics/menu_objectives.png"),
3254+ "",
3255+ true);
3256+ m_scenariobtn->sigclicked.connect
3257+ (boost::bind(&GameMessageMenu::filter_messages, this, Widelands::Message::Type::kScenario));
3258+
3259+ m_message_filter = Widelands::Message::Type::kAllMessages;
3260+ set_filter_messages_tooltips();
3261+ // End: Buttons for message types
3262+
3263 UI::Button * clearselectionbtn =
3264 new UI::Button
3265 (this, "clear_selection",
3266- 5, 5, 140, 25,
3267- g_gr->images().get("pics/but0.png"),
3268- _("Clear"), _("Clear selection"));
3269+ 5 * 5 + 6 * 34 + 17, 5, 34, 34,
3270+ g_gr->images().get("pics/but2.png"),
3271+ g_gr->images().get("pics/message_clear_selection.png"),
3272+ _("Clear selection"));
3273 clearselectionbtn->sigclicked.connect
3274 (boost::bind(&GameMessageMenu::do_clear_selection, this));
3275
3276 UI::Button * invertselectionbtn =
3277 new UI::Button
3278 (this, "invert_selection",
3279- 150, 5, 140, 25,
3280- g_gr->images().get("pics/but0.png"),
3281- _("Invert"), _("Invert selection"));
3282+ 6 * 5 + 7 * 34 + 17, 5, 34, 34,
3283+ g_gr->images().get("pics/but2.png"),
3284+ g_gr->images().get("pics/message_selection_invert.png"),
3285+ _("Invert selection"));
3286 invertselectionbtn->sigclicked.connect
3287 (boost::bind(&GameMessageMenu::do_invert_selection, this));
3288
3289 m_archivebtn =
3290 new UI::Button
3291 (this, "archive_or_restore_selected_messages",
3292- 295, 5, 25, 25,
3293+ 6 * 5 + 9 * 34 + 34, 5, 34, 34,
3294 g_gr->images().get("pics/but2.png"),
3295 g_gr->images().get("pics/message_archive.png"),
3296- _("Archive selected messages"));
3297+ /** TRANSLATORS: %s is a tooltip, Del is the corresponding hotkey */
3298+ (boost::format(_("Del: %s"))
3299+ /** TRANSLATORS: Tooltip in the messages window */
3300+ % _("Archive selected messages")).str());
3301 m_archivebtn->sigclicked.connect
3302 (boost::bind(&GameMessageMenu::archive_or_restore, this));
3303
3304 m_togglemodebtn =
3305 new UI::Button
3306 (this, "toggle_between_inbox_or_archive",
3307- 325, 5, 190, 25,
3308+ 7 * 5 + 10 * 34 + 34, 5, 34, 34,
3309 g_gr->images().get("pics/but2.png"),
3310+ g_gr->images().get("pics/message_archived.png"),
3311 _("Show Archive"));
3312 m_togglemodebtn->sigclicked.connect
3313 (boost::bind(&GameMessageMenu::toggle_mode, this));
3314@@ -98,13 +166,24 @@
3315 m_centerviewbtn =
3316 new UI::Button
3317 (this, "center_main_mapview_on_location",
3318- 550, 5, 25, 25,
3319+ 580 - 5 - 34, 5, 34, 34,
3320 g_gr->images().get("pics/but2.png"),
3321 g_gr->images().get("pics/menu_goto.png"),
3322- _("center main mapview on location"),
3323+ /** TRANSLATORS: %s is a tooltip, G is the corresponding hotkey */
3324+ (boost::format(_("G: %s"))
3325+ /** TRANSLATORS: Tooltip in the messages window */
3326+ % _("Center main mapview on location")).str(),
3327 false);
3328 m_centerviewbtn->sigclicked.connect(boost::bind(&GameMessageMenu::center_view, this));
3329
3330+
3331+ m_display_message_type_label =
3332+ new UI::MultilineTextarea
3333+ (this,
3334+ 5, 375 - 5 - 34, 5 * 34, 40,
3335+ "<rt image=pics/message_new.png></rt>",
3336+ UI::Align::Align_BottomLeft, false);
3337+
3338 if (get_usedefaultpos())
3339 center_to_parent();
3340
3341@@ -127,7 +206,7 @@
3342 const Message * msgb = mq[MessageId((*list)[b])];
3343
3344 if (msga && msgb) {
3345- return msga->status() == Message::New && msgb->status() != Message::New;
3346+ return msga->status() == Message::Status::kNew && msgb->status() != Message::Status::kNew;
3347 }
3348 return false; // shouldn't happen
3349 }
3350@@ -144,7 +223,7 @@
3351 assert(iplayer().player().messages()[id] == &message);
3352 assert(!list->find(id.value()));
3353 Message::Status const status = message.status();
3354- if ((mode == Archive) != (status == Message::Archived))
3355+ if ((mode == Archive) != (status == Message::Status::kArchived))
3356 toggle_mode();
3357 UI::Table<uintptr_t>::EntryRecord & te = list->add(id.value(), true);
3358 update_record(te, message);
3359@@ -159,7 +238,7 @@
3360 for (uint32_t j = list->size(); j; --j) {
3361 MessageId m_id((*list)[j - 1]);
3362 if (Message const * const message = mq[m_id]) {
3363- if ((mode == Archive) != (message->status() == Message::Archived)) {
3364+ if ((mode == Archive) != (message->status() == Message::Status::kArchived)) {
3365 list->remove(j - 1);
3366 } else {
3367 update_record(list->get_record(j - 1), *message);
3368@@ -174,7 +253,7 @@
3369 MessageId const id = temp_message.first;
3370 const Message & message = *temp_message.second;
3371 Message::Status const status = message.status();
3372- if ((mode == Archive) != (status == Message::Archived))
3373+ if ((mode == Archive) != (status == Message::Status::kArchived))
3374 continue;
3375 if (!list->find(id.value())) {
3376 UI::Table<uintptr_t>::EntryRecord & er = list->add(id.value());
3377@@ -183,6 +262,19 @@
3378 }
3379 }
3380
3381+ // Filter message type
3382+ if (m_message_filter != Message::Type::kAllMessages) {
3383+ set_display_message_type_label(m_message_filter);
3384+ for (uint32_t j = list->size(); j; --j) {
3385+ MessageId m_id((*list)[j - 1]);
3386+ if (Message const * const message = mq[m_id]) {
3387+ if (message->message_type_category() != m_message_filter) {
3388+ list->remove(j - 1);
3389+ }
3390+ }
3391+ }
3392+ }
3393+
3394 if (list->size()) {
3395 if (!list->has_selection())
3396 list->select(0);
3397@@ -192,6 +284,7 @@
3398 } else {
3399 m_centerviewbtn->set_enabled(false);
3400 message_body.set_text(std::string());
3401+ set_display_message_type_label(Widelands::Message::Type::kNoMessages);
3402 }
3403 }
3404
3405@@ -201,7 +294,7 @@
3406 {
3407 er.set_picture
3408 (ColStatus,
3409- g_gr->images().get(status_picture_filename[message.status()]));
3410+ g_gr->images().get(status_picture_filename[static_cast<int>(message.status())]));
3411 er.set_string(ColTitle, message.title());
3412
3413 const uint32_t time = message.sent();
3414@@ -218,7 +311,7 @@
3415 MessageId const id = MessageId((*list)[t]);
3416 if (Message const * const message = mq[id]) {
3417 // Maybe the message was removed since think?
3418- if (message->status() == Message::New) {
3419+ if (message->status() == Message::Status::kNew) {
3420 Widelands::Game & game = iplayer().game();
3421 game.send_player_command
3422 (*new Widelands::CmdMessageSetStatusRead
3423@@ -226,6 +319,7 @@
3424 }
3425 m_centerviewbtn->set_enabled(message->position());
3426 message_body.set_text(message->body ());
3427+ set_display_message_type_label(message->message_type_category());
3428 return;
3429 }
3430 }
3431@@ -247,19 +341,37 @@
3432 {
3433 if (down) {
3434 switch (code.sym) {
3435+ // Don't forget to change the tooltips if any of these get reassigned
3436 case SDLK_g:
3437 if (m_centerviewbtn->enabled())
3438 center_view();
3439 return true;
3440-
3441+ case SDLK_0:
3442+ filter_messages(Widelands::Message::Type::kAllMessages);
3443+ return true;
3444+ case SDLK_1:
3445+ filter_messages(Widelands::Message::Type::kGeologists);
3446+ return true;
3447+ case SDLK_2:
3448+ filter_messages(Widelands::Message::Type::kEconomy);
3449+ return true;
3450+ case SDLK_3:
3451+ filter_messages(Widelands::Message::Type::kSeafaring);
3452+ return true;
3453+ case SDLK_4:
3454+ filter_messages(Widelands::Message::Type::kWarfare);
3455+ return true;
3456+ case SDLK_5:
3457+ filter_messages(Widelands::Message::Type::kScenario);
3458+ return true;
3459+ case SDLK_DELETE:
3460+ archive_or_restore();
3461+ return true;
3462+ case SDL_SCANCODE_KP_PERIOD:
3463 case SDLK_KP_PERIOD:
3464 if (code.mod & KMOD_NUM)
3465 break;
3466 /* no break */
3467- case SDLK_DELETE:
3468- archive_or_restore();
3469- return true;
3470-
3471 default:
3472 break; // not handled
3473 }
3474@@ -336,6 +448,141 @@
3475 }
3476
3477 /**
3478+ * Show only messages of a certain type
3479+ * @param msgtype the types of messages to show
3480+ */
3481+void GameMessageMenu::filter_messages(Widelands::Message::Type const msgtype) {
3482+ switch (msgtype) {
3483+ case Widelands::Message::Type::kGeologists:
3484+ toggle_filter_messages_button(*m_geologistsbtn, msgtype);
3485+ break;
3486+ case Widelands::Message::Type::kEconomy:
3487+ toggle_filter_messages_button(*m_economybtn, msgtype);
3488+ break;
3489+ case Widelands::Message::Type::kSeafaring:
3490+ toggle_filter_messages_button(*m_seafaringbtn, msgtype);
3491+ break;
3492+ case Widelands::Message::Type::kWarfare:
3493+ toggle_filter_messages_button(*m_warfarebtn, msgtype);
3494+ break;
3495+ case Widelands::Message::Type::kScenario:
3496+ toggle_filter_messages_button(*m_scenariobtn, msgtype);
3497+ break;
3498+ default:
3499+ set_filter_messages_tooltips();
3500+ m_message_filter = Widelands::Message::Type::kAllMessages;
3501+ m_geologistsbtn->set_perm_pressed(false);
3502+ m_economybtn->set_perm_pressed(false);
3503+ m_seafaringbtn->set_perm_pressed(false);
3504+ m_warfarebtn->set_perm_pressed(false);
3505+ m_scenariobtn->set_perm_pressed(false);
3506+ }
3507+ think();
3508+}
3509+
3510+/**
3511+ * Helper for filter_messages
3512+ */
3513+void GameMessageMenu::toggle_filter_messages_button(UI::Button & button, Widelands::Message::Type msgtype) {
3514+ set_filter_messages_tooltips();
3515+ if (button.get_perm_pressed()) {
3516+ button.set_perm_pressed(false);
3517+ m_message_filter = Widelands::Message::Type::kAllMessages;
3518+ } else {
3519+ m_geologistsbtn->set_perm_pressed(false);
3520+ m_economybtn->set_perm_pressed(false);
3521+ m_seafaringbtn->set_perm_pressed(false);
3522+ m_warfarebtn->set_perm_pressed(false);
3523+ m_scenariobtn->set_perm_pressed(false);
3524+ button.set_perm_pressed(true);
3525+ m_message_filter = msgtype;
3526+ /** TRANSLATORS: %1% is a tooltip, %2% is the corresponding hotkey */
3527+ button.set_tooltip((boost::format(_("%1% (Hotkey: %2%)"))
3528+ /** TRANSLATORS: Tooltip in the messages window */
3529+ % _("Show all messages")
3530+ % "0").str());
3531+ }
3532+}
3533+
3534+/**
3535+ * Helper for filter_messages
3536+ */
3537+void GameMessageMenu::set_filter_messages_tooltips() {
3538+ m_geologistsbtn->set_tooltip((boost::format(_("%1% (Hotkey: %2%)"))
3539+ /** TRANSLATORS: Tooltip in the messages window */
3540+ % _("Show geologists' messages only")
3541+ % "1").str());
3542+ m_economybtn->set_tooltip((boost::format(_("%1% (Hotkey: %2%)"))
3543+ /** TRANSLATORS: Tooltip in the messages window */
3544+ % _("Show economy messages only")
3545+ % "2").str());
3546+ m_seafaringbtn->set_tooltip((boost::format(_("%1% (Hotkey: %2%)"))
3547+ /** TRANSLATORS: Tooltip in the messages window */
3548+ % _("Show seafaring messages only")
3549+ % "3").str());
3550+ m_warfarebtn->set_tooltip((boost::format(_("%1% (Hotkey: %2%)"))
3551+ /** TRANSLATORS: Tooltip in the messages window */
3552+ % _("Show warfare messages only")
3553+ % "4").str());
3554+ m_scenariobtn->set_tooltip((boost::format(_("%1% (Hotkey: %2%)"))
3555+ /** TRANSLATORS: Tooltip in the messages window */
3556+ % _("Show scenario messages only")
3557+ % "5").str());
3558+}
3559+
3560+/**
3561+ * Update image and tooltip for message category label
3562+ */
3563+void GameMessageMenu::set_display_message_type_label(Widelands::Message::Type msgtype) {
3564+ std::string message_type_tooltip = "";
3565+ std::string message_type_image = "";
3566+
3567+ switch (msgtype) {
3568+ case Widelands::Message::Type::kGeologists:
3569+ /** TRANSLATORS: This is a message's type */
3570+ message_type_tooltip = _("Geologists");
3571+ message_type_image = "<rt image=pics/menu_geologist.png></rt>";
3572+ break;
3573+ case Widelands::Message::Type::kEconomy:
3574+ /** TRANSLATORS: This is a message's type */
3575+ message_type_tooltip = _("Economy");
3576+ message_type_image = "<rt image=pics/menu_build_flag.png></rt>";
3577+ break;
3578+ case Widelands::Message::Type::kSeafaring:
3579+ /** TRANSLATORS: This is a message's type */
3580+ message_type_tooltip = _("Seafaring");
3581+ message_type_image = "<rt image=pics/start_expedition.png></rt>";
3582+ break;
3583+ case Widelands::Message::Type::kWarfare:
3584+ /** TRANSLATORS: This is a message's type */
3585+ message_type_tooltip = _("Warfare");
3586+ message_type_image = "<rt image=pics/messages_warfare.png></rt>";
3587+ break;
3588+ case Widelands::Message::Type::kScenario:
3589+ /** TRANSLATORS: This is a message's type */
3590+ message_type_tooltip = _("Scenario");
3591+ message_type_image = "<rt image=pics/menu_objectives.png></rt>";
3592+ break;
3593+ case Widelands::Message::Type::kNoMessages:
3594+ /** TRANSLATORS: This show up instead of a message's type when there are no messages found */
3595+ message_type_tooltip = _("No message found");
3596+ break;
3597+ default:
3598+ /** TRANSLATORS: This is the default message type */
3599+ message_type_tooltip = _("General");
3600+ message_type_image = "<rt image=pics/message_new.png></rt>";
3601+ }
3602+
3603+ m_display_message_type_label->set_tooltip(
3604+ /** TRANSLATORS: %s is a message's type */
3605+ (boost::format(_("Type of this message: %s"))
3606+ /** TRANSLATORS: Tooltip in the messages window */
3607+ % message_type_tooltip).str());
3608+ m_display_message_type_label->set_text(message_type_image);
3609+}
3610+
3611+
3612+/**
3613 * Clear the current selection of messages.
3614 */
3615 void GameMessageMenu::do_clear_selection()
3616@@ -359,15 +606,23 @@
3617 mode = Archive;
3618 set_title(_("Messages: Archive"));
3619 m_archivebtn->set_pic(g_gr->images().get("pics/message_restore.png"));
3620- m_archivebtn->set_tooltip(_("Restore selected messages"));
3621- m_togglemodebtn->set_title(_("Show Inbox"));
3622+ /** TRANSLATORS: %s is a tooltip, Del is the corresponding hotkey */
3623+ m_archivebtn->set_tooltip((boost::format(_("Del: %s"))
3624+ /** TRANSLATORS: Tooltip in the messages window */
3625+ % _("Restore selected messages")).str());
3626+ m_togglemodebtn->set_pic(g_gr->images().get("pics/message_new.png"));
3627+ m_togglemodebtn->set_tooltip(_("Show Inbox"));
3628 break;
3629 case Archive:
3630 mode = Inbox;
3631 set_title(_("Messages: Inbox"));
3632 m_archivebtn->set_pic(g_gr->images().get("pics/message_archive.png"));
3633- m_archivebtn->set_tooltip(_("Archive selected messages"));
3634- m_togglemodebtn->set_title(_("Show Archive"));
3635+ /** TRANSLATORS: %s is a tooltip, Del is the corresponding hotkey */
3636+ m_archivebtn->set_tooltip((boost::format(_("Del: %s"))
3637+ /** TRANSLATORS: Tooltip in the messages window */
3638+ % _("Archive selected messages")).str());
3639+ m_togglemodebtn->set_pic(g_gr->images().get("pics/message_archived.png"));
3640+ m_togglemodebtn->set_tooltip(_("Show Archive"));
3641 break;
3642 default:
3643 assert(false); // there is nothing but Archive and Inbox
3644
3645=== modified file 'src/wui/game_message_menu.h'
3646--- src/wui/game_message_menu.h 2014-11-28 16:40:55 +0000
3647+++ src/wui/game_message_menu.h 2014-12-28 17:03:29 +0000
3648@@ -21,6 +21,7 @@
3649 #define WL_WUI_GAME_MESSAGE_MENU_H
3650
3651 #include "base/i18n.h"
3652+#include "logic/message.h"
3653 #include "logic/message_queue.h"
3654 #include "ui_basic/button.h"
3655 #include "ui_basic/multilinetextarea.h"
3656@@ -48,6 +49,7 @@
3657
3658 private:
3659 enum Cols {ColSelect, ColStatus, ColTitle, ColTimeSent};
3660+ enum class ReadUnread: uint8_t {allMessages, readMessages, newMessages};
3661
3662 InteractivePlayer & iplayer() const;
3663 void selected(uint32_t);
3664@@ -59,6 +61,10 @@
3665 void archive_or_restore();
3666 void toggle_mode();
3667 void center_view();
3668+ void filter_messages(Widelands::Message::Type);
3669+ void toggle_filter_messages_button(UI::Button &, Widelands::Message::Type);
3670+ void set_filter_messages_tooltips();
3671+ void set_display_message_type_label(Widelands::Message::Type);
3672 void update_record(UI::Table<uintptr_t>::EntryRecord & er, const Widelands::Message &);
3673
3674 UI::Table<uintptr_t> * list;
3675@@ -67,6 +73,14 @@
3676 UI::Button * m_togglemodebtn;
3677 UI::Button * m_centerviewbtn;
3678 Mode mode;
3679+ // Buttons for message types
3680+ UI::Button * m_geologistsbtn;
3681+ UI::Button * m_economybtn;
3682+ UI::Button * m_seafaringbtn;
3683+ UI::Button * m_warfarebtn;
3684+ UI::Button * m_scenariobtn;
3685+ Widelands::Message::Type m_message_filter;
3686+ UI::MultilineTextarea * m_display_message_type_label;
3687 };
3688
3689 #endif // end of include guard: WL_WUI_GAME_MESSAGE_MENU_H
3690
3691=== modified file 'src/wui/interactive_player.cc'
3692--- src/wui/interactive_player.cc 2014-12-03 08:14:35 +0000
3693+++ src/wui/interactive_player.cc 2014-12-28 17:03:29 +0000
3694@@ -254,7 +254,7 @@
3695 std::string msg_tooltip = _("Messages");
3696 if
3697 (uint32_t const nr_new_messages =
3698- player().messages().nr_messages(Widelands::Message::New))
3699+ player().messages().nr_messages(Widelands::Message::Status::kNew))
3700 {
3701 msg_icon = "pics/menu_toggle_newmessage_menu.png";
3702 msg_tooltip =
3703
3704=== modified file 'test/maps/lua_persistence.wmf/scripting/test_persistence.lua'
3705--- test/maps/lua_persistence.wmf/scripting/test_persistence.lua 2014-08-01 15:30:12 +0000
3706+++ test/maps/lua_persistence.wmf/scripting/test_persistence.lua 2014-12-28 17:03:29 +0000
3707@@ -49,7 +49,7 @@
3708 objective.done = true
3709
3710 p:send_message("dummy msg1", "dummy msg 1")
3711- msg = p:send_message("hello nice", "World", {sender="blah", field = field })
3712+ msg = p:send_message("hello nice", "World", {field = field })
3713 player_slot = map.player_slots[1]
3714
3715 myset = Set:new{
3716@@ -118,7 +118,6 @@
3717 assert_table(msg)
3718 assert_equal("hello nice", msg.title)
3719 assert_equal("World", msg.body)
3720- assert_equal("blah", msg.sender)
3721 assert_equal(field, msg.field)
3722
3723 assert_table(map)
3724
3725=== modified file 'test/maps/lua_testsuite.wmf/scripting/messages.lua'
3726--- test/maps/lua_testsuite.wmf/scripting/messages.lua 2014-09-09 08:24:10 +0000
3727+++ test/maps/lua_testsuite.wmf/scripting/messages.lua 2014-12-28 17:03:29 +0000
3728@@ -13,7 +13,6 @@
3729 local m = player1:send_message("Hallo", "World!")
3730 assert_equal("Hallo", m.title)
3731 assert_equal("World!", m.body)
3732- assert_equal("ScriptingEngine", m.sender)
3733 assert_equal(0, m.sent)
3734 assert_equal(0, m.sent)
3735 assert_equal(nil, m.field)
3736@@ -32,10 +31,6 @@
3737 player1:send_message("Hallo", "World!", {status="nono"})
3738 end)
3739 end
3740-function messages_tests:test_sender()
3741- local m = player1:send_message("Hallo", "World!", {sender="i am you"})
3742- assert_equal("i am you", m.sender)
3743-end
3744 function messages_tests:test_field()
3745 local f = map:get_field(23,28)
3746 local m = player1:send_message("Hallo", "World!", {field = f})
3747
3748=== modified file 'txts/README.lua'
3749--- txts/README.lua 2014-12-11 19:38:39 +0000
3750+++ txts/README.lua 2014-12-28 17:03:29 +0000
3751@@ -79,8 +79,14 @@
3752 ) .. p(_
3753 [[In the message window, the following additional shortcuts are available:]]
3754 ) .. p(
3755-_ "G: jumps to the location corresponding to the current message" .. "<br>"
3756-.. _"DELETE: archives the current message"
3757+_ "0: shows all messages" .. "<br>"
3758+.. _ "1: shows geologists' messages only" .. "<br>"
3759+.. _ "2: shows economy messages only" .. "<br>"
3760+.. _ "3: shows seafaring messages only" .. "<br>"
3761+.. _ "4: shows warfare messages only" .. "<br>"
3762+.. _ "5: shows scenario messages only" .. "<br>"
3763+.. _ "G: jumps to the location corresponding to the current message" .. "<br>"
3764+.. _"DELETE: archives/restores the current message"
3765 ) .. h2(_
3766 [[Online Help]]
3767 ) .. p( _

Subscribers

People subscribed via source and target branches

to status/vote changes: