|
1 /* $Id$ */ |
|
2 |
|
3 #include "stdafx.h" |
|
4 #include "openttd.h" |
|
5 #include "table/strings.h" |
|
6 #include "functions.h" |
|
7 #include "map.h" |
|
8 #include "gui.h" |
|
9 #include "command.h" |
|
10 #include "player.h" |
|
11 #include "network/network.h" |
|
12 #include "variables.h" |
|
13 #include "genworld.h" |
|
14 |
|
15 const char* _cmd_text = NULL; |
|
16 |
|
17 #define DEF_COMMAND(yyyy) int32 yyyy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
|
18 |
|
19 DEF_COMMAND(CmdBuildRailroadTrack); |
|
20 DEF_COMMAND(CmdRemoveRailroadTrack); |
|
21 DEF_COMMAND(CmdBuildSingleRail); |
|
22 DEF_COMMAND(CmdRemoveSingleRail); |
|
23 |
|
24 DEF_COMMAND(CmdLandscapeClear); |
|
25 |
|
26 DEF_COMMAND(CmdBuildBridge); |
|
27 |
|
28 DEF_COMMAND(CmdBuildRailroadStation); |
|
29 DEF_COMMAND(CmdRemoveFromRailroadStation); |
|
30 DEF_COMMAND(CmdConvertRail); |
|
31 |
|
32 DEF_COMMAND(CmdBuildSingleSignal); |
|
33 DEF_COMMAND(CmdRemoveSingleSignal); |
|
34 |
|
35 DEF_COMMAND(CmdTerraformLand); |
|
36 |
|
37 DEF_COMMAND(CmdPurchaseLandArea); |
|
38 DEF_COMMAND(CmdSellLandArea); |
|
39 |
|
40 DEF_COMMAND(CmdBuildTunnel); |
|
41 |
|
42 DEF_COMMAND(CmdBuildTrainDepot); |
|
43 DEF_COMMAND(CmdBuildTrainWaypoint); |
|
44 DEF_COMMAND(CmdRenameWaypoint); |
|
45 DEF_COMMAND(CmdRemoveTrainWaypoint); |
|
46 |
|
47 DEF_COMMAND(CmdBuildRoadStop); |
|
48 |
|
49 DEF_COMMAND(CmdBuildLongRoad); |
|
50 DEF_COMMAND(CmdRemoveLongRoad); |
|
51 DEF_COMMAND(CmdBuildRoad); |
|
52 DEF_COMMAND(CmdRemoveRoad); |
|
53 |
|
54 DEF_COMMAND(CmdBuildRoadDepot); |
|
55 |
|
56 DEF_COMMAND(CmdBuildAirport); |
|
57 |
|
58 DEF_COMMAND(CmdBuildDock); |
|
59 |
|
60 DEF_COMMAND(CmdBuildShipDepot); |
|
61 |
|
62 DEF_COMMAND(CmdBuildBuoy); |
|
63 |
|
64 DEF_COMMAND(CmdPlantTree); |
|
65 |
|
66 DEF_COMMAND(CmdBuildRailVehicle); |
|
67 DEF_COMMAND(CmdMoveRailVehicle); |
|
68 |
|
69 DEF_COMMAND(CmdStartStopTrain); |
|
70 |
|
71 DEF_COMMAND(CmdSellRailWagon); |
|
72 |
|
73 DEF_COMMAND(CmdSendTrainToDepot); |
|
74 DEF_COMMAND(CmdForceTrainProceed); |
|
75 DEF_COMMAND(CmdReverseTrainDirection); |
|
76 |
|
77 DEF_COMMAND(CmdModifyOrder); |
|
78 DEF_COMMAND(CmdSkipOrder); |
|
79 DEF_COMMAND(CmdDeleteOrder); |
|
80 DEF_COMMAND(CmdInsertOrder); |
|
81 DEF_COMMAND(CmdChangeServiceInt); |
|
82 DEF_COMMAND(CmdRestoreOrderIndex); |
|
83 |
|
84 DEF_COMMAND(CmdBuildIndustry); |
|
85 |
|
86 DEF_COMMAND(CmdBuildCompanyHQ); |
|
87 DEF_COMMAND(CmdSetPlayerFace); |
|
88 DEF_COMMAND(CmdSetPlayerColor); |
|
89 |
|
90 DEF_COMMAND(CmdIncreaseLoan); |
|
91 DEF_COMMAND(CmdDecreaseLoan); |
|
92 |
|
93 DEF_COMMAND(CmdWantEnginePreview); |
|
94 |
|
95 DEF_COMMAND(CmdNameVehicle); |
|
96 DEF_COMMAND(CmdRenameEngine); |
|
97 |
|
98 DEF_COMMAND(CmdChangeCompanyName); |
|
99 DEF_COMMAND(CmdChangePresidentName); |
|
100 |
|
101 DEF_COMMAND(CmdRenameStation); |
|
102 |
|
103 DEF_COMMAND(CmdSellAircraft); |
|
104 DEF_COMMAND(CmdStartStopAircraft); |
|
105 DEF_COMMAND(CmdBuildAircraft); |
|
106 DEF_COMMAND(CmdSendAircraftToHangar); |
|
107 DEF_COMMAND(CmdRefitAircraft); |
|
108 |
|
109 DEF_COMMAND(CmdPlaceSign); |
|
110 DEF_COMMAND(CmdRenameSign); |
|
111 |
|
112 DEF_COMMAND(CmdBuildRoadVeh); |
|
113 DEF_COMMAND(CmdStartStopRoadVeh); |
|
114 DEF_COMMAND(CmdSellRoadVeh); |
|
115 DEF_COMMAND(CmdSendRoadVehToDepot); |
|
116 DEF_COMMAND(CmdTurnRoadVeh); |
|
117 DEF_COMMAND(CmdRefitRoadVeh); |
|
118 |
|
119 DEF_COMMAND(CmdPause); |
|
120 |
|
121 DEF_COMMAND(CmdBuyShareInCompany); |
|
122 DEF_COMMAND(CmdSellShareInCompany); |
|
123 DEF_COMMAND(CmdBuyCompany); |
|
124 |
|
125 DEF_COMMAND(CmdBuildTown); |
|
126 |
|
127 DEF_COMMAND(CmdRenameTown); |
|
128 DEF_COMMAND(CmdDoTownAction); |
|
129 |
|
130 DEF_COMMAND(CmdSetRoadDriveSide); |
|
131 |
|
132 DEF_COMMAND(CmdChangeDifficultyLevel); |
|
133 DEF_COMMAND(CmdChangePatchSetting); |
|
134 |
|
135 DEF_COMMAND(CmdStartStopShip); |
|
136 DEF_COMMAND(CmdSellShip); |
|
137 DEF_COMMAND(CmdBuildShip); |
|
138 DEF_COMMAND(CmdSendShipToDepot); |
|
139 DEF_COMMAND(CmdRefitShip); |
|
140 |
|
141 DEF_COMMAND(CmdOrderRefit); |
|
142 DEF_COMMAND(CmdCloneOrder); |
|
143 |
|
144 DEF_COMMAND(CmdClearArea); |
|
145 |
|
146 DEF_COMMAND(CmdGiveMoney); |
|
147 DEF_COMMAND(CmdMoneyCheat); |
|
148 DEF_COMMAND(CmdBuildCanal); |
|
149 DEF_COMMAND(CmdBuildLock); |
|
150 |
|
151 DEF_COMMAND(CmdPlayerCtrl); |
|
152 |
|
153 DEF_COMMAND(CmdLevelLand); |
|
154 |
|
155 DEF_COMMAND(CmdRefitRailVehicle); |
|
156 |
|
157 DEF_COMMAND(CmdBuildSignalTrack); |
|
158 DEF_COMMAND(CmdRemoveSignalTrack); |
|
159 |
|
160 DEF_COMMAND(CmdSetAutoReplace); |
|
161 |
|
162 DEF_COMMAND(CmdCloneVehicle); |
|
163 DEF_COMMAND(CmdMassStartStopVehicle); |
|
164 DEF_COMMAND(CmdDepotSellAllVehicles); |
|
165 DEF_COMMAND(CmdDepotMassAutoReplace); |
|
166 |
|
167 /* The master command table */ |
|
168 static const Command _command_proc_table[] = { |
|
169 {CmdBuildRailroadTrack, 0}, /* 0 */ |
|
170 {CmdRemoveRailroadTrack, 0}, /* 1 */ |
|
171 {CmdBuildSingleRail, 0}, /* 2 */ |
|
172 {CmdRemoveSingleRail, 0}, /* 3 */ |
|
173 {CmdLandscapeClear, 0}, /* 4 */ |
|
174 {CmdBuildBridge, 0}, /* 5 */ |
|
175 {CmdBuildRailroadStation, 0}, /* 6 */ |
|
176 {CmdBuildTrainDepot, 0}, /* 7 */ |
|
177 {CmdBuildSingleSignal, 0}, /* 8 */ |
|
178 {CmdRemoveSingleSignal, 0}, /* 9 */ |
|
179 {CmdTerraformLand, 0}, /* 10 */ |
|
180 {CmdPurchaseLandArea, 0}, /* 11 */ |
|
181 {CmdSellLandArea, 0}, /* 12 */ |
|
182 {CmdBuildTunnel, 0}, /* 13 */ |
|
183 {CmdRemoveFromRailroadStation, 0}, /* 14 */ |
|
184 {CmdConvertRail, 0}, /* 15 */ |
|
185 {CmdBuildTrainWaypoint, 0}, /* 16 */ |
|
186 {CmdRenameWaypoint, 0}, /* 17 */ |
|
187 {CmdRemoveTrainWaypoint, 0}, /* 18 */ |
|
188 {NULL, 0}, /* 19 */ |
|
189 {NULL, 0}, /* 20 */ |
|
190 {CmdBuildRoadStop, 0}, /* 21 */ |
|
191 {NULL, 0}, /* 22 */ |
|
192 {CmdBuildLongRoad, 0}, /* 23 */ |
|
193 {CmdRemoveLongRoad, 0}, /* 24 */ |
|
194 {CmdBuildRoad, 0}, /* 25 */ |
|
195 {CmdRemoveRoad, 0}, /* 26 */ |
|
196 {CmdBuildRoadDepot, 0}, /* 27 */ |
|
197 {NULL, 0}, /* 28 */ |
|
198 {CmdBuildAirport, 0}, /* 29 */ |
|
199 {CmdBuildDock, 0}, /* 30 */ |
|
200 {CmdBuildShipDepot, 0}, /* 31 */ |
|
201 {CmdBuildBuoy, 0}, /* 32 */ |
|
202 {CmdPlantTree, 0}, /* 33 */ |
|
203 {CmdBuildRailVehicle, 0}, /* 34 */ |
|
204 {CmdMoveRailVehicle, 0}, /* 35 */ |
|
205 {CmdStartStopTrain, 0}, /* 36 */ |
|
206 {NULL, 0}, /* 37 */ |
|
207 {CmdSellRailWagon, 0}, /* 38 */ |
|
208 {CmdSendTrainToDepot, 0}, /* 39 */ |
|
209 {CmdForceTrainProceed, 0}, /* 40 */ |
|
210 {CmdReverseTrainDirection, 0}, /* 41 */ |
|
211 |
|
212 {CmdModifyOrder, 0}, /* 42 */ |
|
213 {CmdSkipOrder, 0}, /* 43 */ |
|
214 {CmdDeleteOrder, 0}, /* 44 */ |
|
215 {CmdInsertOrder, 0}, /* 45 */ |
|
216 |
|
217 {CmdChangeServiceInt, 0}, /* 46 */ |
|
218 |
|
219 {CmdBuildIndustry, 0}, /* 47 */ |
|
220 {CmdBuildCompanyHQ, 0}, /* 48 */ |
|
221 {CmdSetPlayerFace, 0}, /* 49 */ |
|
222 {CmdSetPlayerColor, 0}, /* 50 */ |
|
223 |
|
224 {CmdIncreaseLoan, 0}, /* 51 */ |
|
225 {CmdDecreaseLoan, 0}, /* 52 */ |
|
226 |
|
227 {CmdWantEnginePreview, 0}, /* 53 */ |
|
228 |
|
229 {CmdNameVehicle, 0}, /* 54 */ |
|
230 {CmdRenameEngine, 0}, /* 55 */ |
|
231 |
|
232 {CmdChangeCompanyName, 0}, /* 56 */ |
|
233 {CmdChangePresidentName, 0}, /* 57 */ |
|
234 |
|
235 {CmdRenameStation, 0}, /* 58 */ |
|
236 |
|
237 {CmdSellAircraft, 0}, /* 59 */ |
|
238 {CmdStartStopAircraft, 0}, /* 60 */ |
|
239 |
|
240 {CmdBuildAircraft, 0}, /* 61 */ |
|
241 {CmdSendAircraftToHangar, 0}, /* 62 */ |
|
242 {NULL, 0}, /* 63 */ |
|
243 {CmdRefitAircraft, 0}, /* 64 */ |
|
244 |
|
245 {CmdPlaceSign, 0}, /* 65 */ |
|
246 {CmdRenameSign, 0}, /* 66 */ |
|
247 |
|
248 {CmdBuildRoadVeh, 0}, /* 67 */ |
|
249 {CmdStartStopRoadVeh, 0}, /* 68 */ |
|
250 {CmdSellRoadVeh, 0}, /* 69 */ |
|
251 {CmdSendRoadVehToDepot, 0}, /* 70 */ |
|
252 {CmdTurnRoadVeh, 0}, /* 71 */ |
|
253 {CmdRefitRoadVeh, 0}, /* 72 */ |
|
254 |
|
255 {CmdPause, CMD_SERVER}, /* 73 */ |
|
256 |
|
257 {CmdBuyShareInCompany, 0}, /* 74 */ |
|
258 {CmdSellShareInCompany, 0}, /* 75 */ |
|
259 {CmdBuyCompany, 0}, /* 76 */ |
|
260 |
|
261 {CmdBuildTown, CMD_OFFLINE}, /* 77 */ |
|
262 {NULL, 0}, /* 78 */ |
|
263 {NULL, 0}, /* 79 */ |
|
264 {CmdRenameTown, CMD_SERVER}, /* 80 */ |
|
265 {CmdDoTownAction, 0}, /* 81 */ |
|
266 |
|
267 {CmdSetRoadDriveSide, CMD_SERVER}, /* 82 */ |
|
268 {NULL, 0}, /* 83 */ |
|
269 {NULL, 0}, /* 84 */ |
|
270 {CmdChangeDifficultyLevel, CMD_SERVER}, /* 85 */ |
|
271 |
|
272 {CmdStartStopShip, 0}, /* 86 */ |
|
273 {CmdSellShip, 0}, /* 87 */ |
|
274 {CmdBuildShip, 0}, /* 88 */ |
|
275 {CmdSendShipToDepot, 0}, /* 89 */ |
|
276 {NULL, 0}, /* 90 */ |
|
277 {CmdRefitShip, 0}, /* 91 */ |
|
278 |
|
279 {NULL, 0}, /* 92 */ |
|
280 {NULL, 0}, /* 93 */ |
|
281 {NULL, 0}, /* 94 */ |
|
282 {NULL, 0}, /* 95 */ |
|
283 {NULL, 0}, /* 96 */ |
|
284 {NULL, 0}, /* 97 */ |
|
285 |
|
286 {CmdOrderRefit, 0}, /* 98 */ |
|
287 {CmdCloneOrder, 0}, /* 99 */ |
|
288 |
|
289 {CmdClearArea, 0}, /* 100 */ |
|
290 {NULL, 0}, /* 101 */ |
|
291 |
|
292 {CmdMoneyCheat, CMD_OFFLINE}, /* 102 */ |
|
293 {CmdBuildCanal, 0}, /* 103 */ |
|
294 {CmdPlayerCtrl, 0}, /* 104 */ |
|
295 |
|
296 {CmdLevelLand, 0}, /* 105 */ |
|
297 |
|
298 {CmdRefitRailVehicle, 0}, /* 106 */ |
|
299 {CmdRestoreOrderIndex, 0}, /* 107 */ |
|
300 {CmdBuildLock, 0}, /* 108 */ |
|
301 {NULL, 0}, /* 109 */ |
|
302 {CmdBuildSignalTrack, 0}, /* 110 */ |
|
303 {CmdRemoveSignalTrack, 0}, /* 111 */ |
|
304 {NULL, 0}, /* 112 */ |
|
305 {CmdGiveMoney, 0}, /* 113 */ |
|
306 {CmdChangePatchSetting, CMD_SERVER}, /* 114 */ |
|
307 {CmdSetAutoReplace, 0}, /* 115 */ |
|
308 {CmdCloneVehicle, 0}, /* 116 */ |
|
309 {CmdMassStartStopVehicle, 0}, /* 117 */ |
|
310 {CmdDepotSellAllVehicles, 0}, /* 118 */ |
|
311 {CmdDepotMassAutoReplace, 0}, /* 119 */ |
|
312 }; |
|
313 |
|
314 /* This function range-checks a cmd, and checks if the cmd is not NULL */ |
|
315 bool IsValidCommand(uint cmd) |
|
316 { |
|
317 cmd &= 0xFF; |
|
318 |
|
319 return |
|
320 cmd < lengthof(_command_proc_table) && |
|
321 _command_proc_table[cmd].proc != NULL; |
|
322 } |
|
323 |
|
324 byte GetCommandFlags(uint cmd) |
|
325 { |
|
326 return _command_proc_table[cmd & 0xFF].flags; |
|
327 } |
|
328 |
|
329 |
|
330 static int _docommand_recursive; |
|
331 |
|
332 int32 DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc) |
|
333 { |
|
334 int32 res; |
|
335 CommandProc *proc; |
|
336 |
|
337 /* Do not even think about executing out-of-bounds tile-commands */ |
|
338 if (tile >= MapSize()) { |
|
339 _cmd_text = NULL; |
|
340 return CMD_ERROR; |
|
341 } |
|
342 |
|
343 proc = _command_proc_table[procc].proc; |
|
344 |
|
345 if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID; |
|
346 |
|
347 _docommand_recursive++; |
|
348 |
|
349 // only execute the test call if it's toplevel, or we're not execing. |
|
350 if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) { |
|
351 res = proc(tile, flags & ~DC_EXEC, p1, p2); |
|
352 if (CmdFailed(res)) { |
|
353 if (res & 0xFFFF) _error_message = res & 0xFFFF; |
|
354 goto error; |
|
355 } |
|
356 |
|
357 if (_docommand_recursive == 1 && |
|
358 !(flags & DC_QUERY_COST) && |
|
359 res != 0 && |
|
360 !CheckPlayerHasMoney(res)) { |
|
361 goto error; |
|
362 } |
|
363 |
|
364 if (!(flags & DC_EXEC)) { |
|
365 _docommand_recursive--; |
|
366 _cmd_text = NULL; |
|
367 return res; |
|
368 } |
|
369 } |
|
370 |
|
371 /* Execute the command here. All cost-relevant functions set the expenses type |
|
372 * themselves with "SET_EXPENSES_TYPE(...);" at the beginning of the function */ |
|
373 res = proc(tile, flags, p1, p2); |
|
374 if (CmdFailed(res)) { |
|
375 if (res & 0xFFFF) _error_message = res & 0xFFFF; |
|
376 error: |
|
377 _docommand_recursive--; |
|
378 _cmd_text = NULL; |
|
379 return CMD_ERROR; |
|
380 } |
|
381 |
|
382 // if toplevel, subtract the money. |
|
383 if (--_docommand_recursive == 0) { |
|
384 SubtractMoneyFromPlayer(res); |
|
385 // XXX - Old AI hack which doesn't use DoCommandDP; update last build coord of player |
|
386 if (tile != 0 && IsValidPlayer(_current_player)) { |
|
387 GetPlayer(_current_player)->last_build_coordinate = tile; |
|
388 } |
|
389 } |
|
390 |
|
391 _cmd_text = NULL; |
|
392 return res; |
|
393 } |
|
394 |
|
395 int32 GetAvailableMoneyForCommand(void) |
|
396 { |
|
397 PlayerID pid = _current_player; |
|
398 if (!IsValidPlayer(pid)) return 0x7FFFFFFF; // max int |
|
399 return GetPlayer(pid)->player_money; |
|
400 } |
|
401 |
|
402 // toplevel network safe docommand function for the current player. must not be called recursively. |
|
403 // the callback is called when the command succeeded or failed. |
|
404 bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd) |
|
405 { |
|
406 int32 res = 0,res2; |
|
407 CommandProc *proc; |
|
408 uint32 flags; |
|
409 bool notest; |
|
410 StringID error_part1; |
|
411 |
|
412 int x = TileX(tile) * TILE_SIZE; |
|
413 int y = TileY(tile) * TILE_SIZE; |
|
414 |
|
415 /* Do not even think about executing out-of-bounds tile-commands */ |
|
416 if (tile >= MapSize()) { |
|
417 _cmd_text = NULL; |
|
418 return false; |
|
419 } |
|
420 |
|
421 assert(_docommand_recursive == 0); |
|
422 |
|
423 _error_message = INVALID_STRING_ID; |
|
424 error_part1 = GB(cmd, 16, 16); |
|
425 _additional_cash_required = 0; |
|
426 |
|
427 /** Spectator has no rights except for the (dedicated) server which |
|
428 * is/can be a spectator but as the server it can do anything */ |
|
429 if (_current_player == PLAYER_SPECTATOR && !_network_server) { |
|
430 ShowErrorMessage(_error_message, error_part1, x, y); |
|
431 _cmd_text = NULL; |
|
432 return false; |
|
433 } |
|
434 |
|
435 flags = 0; |
|
436 if (cmd & CMD_AUTO) flags |= DC_AUTO; |
|
437 if (cmd & CMD_NO_WATER) flags |= DC_NO_WATER; |
|
438 |
|
439 // get pointer to command handler |
|
440 assert((cmd & 0xFF) < lengthof(_command_proc_table)); |
|
441 proc = _command_proc_table[cmd & 0xFF].proc; |
|
442 if (proc == NULL) { |
|
443 _cmd_text = NULL; |
|
444 return false; |
|
445 } |
|
446 |
|
447 // Some commands have a different output in dryrun than the realrun |
|
448 // e.g.: if you demolish a whole town, the dryrun would say okay. |
|
449 // but by really destroying, your rating drops and at a certain point |
|
450 // it will fail. so res and res2 are different |
|
451 // CMD_REMOVE_ROAD: This command has special local authority |
|
452 // restrictions which may cause the test run to fail (the previous |
|
453 // road fragments still stay there and the town won't let you |
|
454 // disconnect the road system), but the exec will succeed and this |
|
455 // fact will trigger an assertion failure. --pasky |
|
456 notest = |
|
457 (cmd & 0xFF) == CMD_CLEAR_AREA || |
|
458 (cmd & 0xFF) == CMD_CONVERT_RAIL || |
|
459 (cmd & 0xFF) == CMD_LEVEL_LAND || |
|
460 (cmd & 0xFF) == CMD_REMOVE_ROAD || |
|
461 (cmd & 0xFF) == CMD_REMOVE_LONG_ROAD; |
|
462 |
|
463 _docommand_recursive = 1; |
|
464 |
|
465 // cost estimation only? |
|
466 if (!IsGeneratingWorld() && |
|
467 _shift_pressed && |
|
468 IsLocalPlayer() && |
|
469 !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR)) && |
|
470 (cmd & 0xFF) != CMD_PAUSE) { |
|
471 // estimate the cost. |
|
472 res = proc(tile, flags, p1, p2); |
|
473 if (CmdFailed(res)) { |
|
474 if (res & 0xFFFF) _error_message = res & 0xFFFF; |
|
475 ShowErrorMessage(_error_message, error_part1, x, y); |
|
476 } else { |
|
477 ShowEstimatedCostOrIncome(res, x, y); |
|
478 } |
|
479 |
|
480 _docommand_recursive = 0; |
|
481 _cmd_text = NULL; |
|
482 return false; |
|
483 } |
|
484 |
|
485 |
|
486 if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) { |
|
487 // first test if the command can be executed. |
|
488 res = proc(tile, flags, p1, p2); |
|
489 if (CmdFailed(res)) { |
|
490 if (res & 0xFFFF) _error_message = res & 0xFFFF; |
|
491 goto show_error; |
|
492 } |
|
493 // no money? Only check if notest is off |
|
494 if (!notest && res != 0 && !CheckPlayerHasMoney(res)) goto show_error; |
|
495 } |
|
496 |
|
497 #ifdef ENABLE_NETWORK |
|
498 /** If we are in network, and the command is not from the network |
|
499 * send it to the command-queue and abort execution |
|
500 * If we are a dedicated server temporarily switch local player, otherwise |
|
501 * the other parties won't be able to execute our command and will desync. |
|
502 * We also need to do this if the server's company has gone bankrupt |
|
503 * @todo Rewrite (dedicated) server to something more than a dirty hack! |
|
504 */ |
|
505 if (_networking && !(cmd & CMD_NETWORK_COMMAND)) { |
|
506 PlayerID pbck = _local_player; |
|
507 if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = 0; |
|
508 NetworkSend_Command(tile, p1, p2, cmd, callback); |
|
509 if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = pbck; |
|
510 _docommand_recursive = 0; |
|
511 _cmd_text = NULL; |
|
512 return true; |
|
513 } |
|
514 #endif /* ENABLE_NETWORK */ |
|
515 |
|
516 // update last build coordinate of player. |
|
517 if (tile != 0 && IsValidPlayer(_current_player)) { |
|
518 GetPlayer(_current_player)->last_build_coordinate = tile; |
|
519 } |
|
520 |
|
521 /* Actually try and execute the command. If no cost-type is given |
|
522 * use the construction one */ |
|
523 _yearly_expenses_type = EXPENSES_CONSTRUCTION; |
|
524 res2 = proc(tile, flags | DC_EXEC, p1, p2); |
|
525 |
|
526 // If notest is on, it means the result of the test can be different than |
|
527 // the real command.. so ignore the test |
|
528 if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) { |
|
529 assert(res == res2); // sanity check |
|
530 } else { |
|
531 if (CmdFailed(res2)) { |
|
532 if (res2 & 0xFFFF) _error_message = res2 & 0xFFFF; |
|
533 goto show_error; |
|
534 } |
|
535 } |
|
536 |
|
537 SubtractMoneyFromPlayer(res2); |
|
538 |
|
539 if (IsLocalPlayer() && _game_mode != GM_EDITOR) { |
|
540 if (res2 != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2); |
|
541 if (_additional_cash_required) { |
|
542 SetDParam(0, _additional_cash_required); |
|
543 ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, error_part1, x,y); |
|
544 if (res2 == 0) goto callb_err; |
|
545 } |
|
546 } |
|
547 |
|
548 _docommand_recursive = 0; |
|
549 |
|
550 if (callback) callback(true, tile, p1, p2); |
|
551 _cmd_text = NULL; |
|
552 return true; |
|
553 |
|
554 show_error: |
|
555 // show error message if the command fails? |
|
556 if (IsLocalPlayer() && error_part1 != 0) { |
|
557 ShowErrorMessage(_error_message, error_part1, x,y); |
|
558 } |
|
559 |
|
560 callb_err: |
|
561 _docommand_recursive = 0; |
|
562 |
|
563 if (callback) callback(false, tile, p1, p2); |
|
564 _cmd_text = NULL; |
|
565 return false; |
|
566 } |