Merge lp:~widelands-dev/widelands/peaceful into lp:widelands
- peaceful
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 9086 |
Proposed branch: | lp:~widelands-dev/widelands/peaceful |
Merge into: | lp:widelands |
Diff against target: |
793 lines (+289/-16) 28 files modified
data/campaigns/fri02.wmf/scripting/mission_thread.lua (+26/-9) data/scripting/win_conditions/artifacts.lua (+1/-0) data/scripting/win_conditions/collectors.lua (+1/-0) data/scripting/win_conditions/defeat_all.lua (+1/-0) data/scripting/win_conditions/endless_game.lua (+1/-0) data/scripting/win_conditions/endless_game_fogless.lua (+1/-0) data/scripting/win_conditions/territorial_lord.lua (+1/-0) data/scripting/win_conditions/territorial_time.lua (+1/-0) data/scripting/win_conditions/wood_gnome.lua (+1/-0) src/game_io/game_player_info_packet.cc (+16/-2) src/logic/game.cc (+13/-0) src/logic/game_settings.h (+7/-1) src/logic/player.cc (+17/-1) src/logic/player.h (+5/-0) src/logic/single_player_game_settings_provider.cc (+8/-0) src/logic/single_player_game_settings_provider.h (+3/-0) src/network/gameclient.cc (+13/-0) src/network/gameclient.h (+3/-0) src/network/gamehost.cc (+28/-0) src/network/gamehost.h (+1/-0) src/network/network_protocol.h (+9/-1) src/scripting/lua_game.cc (+35/-0) src/scripting/lua_game.h (+2/-0) src/ui_fsmenu/launch_game.cc (+29/-0) src/ui_fsmenu/launch_game.h (+9/-0) src/ui_fsmenu/launch_mpg.cc (+11/-2) src/ui_fsmenu/launch_spg.cc (+8/-0) test/maps/port_space.wmf/scripting/test_attack_forbidden.lua (+38/-0) |
To merge this branch: | bzr merge lp:~widelands-dev/widelands/peaceful |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Widelands Developers | Pending | ||
Review via email: mp+365273@code.launchpad.net |
Commit message
Allow scripts to override the hostility of each player to each other player.
Add an option »Peaceful Mode« to the launch game screen.
Description of the change
bunnybot (widelandsofficial) wrote : | # |
GunChleoc (gunchleoc) wrote : | # |
Code LGTM so far except for a few nits, not tested.
I think we should also add some code to the fieldactions to forbid attacking a building, and the AI will need changing as well.
Benedikt Straub (nordfriese) wrote : | # |
Implemented your comments.
Fieldaction and the AI already work correctly, because they use
if (player_
to see whether the aggressor is hostile to a building´s owner, and is_hostile() is where I put the important logic.
The only change the AI might need is that I´m not sure how it will handle players in a different team whom it is forbidden to attack. But when I tested the 2nd frisian scenario with these changes, it behaved well.
GunChleoc (gunchleoc) wrote : | # |
Tested and working.
I think we should not allow peaceful mode for territorial time, territorial lord or autocrat, because it can make those game modes unwinnable. UI-wise, you could hook into the win condition dropdown's selected signal and show/hide the checkbox.
Benedikt Straub (nordfriese) wrote : | # |
OK, implemented that :)
GunChleoc (gunchleoc) wrote : | # |
Code LGTM, 1 nit. Will do some testing.
GunChleoc (gunchleoc) wrote : | # |
Tested.
1 more thing: Tooltips that have only 1 sentence in them should not have a . at the end.
Benedikt Straub (nordfriese) wrote : | # |
Tooltips changed
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 4815. State: passed. Details: https:/
Appveyor build 4596. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
Excellent :)
@bunnybot merge
Preview Diff
1 | === modified file 'data/campaigns/fri02.wmf/scripting/mission_thread.lua' | |||
2 | --- data/campaigns/fri02.wmf/scripting/mission_thread.lua 2018-09-29 08:43:57 +0000 | |||
3 | +++ data/campaigns/fri02.wmf/scripting/mission_thread.lua 2019-04-26 16:56:58 +0000 | |||
4 | @@ -280,7 +280,8 @@ | |||
5 | 280 | if not p2.defeated then | 280 | if not p2.defeated then |
6 | 281 | campaign_message_box(defeat_murilius_1) | 281 | campaign_message_box(defeat_murilius_1) |
7 | 282 | campaign_message_box(defeat_murilius_2) | 282 | campaign_message_box(defeat_murilius_2) |
9 | 283 | p2.team = 2 | 283 | p1:set_attack_forbidden(2, false) |
10 | 284 | p2:set_attack_forbidden(1, false) | ||
11 | 284 | o = add_campaign_objective(obj_defeat_murilius) | 285 | o = add_campaign_objective(obj_defeat_murilius) |
12 | 285 | local def = false | 286 | local def = false |
13 | 286 | while not def do | 287 | while not def do |
14 | @@ -299,7 +300,8 @@ | |||
15 | 299 | end | 300 | end |
16 | 300 | 301 | ||
17 | 301 | function defeat_murilius() | 302 | function defeat_murilius() |
19 | 302 | p2.team = 2 | 303 | p1:set_attack_forbidden(2, false) |
20 | 304 | p2:set_attack_forbidden(1, false) | ||
21 | 303 | campaign_message_box(defeat_both) | 305 | campaign_message_box(defeat_both) |
22 | 304 | local o = add_campaign_objective(obj_defeat_both) | 306 | local o = add_campaign_objective(obj_defeat_both) |
23 | 305 | while not (p2.defeated and p3.defeated) do sleep(4829) end | 307 | while not (p2.defeated and p3.defeated) do sleep(4829) end |
24 | @@ -333,13 +335,28 @@ | |||
25 | 333 | include "map:scripting/starting_conditions.lua" | 335 | include "map:scripting/starting_conditions.lua" |
26 | 334 | sleep(5000) | 336 | sleep(5000) |
27 | 335 | 337 | ||
35 | 336 | p1.team = 1 | 338 | p1:set_attack_forbidden(2, true) |
36 | 337 | p2.team = 1 | 339 | p2:set_attack_forbidden(1, true) |
37 | 338 | p3.team = 2 | 340 | p2:set_attack_forbidden(3, true) |
38 | 339 | -- TODO: instead of alliances, just forbid certain players to attack each other: | 341 | run(function() |
39 | 340 | -- · Beginning: forbid 1>2, 2>1, 2>3 | 342 | repeat |
40 | 341 | -- · Refusing alliance: forbid only 2>3 | 343 | local conquered = (#p3:get_buildings("empire_sentry") + |
41 | 342 | -- · Accepting alliance: first unchanged, after p3 defeated: allow all | 344 | #p3:get_buildings("empire_blockhouse") + |
42 | 345 | #p3:get_buildings("empire_outpost") + | ||
43 | 346 | #p3:get_buildings("empire_barrier") + | ||
44 | 347 | #p3:get_buildings("empire_tower") + | ||
45 | 348 | #p3:get_buildings("empire_fortress") + | ||
46 | 349 | #p3:get_buildings("empire_castle") - | ||
47 | 350 | #p2:get_buildings("barbarians_sentry") - | ||
48 | 351 | #p2:get_buildings("barbarians_barrier") - | ||
49 | 352 | #p2:get_buildings("barbarians_tower") - | ||
50 | 353 | #p2:get_buildings("barbarians_fortress") - | ||
51 | 354 | #p2:get_buildings("barbarians_citadel")) | ||
52 | 355 | p2:set_attack_forbidden(3, conquered <= 0) | ||
53 | 356 | sleep(6913) | ||
54 | 357 | until p3.defeated or p2.defeated | ||
55 | 358 | p2:set_attack_forbidden(3, false) | ||
56 | 359 | end) | ||
57 | 343 | 360 | ||
58 | 344 | campaign_message_box(intro_3) | 361 | campaign_message_box(intro_3) |
59 | 345 | local o = add_campaign_objective(obj_new_home) | 362 | local o = add_campaign_objective(obj_new_home) |
60 | 346 | 363 | ||
61 | === modified file 'data/scripting/win_conditions/artifacts.lua' | |||
62 | --- data/scripting/win_conditions/artifacts.lua 2019-04-25 12:07:53 +0000 | |||
63 | +++ data/scripting/win_conditions/artifacts.lua 2019-04-26 16:56:58 +0000 | |||
64 | @@ -23,6 +23,7 @@ | |||
65 | 23 | return { | 23 | return { |
66 | 24 | name = wc_name, | 24 | name = wc_name, |
67 | 25 | description = wc_desc, | 25 | description = wc_desc, |
68 | 26 | peaceful_mode_allowed = true, | ||
69 | 26 | map_tags = { "artifacts" }, -- Map tags needed so that this win condition will be available only for suitable maps | 27 | map_tags = { "artifacts" }, -- Map tags needed so that this win condition will be available only for suitable maps |
70 | 27 | init = function() | 28 | init = function() |
71 | 28 | -- Find all artifacts | 29 | -- Find all artifacts |
72 | 29 | 30 | ||
73 | === modified file 'data/scripting/win_conditions/collectors.lua' | |||
74 | --- data/scripting/win_conditions/collectors.lua 2019-02-13 16:29:08 +0000 | |||
75 | +++ data/scripting/win_conditions/collectors.lua 2019-04-26 16:56:58 +0000 | |||
76 | @@ -24,6 +24,7 @@ | |||
77 | 24 | return { | 24 | return { |
78 | 25 | name = wc_name, | 25 | name = wc_name, |
79 | 26 | description = wc_desc, | 26 | description = wc_desc, |
80 | 27 | peaceful_mode_allowed = true, | ||
81 | 27 | func = function() | 28 | func = function() |
82 | 28 | 29 | ||
83 | 29 | -- set the objective with the game type for all players | 30 | -- set the objective with the game type for all players |
84 | 30 | 31 | ||
85 | === modified file 'data/scripting/win_conditions/defeat_all.lua' | |||
86 | --- data/scripting/win_conditions/defeat_all.lua 2016-03-15 08:42:41 +0000 | |||
87 | +++ data/scripting/win_conditions/defeat_all.lua 2019-04-26 16:56:58 +0000 | |||
88 | @@ -18,6 +18,7 @@ | |||
89 | 18 | return { | 18 | return { |
90 | 19 | name = wc_name, | 19 | name = wc_name, |
91 | 20 | description = wc_desc, | 20 | description = wc_desc, |
92 | 21 | peaceful_mode_allowed = false, | ||
93 | 21 | func = function() | 22 | func = function() |
94 | 22 | local plrs = wl.Game().players | 23 | local plrs = wl.Game().players |
95 | 23 | 24 | ||
96 | 24 | 25 | ||
97 | === modified file 'data/scripting/win_conditions/endless_game.lua' | |||
98 | --- data/scripting/win_conditions/endless_game.lua 2016-03-15 08:42:41 +0000 | |||
99 | +++ data/scripting/win_conditions/endless_game.lua 2019-04-26 16:56:58 +0000 | |||
100 | @@ -18,6 +18,7 @@ | |||
101 | 18 | return { | 18 | return { |
102 | 19 | name = wc_name, | 19 | name = wc_name, |
103 | 20 | description = wc_desc, | 20 | description = wc_desc, |
104 | 21 | peaceful_mode_allowed = true, | ||
105 | 21 | func = function() | 22 | func = function() |
106 | 22 | local plrs = wl.Game().players | 23 | local plrs = wl.Game().players |
107 | 23 | 24 | ||
108 | 24 | 25 | ||
109 | === modified file 'data/scripting/win_conditions/endless_game_fogless.lua' | |||
110 | --- data/scripting/win_conditions/endless_game_fogless.lua 2016-03-15 08:42:41 +0000 | |||
111 | +++ data/scripting/win_conditions/endless_game_fogless.lua 2019-04-26 16:56:58 +0000 | |||
112 | @@ -18,6 +18,7 @@ | |||
113 | 18 | return { | 18 | return { |
114 | 19 | name = wc_name, | 19 | name = wc_name, |
115 | 20 | description = wc_desc, | 20 | description = wc_desc, |
116 | 21 | peaceful_mode_allowed = true, | ||
117 | 21 | func = function() | 22 | func = function() |
118 | 22 | local plrs = wl.Game().players | 23 | local plrs = wl.Game().players |
119 | 23 | 24 | ||
120 | 24 | 25 | ||
121 | === modified file 'data/scripting/win_conditions/territorial_lord.lua' | |||
122 | --- data/scripting/win_conditions/territorial_lord.lua 2019-04-25 06:13:15 +0000 | |||
123 | +++ data/scripting/win_conditions/territorial_lord.lua 2019-04-26 16:56:58 +0000 | |||
124 | @@ -26,6 +26,7 @@ | |||
125 | 26 | return { | 26 | return { |
126 | 27 | name = wc_name, | 27 | name = wc_name, |
127 | 28 | description = wc_desc, | 28 | description = wc_desc, |
128 | 29 | peaceful_mode_allowed = false, | ||
129 | 29 | init = function() | 30 | init = function() |
130 | 30 | fields = wl.Game().map:count_conquerable_fields() | 31 | fields = wl.Game().map:count_conquerable_fields() |
131 | 31 | end, | 32 | end, |
132 | 32 | 33 | ||
133 | === modified file 'data/scripting/win_conditions/territorial_time.lua' | |||
134 | --- data/scripting/win_conditions/territorial_time.lua 2019-04-25 06:13:15 +0000 | |||
135 | +++ data/scripting/win_conditions/territorial_time.lua 2019-04-26 16:56:58 +0000 | |||
136 | @@ -30,6 +30,7 @@ | |||
137 | 30 | return { | 30 | return { |
138 | 31 | name = wc_name, | 31 | name = wc_name, |
139 | 32 | description = wc_desc, | 32 | description = wc_desc, |
140 | 33 | peaceful_mode_allowed = false, | ||
141 | 33 | init = function() | 34 | init = function() |
142 | 34 | fields = wl.Game().map:count_conquerable_fields() | 35 | fields = wl.Game().map:count_conquerable_fields() |
143 | 35 | end, | 36 | end, |
144 | 36 | 37 | ||
145 | === modified file 'data/scripting/win_conditions/wood_gnome.lua' | |||
146 | --- data/scripting/win_conditions/wood_gnome.lua 2019-03-09 10:55:24 +0000 | |||
147 | +++ data/scripting/win_conditions/wood_gnome.lua 2019-04-26 16:56:58 +0000 | |||
148 | @@ -24,6 +24,7 @@ | |||
149 | 24 | return { | 24 | return { |
150 | 25 | name = wc_name, | 25 | name = wc_name, |
151 | 26 | description = wc_desc, | 26 | description = wc_desc, |
152 | 27 | peaceful_mode_allowed = true, | ||
153 | 27 | init = function() | 28 | init = function() |
154 | 28 | -- Calculate valuable fields | 29 | -- Calculate valuable fields |
155 | 29 | wl.Game().map:count_terrestrial_fields() | 30 | wl.Game().map:count_terrestrial_fields() |
156 | 30 | 31 | ||
157 | === modified file 'src/game_io/game_player_info_packet.cc' | |||
158 | --- src/game_io/game_player_info_packet.cc 2019-02-23 11:00:49 +0000 | |||
159 | +++ src/game_io/game_player_info_packet.cc 2019-04-26 16:56:58 +0000 | |||
160 | @@ -30,14 +30,14 @@ | |||
161 | 30 | 30 | ||
162 | 31 | namespace Widelands { | 31 | namespace Widelands { |
163 | 32 | 32 | ||
165 | 33 | constexpr uint16_t kCurrentPacketVersion = 22; | 33 | constexpr uint16_t kCurrentPacketVersion = 23; |
166 | 34 | 34 | ||
167 | 35 | void GamePlayerInfoPacket::read(FileSystem& fs, Game& game, MapObjectLoader*) { | 35 | void GamePlayerInfoPacket::read(FileSystem& fs, Game& game, MapObjectLoader*) { |
168 | 36 | try { | 36 | try { |
169 | 37 | FileRead fr; | 37 | FileRead fr; |
170 | 38 | fr.open(fs, "binary/player_info"); | 38 | fr.open(fs, "binary/player_info"); |
171 | 39 | uint16_t const packet_version = fr.unsigned_16(); | 39 | uint16_t const packet_version = fr.unsigned_16(); |
173 | 40 | if (packet_version == kCurrentPacketVersion) { | 40 | if (packet_version <= kCurrentPacketVersion && packet_version >= 22) { |
174 | 41 | uint32_t const max_players = fr.unsigned_16(); | 41 | uint32_t const max_players = fr.unsigned_16(); |
175 | 42 | for (uint32_t i = 1; i < max_players + 1; ++i) { | 42 | for (uint32_t i = 1; i < max_players + 1; ++i) { |
176 | 43 | game.remove_player(i); | 43 | game.remove_player(i); |
177 | @@ -59,6 +59,15 @@ | |||
178 | 59 | player->set_see_all(see_all); | 59 | player->set_see_all(see_all); |
179 | 60 | 60 | ||
180 | 61 | player->set_ai(fr.c_string()); | 61 | player->set_ai(fr.c_string()); |
181 | 62 | |||
182 | 63 | if (packet_version == kCurrentPacketVersion) { | ||
183 | 64 | player->forbid_attack_.clear(); | ||
184 | 65 | uint8_t size = fr.unsigned_8(); | ||
185 | 66 | for (uint8_t j = 0; j < size; ++j) { | ||
186 | 67 | player->forbid_attack_.emplace(fr.unsigned_8()); | ||
187 | 68 | } | ||
188 | 69 | } | ||
189 | 70 | |||
190 | 62 | player->read_statistics(fr, packet_version); | 71 | player->read_statistics(fr, packet_version); |
191 | 63 | player->read_remaining_shipnames(fr); | 72 | player->read_remaining_shipnames(fr); |
192 | 64 | 73 | ||
193 | @@ -118,6 +127,11 @@ | |||
194 | 118 | fw.c_string(plr->name_.c_str()); | 127 | fw.c_string(plr->name_.c_str()); |
195 | 119 | fw.c_string(plr->ai_.c_str()); | 128 | fw.c_string(plr->ai_.c_str()); |
196 | 120 | 129 | ||
197 | 130 | fw.unsigned_8(plr->forbid_attack_.size()); | ||
198 | 131 | for (const auto& it : plr->forbid_attack_) { | ||
199 | 132 | fw.unsigned_8(it); | ||
200 | 133 | } | ||
201 | 134 | |||
202 | 121 | plr->write_statistics(fw); | 135 | plr->write_statistics(fw); |
203 | 122 | plr->write_remaining_shipnames(fw); | 136 | plr->write_remaining_shipnames(fw); |
204 | 123 | fw.unsigned_32(plr->casualties()); | 137 | fw.unsigned_32(plr->casualties()); |
205 | 124 | 138 | ||
206 | === modified file 'src/logic/game.cc' | |||
207 | --- src/logic/game.cc 2019-04-08 06:45:49 +0000 | |||
208 | +++ src/logic/game.cc 2019-04-26 16:56:58 +0000 | |||
209 | @@ -323,6 +323,19 @@ | |||
210 | 323 | // Check for win_conditions | 323 | // Check for win_conditions |
211 | 324 | if (!settings.scenario) { | 324 | if (!settings.scenario) { |
212 | 325 | loader_ui->step(_("Initializing game…")); | 325 | loader_ui->step(_("Initializing game…")); |
213 | 326 | if (settings.peaceful) { | ||
214 | 327 | for (uint32_t i = 1; i < settings.players.size(); ++i) { | ||
215 | 328 | if (Player* p1 = get_player(i)) { | ||
216 | 329 | for (uint32_t j = i + 1; j <= settings.players.size(); ++j) { | ||
217 | 330 | if (Player* p2 = get_player(j)) { | ||
218 | 331 | p1->set_attack_forbidden(j, true); | ||
219 | 332 | p2->set_attack_forbidden(i, true); | ||
220 | 333 | } | ||
221 | 334 | } | ||
222 | 335 | } | ||
223 | 336 | } | ||
224 | 337 | } | ||
225 | 338 | |||
226 | 326 | std::unique_ptr<LuaTable> table(lua().run_script(settings.win_condition_script)); | 339 | std::unique_ptr<LuaTable> table(lua().run_script(settings.win_condition_script)); |
227 | 327 | table->do_not_warn_about_unaccessed_keys(); | 340 | table->do_not_warn_about_unaccessed_keys(); |
228 | 328 | win_condition_displayname_ = table->get_string("name"); | 341 | win_condition_displayname_ = table->get_string("name"); |
229 | 329 | 342 | ||
230 | === modified file 'src/logic/game_settings.h' | |||
231 | --- src/logic/game_settings.h 2019-02-23 11:00:49 +0000 | |||
232 | +++ src/logic/game_settings.h 2019-04-26 16:56:58 +0000 | |||
233 | @@ -111,7 +111,7 @@ | |||
234 | 111 | * Think of it as the Model in MVC. | 111 | * Think of it as the Model in MVC. |
235 | 112 | */ | 112 | */ |
236 | 113 | struct GameSettings { | 113 | struct GameSettings { |
238 | 114 | GameSettings() : playernum(0), usernum(0), scenario(false), multiplayer(false), savegame(false) { | 114 | GameSettings() : playernum(0), usernum(0), scenario(false), multiplayer(false), savegame(false), peaceful(false) { |
239 | 115 | std::unique_ptr<LuaInterface> lua(new LuaInterface); | 115 | std::unique_ptr<LuaInterface> lua(new LuaInterface); |
240 | 116 | std::unique_ptr<LuaTable> win_conditions( | 116 | std::unique_ptr<LuaTable> win_conditions( |
241 | 117 | lua->run_script("scripting/win_conditions/init.lua")); | 117 | lua->run_script("scripting/win_conditions/init.lua")); |
242 | @@ -156,6 +156,9 @@ | |||
243 | 156 | /// Is a savegame selected for loading? | 156 | /// Is a savegame selected for loading? |
244 | 157 | bool savegame; | 157 | bool savegame; |
245 | 158 | 158 | ||
246 | 159 | // Is all fighting forbidden? | ||
247 | 160 | bool peaceful; | ||
248 | 161 | |||
249 | 159 | /// List of tribes that players are allowed to choose | 162 | /// List of tribes that players are allowed to choose |
250 | 160 | std::vector<Widelands::TribeBasicInfo> tribes; | 163 | std::vector<Widelands::TribeBasicInfo> tribes; |
251 | 161 | 164 | ||
252 | @@ -210,6 +213,9 @@ | |||
253 | 210 | virtual void set_win_condition_script(const std::string& wc) = 0; | 213 | virtual void set_win_condition_script(const std::string& wc) = 0; |
254 | 211 | virtual std::string get_win_condition_script() = 0; | 214 | virtual std::string get_win_condition_script() = 0; |
255 | 212 | 215 | ||
256 | 216 | virtual void set_peaceful_mode(bool peace) = 0; | ||
257 | 217 | virtual bool is_peaceful_mode() = 0; | ||
258 | 218 | |||
259 | 213 | // For retrieving tips texts | 219 | // For retrieving tips texts |
260 | 214 | struct NoTribe {}; | 220 | struct NoTribe {}; |
261 | 215 | const std::string& get_players_tribe() { | 221 | const std::string& get_players_tribe() { |
262 | 216 | 222 | ||
263 | === modified file 'src/logic/player.cc' | |||
264 | --- src/logic/player.cc 2019-04-24 06:01:37 +0000 | |||
265 | +++ src/logic/player.cc 2019-04-26 16:56:58 +0000 | |||
266 | @@ -254,7 +254,8 @@ | |||
267 | 254 | * each other. | 254 | * each other. |
268 | 255 | */ | 255 | */ |
269 | 256 | bool Player::is_hostile(const Player& other) const { | 256 | bool Player::is_hostile(const Player& other) const { |
271 | 257 | return &other != this && (!team_number_ || team_number_ != other.team_number_); | 257 | return &other != this && (!team_number_ || team_number_ != other.team_number_) && |
272 | 258 | !is_attack_forbidden(other.player_number()); | ||
273 | 258 | } | 259 | } |
274 | 259 | 260 | ||
275 | 260 | bool Player::is_defeated() const { | 261 | bool Player::is_defeated() const { |
276 | @@ -1334,6 +1335,21 @@ | |||
277 | 1334 | return ai_; | 1335 | return ai_; |
278 | 1335 | } | 1336 | } |
279 | 1336 | 1337 | ||
280 | 1338 | bool Player::is_attack_forbidden(PlayerNumber who) const { | ||
281 | 1339 | return forbid_attack_.find(who) != forbid_attack_.end(); | ||
282 | 1340 | } | ||
283 | 1341 | |||
284 | 1342 | void Player::set_attack_forbidden(PlayerNumber who, bool forbid) { | ||
285 | 1343 | const auto it = forbid_attack_.find(who); | ||
286 | 1344 | if (forbid ^ (it == forbid_attack_.end())) { | ||
287 | 1345 | return; | ||
288 | 1346 | } else if (forbid) { | ||
289 | 1347 | forbid_attack_.emplace(who); | ||
290 | 1348 | } else { | ||
291 | 1349 | forbid_attack_.erase(it); | ||
292 | 1350 | } | ||
293 | 1351 | } | ||
294 | 1352 | |||
295 | 1337 | /** | 1353 | /** |
296 | 1338 | * Pick random name from remaining names (if any) | 1354 | * Pick random name from remaining names (if any) |
297 | 1339 | */ | 1355 | */ |
298 | 1340 | 1356 | ||
299 | === modified file 'src/logic/player.h' | |||
300 | --- src/logic/player.h 2019-03-17 11:44:04 +0000 | |||
301 | +++ src/logic/player.h 2019-04-26 16:56:58 +0000 | |||
302 | @@ -604,6 +604,9 @@ | |||
303 | 604 | further_initializations_.push_back(init); | 604 | further_initializations_.push_back(init); |
304 | 605 | } | 605 | } |
305 | 606 | 606 | ||
306 | 607 | void set_attack_forbidden(PlayerNumber who, bool forbid); | ||
307 | 608 | bool is_attack_forbidden(PlayerNumber who) const; | ||
308 | 609 | |||
309 | 607 | const std::string pick_shipname(); | 610 | const std::string pick_shipname(); |
310 | 608 | 611 | ||
311 | 609 | private: | 612 | private: |
312 | @@ -681,6 +684,8 @@ | |||
313 | 681 | */ | 684 | */ |
314 | 682 | std::vector<std::vector<uint32_t>> ware_stocks_; | 685 | std::vector<std::vector<uint32_t>> ware_stocks_; |
315 | 683 | 686 | ||
316 | 687 | std::set<PlayerNumber> forbid_attack_; | ||
317 | 688 | |||
318 | 684 | PlayerBuildingStats building_stats_; | 689 | PlayerBuildingStats building_stats_; |
319 | 685 | 690 | ||
320 | 686 | FxId message_fx_; | 691 | FxId message_fx_; |
321 | 687 | 692 | ||
322 | === modified file 'src/logic/single_player_game_settings_provider.cc' | |||
323 | --- src/logic/single_player_game_settings_provider.cc 2019-02-23 11:00:49 +0000 | |||
324 | +++ src/logic/single_player_game_settings_provider.cc 2019-04-26 16:56:58 +0000 | |||
325 | @@ -69,6 +69,14 @@ | |||
326 | 69 | return s.mapfilename; | 69 | return s.mapfilename; |
327 | 70 | } | 70 | } |
328 | 71 | 71 | ||
329 | 72 | bool SinglePlayerGameSettingsProvider::is_peaceful_mode() { | ||
330 | 73 | return s.peaceful; | ||
331 | 74 | } | ||
332 | 75 | |||
333 | 76 | void SinglePlayerGameSettingsProvider::set_peaceful_mode(bool peace) { | ||
334 | 77 | s.peaceful = peace; | ||
335 | 78 | } | ||
336 | 79 | |||
337 | 72 | void SinglePlayerGameSettingsProvider::set_map(const std::string& mapname, | 80 | void SinglePlayerGameSettingsProvider::set_map(const std::string& mapname, |
338 | 73 | const std::string& mapfilename, | 81 | const std::string& mapfilename, |
339 | 74 | uint32_t const maxplayers, | 82 | uint32_t const maxplayers, |
340 | 75 | 83 | ||
341 | === modified file 'src/logic/single_player_game_settings_provider.h' | |||
342 | --- src/logic/single_player_game_settings_provider.h 2019-02-23 11:00:49 +0000 | |||
343 | +++ src/logic/single_player_game_settings_provider.h 2019-04-26 16:56:58 +0000 | |||
344 | @@ -62,6 +62,9 @@ | |||
345 | 62 | std::string get_win_condition_script() override; | 62 | std::string get_win_condition_script() override; |
346 | 63 | void set_win_condition_script(const std::string& wc) override; | 63 | void set_win_condition_script(const std::string& wc) override; |
347 | 64 | 64 | ||
348 | 65 | void set_peaceful_mode(bool peace) override; | ||
349 | 66 | bool is_peaceful_mode() override; | ||
350 | 67 | |||
351 | 65 | private: | 68 | private: |
352 | 66 | GameSettings s; | 69 | GameSettings s; |
353 | 67 | }; | 70 | }; |
354 | 68 | 71 | ||
355 | === modified file 'src/network/gameclient.cc' | |||
356 | --- src/network/gameclient.cc 2019-02-23 11:00:49 +0000 | |||
357 | +++ src/network/gameclient.cc 2019-04-26 16:56:58 +0000 | |||
358 | @@ -405,6 +405,15 @@ | |||
359 | 405 | // set_player_number(uint8_t) to the host. | 405 | // set_player_number(uint8_t) to the host. |
360 | 406 | } | 406 | } |
361 | 407 | 407 | ||
362 | 408 | |||
363 | 409 | void GameClient::set_peaceful_mode(bool peace) { | ||
364 | 410 | d->settings.peaceful = peace; | ||
365 | 411 | } | ||
366 | 412 | |||
367 | 413 | bool GameClient::is_peaceful_mode() { | ||
368 | 414 | return d->settings.peaceful; | ||
369 | 415 | } | ||
370 | 416 | |||
371 | 408 | std::string GameClient::get_win_condition_script() { | 417 | std::string GameClient::get_win_condition_script() { |
372 | 409 | return d->settings.win_condition_script; | 418 | return d->settings.win_condition_script; |
373 | 410 | } | 419 | } |
374 | @@ -819,6 +828,10 @@ | |||
375 | 819 | d->settings.win_condition_script = g_fs->FileSystem::fix_cross_file(packet.string()); | 828 | d->settings.win_condition_script = g_fs->FileSystem::fix_cross_file(packet.string()); |
376 | 820 | break; | 829 | break; |
377 | 821 | } | 830 | } |
378 | 831 | case NETCMD_PEACEFUL_MODE: { | ||
379 | 832 | d->settings.peaceful = packet.unsigned_8(); | ||
380 | 833 | break; | ||
381 | 834 | } | ||
382 | 822 | 835 | ||
383 | 823 | case NETCMD_LAUNCH: { | 836 | case NETCMD_LAUNCH: { |
384 | 824 | if (!d->modal || d->game) { | 837 | if (!d->modal || d->game) { |
385 | 825 | 838 | ||
386 | === modified file 'src/network/gameclient.h' | |||
387 | --- src/network/gameclient.h 2019-02-23 11:00:49 +0000 | |||
388 | +++ src/network/gameclient.h 2019-04-26 16:56:58 +0000 | |||
389 | @@ -95,6 +95,9 @@ | |||
390 | 95 | void set_win_condition_script(const std::string&) override; | 95 | void set_win_condition_script(const std::string&) override; |
391 | 96 | std::string get_win_condition_script() override; | 96 | std::string get_win_condition_script() override; |
392 | 97 | 97 | ||
393 | 98 | void set_peaceful_mode(bool peace) override; | ||
394 | 99 | bool is_peaceful_mode() override; | ||
395 | 100 | |||
396 | 98 | // ChatProvider interface | 101 | // ChatProvider interface |
397 | 99 | void send(const std::string& msg) override; | 102 | void send(const std::string& msg) override; |
398 | 100 | const std::vector<ChatMessage>& get_messages() const override; | 103 | const std::vector<ChatMessage>& get_messages() const override; |
399 | 101 | 104 | ||
400 | === modified file 'src/network/gamehost.cc' | |||
401 | --- src/network/gamehost.cc 2019-02-23 11:00:49 +0000 | |||
402 | +++ src/network/gamehost.cc 2019-04-26 16:56:58 +0000 | |||
403 | @@ -203,6 +203,13 @@ | |||
404 | 203 | host_->set_win_condition_script(wc); | 203 | host_->set_win_condition_script(wc); |
405 | 204 | } | 204 | } |
406 | 205 | 205 | ||
407 | 206 | void set_peaceful_mode(bool peace) override { | ||
408 | 207 | host_->set_peaceful_mode(peace); | ||
409 | 208 | } | ||
410 | 209 | bool is_peaceful_mode() override { | ||
411 | 210 | return host_->settings().peaceful; | ||
412 | 211 | } | ||
413 | 212 | |||
414 | 206 | private: | 213 | private: |
415 | 207 | GameHost* host_; | 214 | GameHost* host_; |
416 | 208 | std::vector<std::string> wincondition_scripts_; | 215 | std::vector<std::string> wincondition_scripts_; |
417 | @@ -1368,6 +1375,16 @@ | |||
418 | 1368 | broadcast(packet); | 1375 | broadcast(packet); |
419 | 1369 | } | 1376 | } |
420 | 1370 | 1377 | ||
421 | 1378 | void GameHost::set_peaceful_mode(bool peace) { | ||
422 | 1379 | d->settings.peaceful = peace; | ||
423 | 1380 | |||
424 | 1381 | // Broadcast changes | ||
425 | 1382 | SendPacket packet; | ||
426 | 1383 | packet.unsigned_8(NETCMD_PEACEFUL_MODE); | ||
427 | 1384 | packet.unsigned_8(peace ? 1 : 0); | ||
428 | 1385 | broadcast(packet); | ||
429 | 1386 | } | ||
430 | 1387 | |||
431 | 1371 | void GameHost::switch_to_player(uint32_t user, uint8_t number) { | 1388 | void GameHost::switch_to_player(uint32_t user, uint8_t number) { |
432 | 1372 | if (number < d->settings.players.size() && | 1389 | if (number < d->settings.players.size() && |
433 | 1373 | (d->settings.players.at(number).state != PlayerSettings::State::kOpen && | 1390 | (d->settings.players.at(number).state != PlayerSettings::State::kOpen && |
434 | @@ -1676,6 +1693,11 @@ | |||
435 | 1676 | packet.string(d->settings.win_condition_script); | 1693 | packet.string(d->settings.win_condition_script); |
436 | 1677 | d->net->send(client.sock_id, packet); | 1694 | d->net->send(client.sock_id, packet); |
437 | 1678 | 1695 | ||
438 | 1696 | packet.reset(); | ||
439 | 1697 | packet.unsigned_8(NETCMD_PEACEFUL_MODE); | ||
440 | 1698 | packet.unsigned_8(d->settings.peaceful ? 1 : 0); | ||
441 | 1699 | d->net->send(client.sock_id, packet); | ||
442 | 1700 | |||
443 | 1679 | // Broadcast new information about the player to everybody | 1701 | // Broadcast new information about the player to everybody |
444 | 1680 | packet.reset(); | 1702 | packet.reset(); |
445 | 1681 | packet.unsigned_8(NETCMD_SETTING_USER); | 1703 | packet.unsigned_8(NETCMD_SETTING_USER); |
446 | @@ -2143,6 +2165,12 @@ | |||
447 | 2143 | } | 2165 | } |
448 | 2144 | break; | 2166 | break; |
449 | 2145 | 2167 | ||
450 | 2168 | case NETCMD_PEACEFUL_MODE: | ||
451 | 2169 | if (!d->game) { | ||
452 | 2170 | throw DisconnectException("NO_ACCESS_TO_SERVER"); | ||
453 | 2171 | } | ||
454 | 2172 | break; | ||
455 | 2173 | |||
456 | 2146 | case NETCMD_LAUNCH: | 2174 | case NETCMD_LAUNCH: |
457 | 2147 | if (!d->game) { | 2175 | if (!d->game) { |
458 | 2148 | throw DisconnectException("NO_ACCESS_TO_SERVER"); | 2176 | throw DisconnectException("NO_ACCESS_TO_SERVER"); |
459 | 2149 | 2177 | ||
460 | === modified file 'src/network/gamehost.h' | |||
461 | --- src/network/gamehost.h 2019-02-23 11:00:49 +0000 | |||
462 | +++ src/network/gamehost.h 2019-04-26 16:56:58 +0000 | |||
463 | @@ -80,6 +80,7 @@ | |||
464 | 80 | void set_player_shared(PlayerSlot number, Widelands::PlayerNumber shared); | 80 | void set_player_shared(PlayerSlot number, Widelands::PlayerNumber shared); |
465 | 81 | void switch_to_player(uint32_t user, uint8_t number); | 81 | void switch_to_player(uint32_t user, uint8_t number); |
466 | 82 | void set_win_condition_script(const std::string& wc); | 82 | void set_win_condition_script(const std::string& wc); |
467 | 83 | void set_peaceful_mode(bool peace); | ||
468 | 83 | void replace_client_with_ai(uint8_t playernumber, const std::string& ai); | 84 | void replace_client_with_ai(uint8_t playernumber, const std::string& ai); |
469 | 84 | 85 | ||
470 | 85 | // just visible stuff for the select mapmenu | 86 | // just visible stuff for the select mapmenu |
471 | 86 | 87 | ||
472 | === modified file 'src/network/network_protocol.h' | |||
473 | --- src/network/network_protocol.h 2019-02-23 11:00:49 +0000 | |||
474 | +++ src/network/network_protocol.h 2019-04-26 16:56:58 +0000 | |||
475 | @@ -28,7 +28,7 @@ | |||
476 | 28 | * The current version of the in-game network protocol. Client and host | 28 | * The current version of the in-game network protocol. Client and host |
477 | 29 | * protocol versions must match. | 29 | * protocol versions must match. |
478 | 30 | */ | 30 | */ |
480 | 31 | NETWORK_PROTOCOL_VERSION = 22, | 31 | NETWORK_PROTOCOL_VERSION = 23, |
481 | 32 | 32 | ||
482 | 33 | /** | 33 | /** |
483 | 34 | * The default interval (in milliseconds) in which the host issues | 34 | * The default interval (in milliseconds) in which the host issues |
484 | @@ -429,6 +429,14 @@ | |||
485 | 429 | NETCMD_SYSTEM_MESSAGE_CODE = 32, | 429 | NETCMD_SYSTEM_MESSAGE_CODE = 32, |
486 | 430 | 430 | ||
487 | 431 | /** | 431 | /** |
488 | 432 | * Sent by the host to toggle peaceful mode. | ||
489 | 433 | * | ||
490 | 434 | * Attached data is: | ||
491 | 435 | * \li uint8_t: 1 if peaceful mode is enabled, 0 otherwise | ||
492 | 436 | */ | ||
493 | 437 | NETCMD_PEACEFUL_MODE = 33, | ||
494 | 438 | |||
495 | 439 | /** | ||
496 | 432 | * Sent by the metaserver to a freshly opened game to check connectability | 440 | * Sent by the metaserver to a freshly opened game to check connectability |
497 | 433 | */ | 441 | */ |
498 | 434 | NETCMD_METASERVER_PING = 64 | 442 | NETCMD_METASERVER_PING = 64 |
499 | 435 | 443 | ||
500 | === modified file 'src/scripting/lua_game.cc' | |||
501 | --- src/scripting/lua_game.cc 2019-04-24 06:43:22 +0000 | |||
502 | +++ src/scripting/lua_game.cc 2019-04-26 16:56:58 +0000 | |||
503 | @@ -100,6 +100,8 @@ | |||
504 | 100 | METHOD(LuaPlayer, allow_workers), | 100 | METHOD(LuaPlayer, allow_workers), |
505 | 101 | METHOD(LuaPlayer, switchplayer), | 101 | METHOD(LuaPlayer, switchplayer), |
506 | 102 | METHOD(LuaPlayer, get_produced_wares_count), | 102 | METHOD(LuaPlayer, get_produced_wares_count), |
507 | 103 | METHOD(LuaPlayer, set_attack_forbidden), | ||
508 | 104 | METHOD(LuaPlayer, is_attack_forbidden), | ||
509 | 103 | {nullptr, nullptr}, | 105 | {nullptr, nullptr}, |
510 | 104 | }; | 106 | }; |
511 | 105 | const PropertyType<LuaPlayer> LuaPlayer::Properties[] = { | 107 | const PropertyType<LuaPlayer> LuaPlayer::Properties[] = { |
512 | @@ -856,6 +858,39 @@ | |||
513 | 856 | return 1; | 858 | return 1; |
514 | 857 | } | 859 | } |
515 | 858 | 860 | ||
516 | 861 | /* RST | ||
517 | 862 | .. method:: is_attack_forbidden(who) | ||
518 | 863 | |||
519 | 864 | Returns true if this player is currently forbidden to attack the player with the specified | ||
520 | 865 | player number. Note that the return value `false` does not necessarily mean that this | ||
521 | 866 | player *can* attack the other player, as they might for example be in the same team. | ||
522 | 867 | |||
523 | 868 | :arg who: player number of the player to query | ||
524 | 869 | :type who: :class:`int` | ||
525 | 870 | :rtype: :class:`boolean` | ||
526 | 871 | */ | ||
527 | 872 | int LuaPlayer::is_attack_forbidden(lua_State* L) { | ||
528 | 873 | lua_pushboolean(L, get(L, get_egbase(L)).is_attack_forbidden(luaL_checkinteger(L, 2))); | ||
529 | 874 | return 1; | ||
530 | 875 | } | ||
531 | 876 | |||
532 | 877 | /* RST | ||
533 | 878 | .. method:: set_attack_forbidden(who, forbid) | ||
534 | 879 | |||
535 | 880 | Sets whether this player is forbidden to attack the player with the specified | ||
536 | 881 | player number. Note that setting this to `false` does not necessarily mean that this | ||
537 | 882 | player *can* attack the other player, as they might for example be in the same team. | ||
538 | 883 | |||
539 | 884 | :arg who: player number of the player to query | ||
540 | 885 | :type who: :class:`int` | ||
541 | 886 | :arg forbid: Whether to allow or forbid attacks | ||
542 | 887 | :type forbid: :class:`boolean` | ||
543 | 888 | */ | ||
544 | 889 | int LuaPlayer::set_attack_forbidden(lua_State* L) { | ||
545 | 890 | get(L, get_egbase(L)).set_attack_forbidden(luaL_checkinteger(L, 2), luaL_checkboolean(L, 3)); | ||
546 | 891 | return 0; | ||
547 | 892 | } | ||
548 | 893 | |||
549 | 859 | /* | 894 | /* |
550 | 860 | ========================================================== | 895 | ========================================================== |
551 | 861 | C METHODS | 896 | C METHODS |
552 | 862 | 897 | ||
553 | === modified file 'src/scripting/lua_game.h' | |||
554 | --- src/scripting/lua_game.h 2019-04-18 16:50:35 +0000 | |||
555 | +++ src/scripting/lua_game.h 2019-04-26 16:56:58 +0000 | |||
556 | @@ -96,6 +96,8 @@ | |||
557 | 96 | int allow_workers(lua_State* L); | 96 | int allow_workers(lua_State* L); |
558 | 97 | int switchplayer(lua_State* L); | 97 | int switchplayer(lua_State* L); |
559 | 98 | int get_produced_wares_count(lua_State* L); | 98 | int get_produced_wares_count(lua_State* L); |
560 | 99 | int set_attack_forbidden(lua_State* L); | ||
561 | 100 | int is_attack_forbidden(lua_State* L); | ||
562 | 99 | 101 | ||
563 | 100 | /* | 102 | /* |
564 | 101 | * C methods | 103 | * C methods |
565 | 102 | 104 | ||
566 | === modified file 'src/ui_fsmenu/launch_game.cc' | |||
567 | --- src/ui_fsmenu/launch_game.cc 2019-02-23 11:00:49 +0000 | |||
568 | +++ src/ui_fsmenu/launch_game.cc 2019-04-26 16:56:58 +0000 | |||
569 | @@ -55,6 +55,11 @@ | |||
570 | 55 | "", | 55 | "", |
571 | 56 | UI::DropdownType::kTextual, | 56 | UI::DropdownType::kTextual, |
572 | 57 | UI::PanelStyle::kFsMenu), | 57 | UI::PanelStyle::kFsMenu), |
573 | 58 | |||
574 | 59 | peaceful_(this, | ||
575 | 60 | Vector2i(get_w() * 7 / 10, | ||
576 | 61 | get_h() * 19 / 40 + buth_), | ||
577 | 62 | _("Peaceful mode")), | ||
578 | 58 | ok_(this, "ok", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuPrimary, _("Start game")), | 63 | ok_(this, "ok", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuPrimary, _("Start game")), |
579 | 59 | back_(this, "back", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuSecondary, _("Back")), | 64 | back_(this, "back", 0, 0, butw_, buth_, UI::ButtonStyle::kFsMenuSecondary, _("Back")), |
580 | 60 | // Text labels | 65 | // Text labels |
581 | @@ -62,9 +67,12 @@ | |||
582 | 62 | // Variables and objects used in the menu | 67 | // Variables and objects used in the menu |
583 | 63 | settings_(settings), | 68 | settings_(settings), |
584 | 64 | ctrl_(ctrl), | 69 | ctrl_(ctrl), |
585 | 70 | peaceful_mode_forbidden_(false), | ||
586 | 65 | nr_players_(0) { | 71 | nr_players_(0) { |
587 | 66 | win_condition_dropdown_.selected.connect( | 72 | win_condition_dropdown_.selected.connect( |
588 | 67 | boost::bind(&FullscreenMenuLaunchGame::win_condition_selected, this)); | 73 | boost::bind(&FullscreenMenuLaunchGame::win_condition_selected, this)); |
589 | 74 | peaceful_.changed.connect( | ||
590 | 75 | boost::bind(&FullscreenMenuLaunchGame::toggle_peaceful, this)); | ||
591 | 68 | back_.sigclicked.connect( | 76 | back_.sigclicked.connect( |
592 | 69 | boost::bind(&FullscreenMenuLaunchGame::clicked_back, boost::ref(*this))); | 77 | boost::bind(&FullscreenMenuLaunchGame::clicked_back, boost::ref(*this))); |
593 | 70 | ok_.sigclicked.connect(boost::bind(&FullscreenMenuLaunchGame::clicked_ok, boost::ref(*this))); | 78 | ok_.sigclicked.connect(boost::bind(&FullscreenMenuLaunchGame::clicked_ok, boost::ref(*this))); |
594 | @@ -78,6 +86,23 @@ | |||
595 | 78 | delete lua_; | 86 | delete lua_; |
596 | 79 | } | 87 | } |
597 | 80 | 88 | ||
598 | 89 | void FullscreenMenuLaunchGame::update_peaceful_mode() { | ||
599 | 90 | bool forbidden = peaceful_mode_forbidden_ || settings_->settings().scenario || settings_->settings().savegame; | ||
600 | 91 | peaceful_.set_enabled(!forbidden && settings_->can_change_map()); | ||
601 | 92 | if (forbidden) { | ||
602 | 93 | peaceful_.set_state(false); | ||
603 | 94 | } | ||
604 | 95 | if (settings_->settings().scenario) { | ||
605 | 96 | peaceful_.set_tooltip(_("The relations between players are set by the scenario")); | ||
606 | 97 | } else if (settings_->settings().savegame) { | ||
607 | 98 | peaceful_.set_tooltip(_("The relations between players are set by the saved game")); | ||
608 | 99 | } else if (peaceful_mode_forbidden_) { | ||
609 | 100 | peaceful_.set_tooltip(_("The selected win condition does not allow peaceful matches")); | ||
610 | 101 | } else { | ||
611 | 102 | peaceful_.set_tooltip(_("Forbid fighting between players")); | ||
612 | 103 | } | ||
613 | 104 | } | ||
614 | 105 | |||
615 | 81 | bool FullscreenMenuLaunchGame::init_win_condition_label() { | 106 | bool FullscreenMenuLaunchGame::init_win_condition_label() { |
616 | 82 | if (settings_->settings().scenario) { | 107 | if (settings_->settings().scenario) { |
617 | 83 | win_condition_dropdown_.set_enabled(false); | 108 | win_condition_dropdown_.set_enabled(false); |
618 | @@ -190,6 +215,10 @@ | |||
619 | 190 | return t; | 215 | return t; |
620 | 191 | } | 216 | } |
621 | 192 | 217 | ||
622 | 218 | void FullscreenMenuLaunchGame::toggle_peaceful() { | ||
623 | 219 | settings_->set_peaceful_mode(peaceful_.get_state()); | ||
624 | 220 | } | ||
625 | 221 | |||
626 | 193 | // Implemented by subclasses | 222 | // Implemented by subclasses |
627 | 194 | void FullscreenMenuLaunchGame::clicked_ok() { | 223 | void FullscreenMenuLaunchGame::clicked_ok() { |
628 | 195 | NEVER_HERE(); | 224 | NEVER_HERE(); |
629 | 196 | 225 | ||
630 | === modified file 'src/ui_fsmenu/launch_game.h' | |||
631 | --- src/ui_fsmenu/launch_game.h 2019-02-23 11:00:49 +0000 | |||
632 | +++ src/ui_fsmenu/launch_game.h 2019-04-26 16:56:58 +0000 | |||
633 | @@ -26,6 +26,7 @@ | |||
634 | 26 | #include "graphic/playercolor.h" | 26 | #include "graphic/playercolor.h" |
635 | 27 | #include "logic/map.h" | 27 | #include "logic/map.h" |
636 | 28 | #include "ui_basic/button.h" | 28 | #include "ui_basic/button.h" |
637 | 29 | #include "ui_basic/checkbox.h" | ||
638 | 29 | #include "ui_basic/dropdown.h" | 30 | #include "ui_basic/dropdown.h" |
639 | 30 | #include "ui_basic/textarea.h" | 31 | #include "ui_basic/textarea.h" |
640 | 31 | #include "ui_fsmenu/base.h" | 32 | #include "ui_fsmenu/base.h" |
641 | @@ -56,6 +57,9 @@ | |||
642 | 56 | /// Creates a blank label/tooltip and returns 'false' otherwise. | 57 | /// Creates a blank label/tooltip and returns 'false' otherwise. |
643 | 57 | bool init_win_condition_label(); | 58 | bool init_win_condition_label(); |
644 | 58 | 59 | ||
645 | 60 | /// Enables or disables the peaceful mode checkbox. | ||
646 | 61 | void update_peaceful_mode(); | ||
647 | 62 | |||
648 | 59 | /// Loads all win conditions that can be played with the map into the selection dropdown. | 63 | /// Loads all win conditions that can be played with the map into the selection dropdown. |
649 | 60 | /// Disables the dropdown if the map is a scenario. | 64 | /// Disables the dropdown if the map is a scenario. |
650 | 61 | void update_win_conditions(); | 65 | void update_win_conditions(); |
651 | @@ -71,16 +75,21 @@ | |||
652 | 71 | std::unique_ptr<LuaTable> win_condition_if_valid(const std::string& win_condition_script, | 75 | std::unique_ptr<LuaTable> win_condition_if_valid(const std::string& win_condition_script, |
653 | 72 | std::set<std::string> tags) const; | 76 | std::set<std::string> tags) const; |
654 | 73 | 77 | ||
655 | 78 | void toggle_peaceful(); | ||
656 | 79 | |||
657 | 74 | uint32_t butw_; | 80 | uint32_t butw_; |
658 | 75 | uint32_t buth_; | 81 | uint32_t buth_; |
659 | 76 | 82 | ||
660 | 77 | UI::Dropdown<std::string> win_condition_dropdown_; | 83 | UI::Dropdown<std::string> win_condition_dropdown_; |
661 | 84 | UI::Checkbox peaceful_; | ||
662 | 78 | std::string last_win_condition_; | 85 | std::string last_win_condition_; |
663 | 79 | UI::Button ok_, back_; | 86 | UI::Button ok_, back_; |
664 | 80 | UI::Textarea title_; | 87 | UI::Textarea title_; |
665 | 81 | GameSettingsProvider* settings_; | 88 | GameSettingsProvider* settings_; |
666 | 82 | GameController* ctrl_; | 89 | GameController* ctrl_; |
667 | 83 | 90 | ||
668 | 91 | bool peaceful_mode_forbidden_; | ||
669 | 92 | |||
670 | 84 | Widelands::PlayerNumber nr_players_; | 93 | Widelands::PlayerNumber nr_players_; |
671 | 85 | }; | 94 | }; |
672 | 86 | 95 | ||
673 | 87 | 96 | ||
674 | === modified file 'src/ui_fsmenu/launch_mpg.cc' | |||
675 | --- src/ui_fsmenu/launch_mpg.cc 2019-02-23 11:00:49 +0000 | |||
676 | +++ src/ui_fsmenu/launch_mpg.cc 2019-04-26 16:56:58 +0000 | |||
677 | @@ -159,7 +159,7 @@ | |||
678 | 159 | UI::PanelStyle::kFsMenu), | 159 | UI::PanelStyle::kFsMenu), |
679 | 160 | client_info_(this, | 160 | client_info_(this, |
680 | 161 | right_column_x_, | 161 | right_column_x_, |
682 | 162 | get_h() * 13 / 20 - 2 * label_height_, | 162 | get_h() * 15 / 20 - 2 * label_height_, |
683 | 163 | butw_, | 163 | butw_, |
684 | 164 | get_h(), | 164 | get_h(), |
685 | 165 | UI::PanelStyle::kFsMenu), | 165 | UI::PanelStyle::kFsMenu), |
686 | @@ -167,7 +167,8 @@ | |||
687 | 167 | 167 | ||
688 | 168 | // Variables and objects used in the menu | 168 | // Variables and objects used in the menu |
689 | 169 | chat_(nullptr) { | 169 | chat_(nullptr) { |
691 | 170 | ok_.set_pos(Vector2i(right_column_x_, get_h() * 12 / 20 - 2 * label_height_)); | 170 | peaceful_.set_pos(Vector2i(right_column_x_, get_h() * 25 / 40 - 2 * label_height_)); |
692 | 171 | ok_.set_pos(Vector2i(right_column_x_, get_h() * 14 / 20 - 2 * label_height_)); | ||
693 | 171 | back_.set_pos(Vector2i(right_column_x_, get_h() * 218 / 240)); | 172 | back_.set_pos(Vector2i(right_column_x_, get_h() * 218 / 240)); |
694 | 172 | win_condition_dropdown_.set_pos( | 173 | win_condition_dropdown_.set_pos( |
695 | 173 | Vector2i(right_column_x_, get_h() * 11 / 20 - 2 * label_height_)); | 174 | Vector2i(right_column_x_, get_h() * 11 / 20 - 2 * label_height_)); |
696 | @@ -240,6 +241,11 @@ | |||
697 | 240 | if (settings_->can_change_map() && win_condition_dropdown_.has_selection()) { | 241 | if (settings_->can_change_map() && win_condition_dropdown_.has_selection()) { |
698 | 241 | settings_->set_win_condition_script(win_condition_dropdown_.get_selected()); | 242 | settings_->set_win_condition_script(win_condition_dropdown_.get_selected()); |
699 | 242 | last_win_condition_ = win_condition_dropdown_.get_selected(); | 243 | last_win_condition_ = win_condition_dropdown_.get_selected(); |
700 | 244 | |||
701 | 245 | std::unique_ptr<LuaTable> t = lua_->run_script(last_win_condition_); | ||
702 | 246 | t->do_not_warn_about_unaccessed_keys(); | ||
703 | 247 | peaceful_mode_forbidden_ = !t->get_bool("peaceful_mode_allowed"); | ||
704 | 248 | update_peaceful_mode(); | ||
705 | 243 | } | 249 | } |
706 | 244 | } | 250 | } |
707 | 245 | 251 | ||
708 | @@ -422,6 +428,9 @@ | |||
709 | 422 | change_map_or_save_.set_enabled(settings_->can_change_map()); | 428 | change_map_or_save_.set_enabled(settings_->can_change_map()); |
710 | 423 | change_map_or_save_.set_visible(settings_->can_change_map()); | 429 | change_map_or_save_.set_visible(settings_->can_change_map()); |
711 | 424 | 430 | ||
712 | 431 | update_peaceful_mode(); | ||
713 | 432 | peaceful_.set_state(settings_->is_peaceful_mode()); | ||
714 | 433 | |||
715 | 425 | if (!settings_->can_change_map() && !init_win_condition_label()) { | 434 | if (!settings_->can_change_map() && !init_win_condition_label()) { |
716 | 426 | try { | 435 | try { |
717 | 427 | // We do not validate the scripts for the client - it's only a label. | 436 | // We do not validate the scripts for the client - it's only a label. |
718 | 428 | 437 | ||
719 | === modified file 'src/ui_fsmenu/launch_spg.cc' | |||
720 | --- src/ui_fsmenu/launch_spg.cc 2019-02-23 11:00:49 +0000 | |||
721 | +++ src/ui_fsmenu/launch_spg.cc 2019-04-26 16:56:58 +0000 | |||
722 | @@ -166,6 +166,11 @@ | |||
723 | 166 | void FullscreenMenuLaunchSPG::win_condition_selected() { | 166 | void FullscreenMenuLaunchSPG::win_condition_selected() { |
724 | 167 | if (win_condition_dropdown_.has_selection()) { | 167 | if (win_condition_dropdown_.has_selection()) { |
725 | 168 | last_win_condition_ = win_condition_dropdown_.get_selected(); | 168 | last_win_condition_ = win_condition_dropdown_.get_selected(); |
726 | 169 | |||
727 | 170 | std::unique_ptr<LuaTable> t = lua_->run_script(last_win_condition_); | ||
728 | 171 | t->do_not_warn_about_unaccessed_keys(); | ||
729 | 172 | peaceful_mode_forbidden_ = !t->get_bool("peaceful_mode_allowed"); | ||
730 | 173 | update_peaceful_mode(); | ||
731 | 169 | } | 174 | } |
732 | 170 | } | 175 | } |
733 | 171 | 176 | ||
734 | @@ -217,6 +222,8 @@ | |||
735 | 217 | select_map_.set_visible(settings_->can_change_map()); | 222 | select_map_.set_visible(settings_->can_change_map()); |
736 | 218 | select_map_.set_enabled(settings_->can_change_map()); | 223 | select_map_.set_enabled(settings_->can_change_map()); |
737 | 219 | 224 | ||
738 | 225 | peaceful_.set_state(settings_->is_peaceful_mode()); | ||
739 | 226 | |||
740 | 220 | set_player_names_and_tribes(); | 227 | set_player_names_and_tribes(); |
741 | 221 | } | 228 | } |
742 | 222 | 229 | ||
743 | @@ -262,6 +269,7 @@ | |||
744 | 262 | safe_place_for_host(nr_players_); | 269 | safe_place_for_host(nr_players_); |
745 | 263 | settings_->set_map(mapdata.name, mapdata.filename, nr_players_); | 270 | settings_->set_map(mapdata.name, mapdata.filename, nr_players_); |
746 | 264 | update_win_conditions(); | 271 | update_win_conditions(); |
747 | 272 | update_peaceful_mode(); | ||
748 | 265 | update(true); | 273 | update(true); |
749 | 266 | return true; | 274 | return true; |
750 | 267 | } | 275 | } |
751 | 268 | 276 | ||
752 | === added file 'test/maps/port_space.wmf/scripting/test_attack_forbidden.lua' | |||
753 | --- test/maps/port_space.wmf/scripting/test_attack_forbidden.lua 1970-01-01 00:00:00 +0000 | |||
754 | +++ test/maps/port_space.wmf/scripting/test_attack_forbidden.lua 2019-04-26 16:56:58 +0000 | |||
755 | @@ -0,0 +1,38 @@ | |||
756 | 1 | run(function() | ||
757 | 2 | -- Initially, no overrides exist | ||
758 | 3 | assert_equal(false, p1:is_attack_forbidden(2)) | ||
759 | 4 | assert_equal(false, p2:is_attack_forbidden(1)) | ||
760 | 5 | -- No dumbness checks should take place | ||
761 | 6 | assert_equal(false, p1:is_attack_forbidden(1)) | ||
762 | 7 | assert_equal(false, p2:is_attack_forbidden(2)) | ||
763 | 8 | assert_equal(false, p1:is_attack_forbidden(3)) | ||
764 | 9 | |||
765 | 10 | p1:set_attack_forbidden(2, true) | ||
766 | 11 | |||
767 | 12 | assert_equal(true, p1:is_attack_forbidden(2)) | ||
768 | 13 | assert_equal(false, p2:is_attack_forbidden(1)) | ||
769 | 14 | assert_equal(false, p1:is_attack_forbidden(3)) | ||
770 | 15 | |||
771 | 16 | p2:set_attack_forbidden(3, true) | ||
772 | 17 | |||
773 | 18 | assert_equal(true, p1:is_attack_forbidden(2)) | ||
774 | 19 | assert_equal(false, p2:is_attack_forbidden(1)) | ||
775 | 20 | assert_equal(false, p1:is_attack_forbidden(3)) | ||
776 | 21 | assert_equal(true, p2:is_attack_forbidden(3)) | ||
777 | 22 | |||
778 | 23 | p2:set_attack_forbidden(1, true) | ||
779 | 24 | |||
780 | 25 | assert_equal(true, p1:is_attack_forbidden(2)) | ||
781 | 26 | assert_equal(true, p2:is_attack_forbidden(1)) | ||
782 | 27 | assert_equal(true, p2:is_attack_forbidden(3)) | ||
783 | 28 | |||
784 | 29 | p2:set_attack_forbidden(1, false) | ||
785 | 30 | p1:set_attack_forbidden(2, false) | ||
786 | 31 | |||
787 | 32 | assert_equal(false, p2:is_attack_forbidden(1)) | ||
788 | 33 | assert_equal(false, p1:is_attack_forbidden(2)) | ||
789 | 34 | assert_equal(true, p2:is_attack_forbidden(3)) | ||
790 | 35 | |||
791 | 36 | print("# All Tests passed.") | ||
792 | 37 | wl.ui.MapView():close() | ||
793 | 38 | end) |
Continuous integration builds have changed state:
Travis build 4656. State: errored. Details: https:/ /travis- ci.org/ widelands/ widelands/ builds/ 512954165. /ci.appveyor. com/project/ widelands- dev/widelands/ build/_ widelands_ dev_widelands_ peaceful- 4443.
Appveyor build 4443. State: success. Details: https:/