1 //       _________ __                 __
2 //      /   _____//  |_____________ _/  |______     ____  __ __  ______
3 //      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
4 //      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ |
5 //     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
6 //             \/                  \/          \//_____/            \/
7 //  ______________________                           ______________________
8 //                        T H E   W A R   B E G I N S
9 //         Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name commands.cpp - Global command handler - network support. */
12 //
13 //      (c) Copyright 2000-2007 by Lutz Sammer, Andreas Arens, and Jimmy Salmon.
14 //
15 //      This program is free software; you can redistribute it and/or modify
16 //      it under the terms of the GNU General Public License as published by
17 //      the Free Software Foundation; only version 2 of the License.
18 //
19 //      This program is distributed in the hope that it will be useful,
20 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //      GNU General Public License for more details.
23 //
24 //      You should have received a copy of the GNU General Public License
25 //      along with this program; if not, write to the Free Software
26 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 //      02111-1307, USA.
28 //
29 
30 //@{
31 
32 /*----------------------------------------------------------------------------
33 --  Includes
34 ----------------------------------------------------------------------------*/
35 
36 #include "stratagus.h"
37 
38 #include "commands.h"
39 
40 #include "actions.h"
41 //Wyrmgus start
42 #include "map/map.h" //it contains map width and height
43 //Wyrmgus end
44 #include "net_message.h"
45 #include "network.h"
46 //Wyrmgus start
47 #include "quest.h"
48 //Wyrmgus end
49 #include "replay.h"
50 #include "spells.h"
51 #include "unit/unit.h"
52 #include "unit/unit_manager.h"
53 #include "unit/unittype.h"
54 
55  /*----------------------------------------------------------------------------
56 --  Functions
57 ----------------------------------------------------------------------------*/
58 
59 /**
60 ** Send command: Unit stop.
61 **
62 ** @param unit pointer to unit.
63 */
SendCommandStopUnit(CUnit & unit)64 void SendCommandStopUnit(CUnit &unit)
65 {
66 	if (!IsNetworkGame()) {
67 		CommandLog("stop", &unit, FlushCommands, -1, -1, NoUnitP, nullptr, -1);
68 		CommandStopUnit(unit);
69 	} else {
70 		NetworkSendCommand(MessageCommandStop, unit, 0, 0, NoUnitP, 0, FlushCommands);
71 	}
72 }
73 
74 /**
75 ** Send command: Unit stand ground.
76 **
77 ** @param unit     pointer to unit.
78 ** @param flush    Flag flush all pending commands.
79 */
SendCommandStandGround(CUnit & unit,int flush)80 void SendCommandStandGround(CUnit &unit, int flush)
81 {
82 	if (!IsNetworkGame()) {
83 		CommandLog("stand-ground", &unit, flush, -1, -1, NoUnitP, nullptr, -1);
84 		CommandStandGround(unit, flush);
85 	} else {
86 		NetworkSendCommand(MessageCommandStand, unit, 0, 0, NoUnitP, 0, flush);
87 	}
88 }
89 
90 /**
91 ** Send command: Defend some unit.
92 **
93 ** @param unit    pointer to unit.
94 ** @param dest    defend this unit.
95 ** @param flush   Flag flush all pending commands.
96 */
SendCommandDefend(CUnit & unit,CUnit & dest,int flush)97 void SendCommandDefend(CUnit &unit, CUnit &dest, int flush)
98 {
99 	if (!IsNetworkGame()) {
100 		CommandLog("defend", &unit, flush, -1, -1, &dest, nullptr, -1);
101 		CommandDefend(unit, dest, flush);
102 	} else {
103 		NetworkSendCommand(MessageCommandDefend, unit, 0, 0, &dest, 0, flush);
104 	}
105 }
106 
107 /**
108 ** Send command: Follow unit to position.
109 **
110 ** @param unit    pointer to unit.
111 ** @param dest    follow this unit.
112 ** @param flush   Flag flush all pending commands.
113 */
SendCommandFollow(CUnit & unit,CUnit & dest,int flush)114 void SendCommandFollow(CUnit &unit, CUnit &dest, int flush)
115 {
116 	if (!IsNetworkGame()) {
117 		CommandLog("follow", &unit, flush, -1, -1, &dest, nullptr, -1);
118 		CommandFollow(unit, dest, flush);
119 	} else {
120 		NetworkSendCommand(MessageCommandFollow, unit, 0, 0, &dest, 0, flush);
121 	}
122 }
123 
124 /**
125 ** Send command: Move unit to position.
126 **
127 ** @param unit    pointer to unit.
128 ** @param pos     map tile position to move to.
129 ** @param flush   Flag flush all pending commands.
130 */
131 //Wyrmgus start
132 //void SendCommandMove(CUnit &unit, const Vec2i &pos, int flush)
SendCommandMove(CUnit & unit,const Vec2i & pos,int flush,int z)133 void SendCommandMove(CUnit &unit, const Vec2i &pos, int flush, int z)
134 //Wyrmgus end
135 {
136 	if (!IsNetworkGame()) {
137 		CommandLog("move", &unit, flush, pos.x, pos.y, NoUnitP, nullptr, -1);
138 		//Wyrmgus start
139 //		CommandMove(unit, pos, flush);
140 		CommandMove(unit, pos, flush, z);
141 		//Wyrmgus end
142 	} else {
143 		NetworkSendCommand(MessageCommandMove, unit, pos.x, pos.y, NoUnitP, 0, flush);
144 	}
145 }
146 
147 //Wyrmgus start
148 /**
149 ** Send command: Set new rally point for unit.
150 **
151 ** @param unit    pointer to unit.
152 ** @param pos     map tile position to move to.
153 */
SendCommandRallyPoint(CUnit & unit,const Vec2i & pos,int z)154 void SendCommandRallyPoint(CUnit &unit, const Vec2i &pos, int z)
155 {
156 	if (!IsNetworkGame()) {
157 		CommandLog("rally-point", &unit, 0, pos.x, pos.y, NoUnitP, nullptr, -1);
158 		CommandRallyPoint(unit, pos, z);
159 	} else {
160 		NetworkSendCommand(MessageCommandMove, unit, pos.x, pos.y, NoUnitP, 0, 0);
161 	}
162 }
163 
164 /**
165 ** Send command: Accept new quest for the unit's player.
166 **
167 ** @param unit    pointer to unit.
168 ** @param pos     map tile position to move to.
169 */
SendCommandQuest(CUnit & unit,CQuest * quest)170 void SendCommandQuest(CUnit &unit, CQuest *quest)
171 {
172 	if (!IsNetworkGame()) {
173 		CommandLog("quest", &unit, 0, 0, 0, NoUnitP, quest->Ident.c_str(), -1);
174 		CommandQuest(unit, quest);
175 	} else {
176 		NetworkSendCommand(MessageCommandQuest, unit, quest->ID, 0, NoUnitP, nullptr, 0);
177 	}
178 }
179 
180 /**
181 ** Send command: Buy an item from a building.
182 **
183 ** @param unit    pointer to unit.
184 ** @param pos     map tile position to move to.
185 */
SendCommandBuy(CUnit & unit,CUnit * sold_unit,int player)186 void SendCommandBuy(CUnit &unit, CUnit *sold_unit, int player)
187 {
188 	if (!IsNetworkGame()) {
189 		CommandLog("buy", &unit, 0, -1, -1, sold_unit, nullptr, player);
190 		CommandBuy(unit, sold_unit, player);
191 	} else {
192 		NetworkSendCommand(MessageCommandBuy, unit, player, 0, sold_unit, 0, 0);
193 	}
194 }
195 
196 /**
197 ** Send command: Produce a resource.
198 */
SendCommandProduceResource(CUnit & unit,int resource)199 void SendCommandProduceResource(CUnit &unit, int resource)
200 {
201 	if (!IsNetworkGame()) {
202 		CommandLog("produce-resource", &unit, 0, 0, -1, NoUnitP, nullptr, resource);
203 		CommandProduceResource(unit, resource);
204 	} else {
205 		NetworkSendCommand(MessageCommandProduceResource, unit, resource, 0, NoUnitP, nullptr, 0);
206 	}
207 }
208 
209 /**
210 ** Send command: Sell a resource for copper.
211 */
SendCommandSellResource(CUnit & unit,int resource,int player)212 void SendCommandSellResource(CUnit &unit, int resource, int player)
213 {
214 	if (!IsNetworkGame()) {
215 		CommandLog("sell-resource", &unit, 0, resource, -1, NoUnitP, nullptr, player);
216 		CommandSellResource(unit, resource, player);
217 	} else {
218 		NetworkSendCommand(MessageCommandSellResource, unit, resource, player, NoUnitP, nullptr, 0);
219 	}
220 }
221 
222 /**
223 ** Send command: Buy a resource with copper.
224 */
SendCommandBuyResource(CUnit & unit,int resource,int player)225 void SendCommandBuyResource(CUnit &unit, int resource, int player)
226 {
227 	if (!IsNetworkGame()) {
228 		CommandLog("buy-resource", &unit, 0, resource, -1, NoUnitP, nullptr, player);
229 		CommandBuyResource(unit, resource, player);
230 	} else {
231 		NetworkSendCommand(MessageCommandBuyResource, unit, resource, player, NoUnitP, nullptr, 0);
232 	}
233 }
234 
235 /**
236 ** Send command: Pick up item.
237 **
238 ** @param unit    pointer to unit.
239 ** @param dest    pick up this item.
240 ** @param flush   Flag flush all pending commands.
241 */
SendCommandPickUp(CUnit & unit,CUnit & dest,int flush)242 void SendCommandPickUp(CUnit &unit, CUnit &dest, int flush)
243 {
244 	if (!IsNetworkGame()) {
245 		CommandLog("pick-up", &unit, flush, -1, -1, &dest, nullptr, -1);
246 		CommandPickUp(unit, dest, flush);
247 	} else {
248 		NetworkSendCommand(MessageCommandPickUp, unit, 0, 0, &dest, 0, flush);
249 	}
250 }
251 //Wyrmgus end
252 
253 /**
254 ** Send command: Unit repair.
255 **
256 ** @param unit    Pointer to unit.
257 ** @param pos     map tile position to repair.
258 ** @param dest    Unit to be repaired.
259 ** @param flush   Flag flush all pending commands.
260 */
261 //Wyrmgus start
262 //void SendCommandRepair(CUnit &unit, const Vec2i &pos, CUnit *dest, int flush)
SendCommandRepair(CUnit & unit,const Vec2i & pos,CUnit * dest,int flush,int z)263 void SendCommandRepair(CUnit &unit, const Vec2i &pos, CUnit *dest, int flush, int z)
264 //Wyrmgus end
265 {
266 	if (!IsNetworkGame()) {
267 		CommandLog("repair", &unit, flush, pos.x, pos.y, dest, nullptr, -1);
268 		//Wyrmgus start
269 //		CommandRepair(unit, pos, dest, flush);
270 		CommandRepair(unit, pos, dest, flush, z);
271 		//Wyrmgus end
272 	} else {
273 		NetworkSendCommand(MessageCommandRepair, unit, pos.x, pos.y, dest, 0, flush);
274 	}
275 }
276 
277 /**
278 ** Send command: Unit auto repair.
279 **
280 ** @param unit      pointer to unit.
281 ** @param on        1 for auto repair on, 0 for off.
282 */
SendCommandAutoRepair(CUnit & unit,int on)283 void SendCommandAutoRepair(CUnit &unit, int on)
284 {
285 	if (!IsNetworkGame()) {
286 		CommandLog("auto-repair", &unit, FlushCommands, on, -1, NoUnitP, nullptr, 0);
287 		CommandAutoRepair(unit, on);
288 	} else {
289 		NetworkSendCommand(MessageCommandAutoRepair, unit, on, -1, NoUnitP, nullptr, FlushCommands);
290 	}
291 }
292 
293 /**
294 ** Send command: Unit attack unit or at position.
295 **
296 ** @param unit     pointer to unit.
297 ** @param pos      map tile position to attack.
298 ** @param attack   or !=NoUnitP unit to be attacked.
299 ** @param flush    Flag flush all pending commands.
300 */
301 //Wyrmgus start
302 //void SendCommandAttack(CUnit &unit, const Vec2i &pos, CUnit *attack, int flush)
SendCommandAttack(CUnit & unit,const Vec2i & pos,CUnit * attack,int flush,int z)303 void SendCommandAttack(CUnit &unit, const Vec2i &pos, CUnit *attack, int flush, int z)
304 //Wyrmgus end
305 {
306 	if (!IsNetworkGame()) {
307 		CommandLog("attack", &unit, flush, pos.x, pos.y, attack, nullptr, -1);
308 		//Wyrmgus start
309 //		CommandAttack(unit, pos, attack, flush);
310 		CommandAttack(unit, pos, attack, flush, z);
311 		//Wyrmgus end
312 	} else {
313 		NetworkSendCommand(MessageCommandAttack, unit, pos.x, pos.y, attack, 0, flush);
314 	}
315 }
316 
317 /**
318 ** Send command: Unit attack ground.
319 **
320 ** @param unit     pointer to unit.
321 ** @param pos      map tile position to fire on.
322 ** @param flush    Flag flush all pending commands.
323 */
324 //Wyrmgus start
325 //void SendCommandAttackGround(CUnit &unit, const Vec2i &pos, int flush)
SendCommandAttackGround(CUnit & unit,const Vec2i & pos,int flush,int z)326 void SendCommandAttackGround(CUnit &unit, const Vec2i &pos, int flush, int z)
327 //Wyrmgus end
328 {
329 	if (!IsNetworkGame()) {
330 		CommandLog("attack-ground", &unit, flush, pos.x, pos.y, NoUnitP, nullptr, -1);
331 		//Wyrmgus start
332 //		CommandAttackGround(unit, pos, flush);
333 		CommandAttackGround(unit, pos, flush, z);
334 		//Wyrmgus end
335 	} else {
336 		NetworkSendCommand(MessageCommandGround, unit, pos.x, pos.y, NoUnitP, 0, flush);
337 	}
338 }
339 
340 //Wyrmgus start
341 /**
342 ** Send command: Use a unit.
343 **
344 ** @param unit    pointer to unit.
345 ** @param dest    use this unit.
346 ** @param flush   Flag flush all pending commands.
347 */
SendCommandUse(CUnit & unit,CUnit & dest,int flush)348 void SendCommandUse(CUnit &unit, CUnit &dest, int flush)
349 {
350 	if (!IsNetworkGame()) {
351 		CommandLog("use", &unit, flush, -1, -1, &dest, nullptr, -1);
352 		CommandUse(unit, dest, flush);
353 	} else {
354 		NetworkSendCommand(MessageCommandUse, unit, 0, 0, &dest, 0, flush);
355 	}
356 }
357 
358 /**
359 ** Send command: Trade with a unit.
360 **
361 ** @param unit    pointer to unit.
362 ** @param dest    trade with this unit.
363 ** @param flush   Flag flush all pending commands.
364 */
SendCommandTrade(CUnit & unit,CUnit & dest,int flush)365 void SendCommandTrade(CUnit &unit, CUnit &dest, int flush)
366 {
367 	if (!IsNetworkGame()) {
368 		CommandLog("use", &unit, flush, -1, -1, &dest, nullptr, -1);
369 		CommandTrade(unit, dest, flush);
370 	} else {
371 		NetworkSendCommand(MessageCommandTrade, unit, 0, 0, &dest, 0, flush);
372 	}
373 }
374 //Wyrmgus end
375 
376 /**
377 ** Send command: Unit patrol between current and position.
378 **
379 ** @param unit     pointer to unit.
380 ** @param pos      map tile position to patrol between.
381 ** @param flush    Flag flush all pending commands.
382 */
383 //Wyrmgus start
384 //void SendCommandPatrol(CUnit &unit, const Vec2i &pos, int flush)
SendCommandPatrol(CUnit & unit,const Vec2i & pos,int flush,int z)385 void SendCommandPatrol(CUnit &unit, const Vec2i &pos, int flush, int z)
386 //Wyrmgus end
387 {
388 	if (!IsNetworkGame()) {
389 		CommandLog("patrol", &unit, flush, pos.x, pos.y, NoUnitP, nullptr, -1);
390 		//Wyrmgus start
391 //		CommandPatrolUnit(unit, pos, flush);
392 		CommandPatrolUnit(unit, pos, flush, z);
393 		//Wyrmgus end
394 	} else {
395 		NetworkSendCommand(MessageCommandPatrol, unit, pos.x, pos.y, NoUnitP, 0, flush);
396 	}
397 }
398 
399 /**
400 ** Send command: Unit board unit.
401 **
402 ** @param unit     pointer to unit.
403 ** @param dest     Destination to be boarded.
404 ** @param flush    Flag flush all pending commands.
405 */
SendCommandBoard(CUnit & unit,CUnit & dest,int flush)406 void SendCommandBoard(CUnit &unit, CUnit &dest, int flush)
407 {
408 	if (!IsNetworkGame()) {
409 		CommandLog("board", &unit, flush, -1, -1, &dest, nullptr, -1);
410 		CommandBoard(unit, dest, flush);
411 	} else {
412 		NetworkSendCommand(MessageCommandBoard, unit, -1, -1, &dest, 0, flush);
413 	}
414 }
415 
416 /**
417 ** Send command: Unit unload unit.
418 **
419 ** @param unit    pointer to unit.
420 ** @param pos     map tile position of unload.
421 ** @param what    Passagier to be unloaded.
422 ** @param flush   Flag flush all pending commands.
423 */
424 //Wyrmgus start
425 //void SendCommandUnload(CUnit &unit, const Vec2i &pos, CUnit *what, int flush)
SendCommandUnload(CUnit & unit,const Vec2i & pos,CUnit * what,int flush,int z)426 void SendCommandUnload(CUnit &unit, const Vec2i &pos, CUnit *what, int flush, int z)
427 //Wyrmgus end
428 {
429 	if (!IsNetworkGame()) {
430 		CommandLog("unload", &unit, flush, pos.x, pos.y, what, nullptr, -1);
431 		//Wyrmgus start
432 //		CommandUnload(unit, pos, what, flush);
433 		CommandUnload(unit, pos, what, flush, z);
434 		//Wyrmgus end
435 	} else {
436 		NetworkSendCommand(MessageCommandUnload, unit, pos.x, pos.y, what, 0, flush);
437 	}
438 }
439 
440 /**
441 ** Send command: Unit builds building at position.
442 **
443 ** @param unit    pointer to unit.
444 ** @param pos     map tile position of construction.
445 ** @param what    pointer to unit-type of the building.
446 ** @param flush   Flag flush all pending commands.
447 */
448 //Wyrmgus start
449 //void SendCommandBuildBuilding(CUnit &unit, const Vec2i &pos, CUnitType &what, int flush)
SendCommandBuildBuilding(CUnit & unit,const Vec2i & pos,CUnitType & what,int flush,int z)450 void SendCommandBuildBuilding(CUnit &unit, const Vec2i &pos, CUnitType &what, int flush, int z)
451 //Wyrmgus end
452 {
453 	if (!IsNetworkGame()) {
454 		CommandLog("build", &unit, flush, pos.x, pos.y, NoUnitP, what.Ident.c_str(), -1);
455 		//Wyrmgus start
456 //		CommandBuildBuilding(unit, pos, what, flush);
457 		CommandBuildBuilding(unit, pos, what, flush, z);
458 		//Wyrmgus end
459 	} else {
460 		NetworkSendCommand(MessageCommandBuild, unit, pos.x, pos.y, NoUnitP, &what, flush);
461 	}
462 }
463 
464 /**
465 **  Send command: Cancel this building construction.
466 **
467 **  @param unit  pointer to unit.
468 */
SendCommandDismiss(CUnit & unit,bool salvage)469 void SendCommandDismiss(CUnit &unit, bool salvage)
470 {
471 	// FIXME: currently unit and worker are same?
472 	if (!IsNetworkGame()) {
473 		CommandLog("dismiss", &unit, FlushCommands, -1, -1, nullptr, nullptr, -1);
474 		CommandDismiss(unit, salvage);
475 	} else {
476 		NetworkSendCommand(MessageCommandDismiss, unit, salvage, 0, nullptr, 0, FlushCommands);
477 	}
478 }
479 
480 /**
481 **  Send command: Unit harvests a location (wood for now).
482 **
483 ** @param unit     pointer to unit.
484 ** @param pos      map tile position where to harvest.
485 ** @param flush    Flag flush all pending commands.
486 */
487 //Wyrmgus start
488 //void SendCommandResourceLoc(CUnit &unit, const Vec2i &pos, int flush)
SendCommandResourceLoc(CUnit & unit,const Vec2i & pos,int flush,int z)489 void SendCommandResourceLoc(CUnit &unit, const Vec2i &pos, int flush, int z)
490 //Wyrmgus end
491 {
492 	if (!IsNetworkGame()) {
493 		CommandLog("resource-loc", &unit, flush, pos.x, pos.y, NoUnitP, nullptr, -1);
494 		//Wyrmgus start
495 //		CommandResourceLoc(unit, pos, flush);
496 		CommandResourceLoc(unit, pos, flush, z);
497 		//Wyrmgus end
498 	} else {
499 		NetworkSendCommand(MessageCommandResourceLoc, unit, pos.x, pos.y, NoUnitP, 0, flush);
500 	}
501 }
502 
503 /**
504 ** Send command: Unit harvest resources
505 **
506 ** @param unit    pointer to unit.
507 ** @param dest    pointer to destination (oil-platform,gold mine).
508 ** @param flush   Flag flush all pending commands.
509 */
SendCommandResource(CUnit & unit,CUnit & dest,int flush)510 void SendCommandResource(CUnit &unit, CUnit &dest, int flush)
511 {
512 	if (!IsNetworkGame()) {
513 		CommandLog("resource", &unit, flush, -1, -1, &dest, nullptr, -1);
514 		CommandResource(unit, dest, flush);
515 	} else {
516 		NetworkSendCommand(MessageCommandResource, unit, 0, 0, &dest, 0, flush);
517 	}
518 }
519 
520 /**
521 ** Send command: Unit return goods.
522 **
523 ** @param unit    pointer to unit.
524 ** @param goal    pointer to destination of the goods. (null=search best)
525 ** @param flush   Flag flush all pending commands.
526 */
SendCommandReturnGoods(CUnit & unit,CUnit * goal,int flush)527 void SendCommandReturnGoods(CUnit &unit, CUnit *goal, int flush)
528 {
529 	if (!IsNetworkGame()) {
530 		CommandLog("return", &unit, flush, -1, -1, goal, nullptr, -1);
531 		CommandReturnGoods(unit, goal, flush);
532 	} else {
533 		NetworkSendCommand(MessageCommandReturn, unit, 0, 0, goal, 0, flush);
534 	}
535 }
536 
537 /**
538 ** Send command: Building/unit train new unit.
539 **
540 ** @param unit    pointer to unit.
541 ** @param what    pointer to unit-type of the unit to be trained.
542 ** @param flush   Flag flush all pending commands.
543 */
544 //Wyrmgus start
545 //void SendCommandTrainUnit(CUnit &unit, CUnitType &what, int flush)
SendCommandTrainUnit(CUnit & unit,CUnitType & what,int player,int flush)546 void SendCommandTrainUnit(CUnit &unit, CUnitType &what, int player, int flush)
547 //Wyrmgus end
548 {
549 	if (!IsNetworkGame()) {
550 		//Wyrmgus start
551 //		CommandLog("train", &unit, flush, -1, -1, NoUnitP, what.Ident.c_str(), -1);
552 //		CommandTrainUnit(unit, what, flush);
553 		CommandLog("train", &unit, flush, -1, -1, NoUnitP, what.Ident.c_str(), player);
554 		CommandTrainUnit(unit, what, player, flush);
555 		//Wyrmgus end
556 	} else {
557 		//Wyrmgus start
558 //		NetworkSendCommand(MessageCommandTrain, unit, 0, 0, NoUnitP, &what, flush);
559 		NetworkSendCommand(MessageCommandTrain, unit, player, 0, NoUnitP, &what, flush);
560 		//Wyrmgus end
561 	}
562 }
563 
564 /**
565 ** Send command: Cancel training.
566 **
567 ** @param unit    Pointer to unit.
568 ** @param slot    Slot of training queue to cancel.
569 ** @param type    Unit-type of unit to cancel.
570 */
SendCommandCancelTraining(CUnit & unit,int slot,const CUnitType * type)571 void SendCommandCancelTraining(CUnit &unit, int slot, const CUnitType *type)
572 {
573 	if (!IsNetworkGame()) {
574 		CommandLog("cancel-train", &unit, FlushCommands, -1, -1, NoUnitP,
575 				   type ? type->Ident.c_str() : nullptr, slot);
576 		CommandCancelTraining(unit, slot, type);
577 	} else {
578 		NetworkSendCommand(MessageCommandCancelTrain, unit, slot, 0, NoUnitP,
579 						   type, FlushCommands);
580 	}
581 }
582 
583 /**
584 ** Send command: Building starts upgrading to.
585 **
586 ** @param unit     pointer to unit.
587 ** @param what     pointer to unit-type of the unit upgrade.
588 ** @param flush    Flag flush all pending commands.
589 */
SendCommandUpgradeTo(CUnit & unit,CUnitType & what,int flush)590 void SendCommandUpgradeTo(CUnit &unit, CUnitType &what, int flush)
591 {
592 	if (!IsNetworkGame()) {
593 		CommandLog("upgrade-to", &unit, flush, -1, -1, NoUnitP, what.Ident.c_str(), -1);
594 		CommandUpgradeTo(unit, what, flush);
595 	} else {
596 		NetworkSendCommand(MessageCommandUpgrade, unit, 0, 0, NoUnitP, &what, flush);
597 	}
598 }
599 
600 /**
601 ** Send command: Cancel building upgrading to.
602 **
603 ** @param unit  Pointer to unit.
604 */
SendCommandCancelUpgradeTo(CUnit & unit)605 void SendCommandCancelUpgradeTo(CUnit &unit)
606 {
607 	if (!IsNetworkGame()) {
608 		CommandLog("cancel-upgrade-to", &unit, FlushCommands, -1, -1, NoUnitP, nullptr, -1);
609 		CommandCancelUpgradeTo(unit);
610 	} else {
611 		NetworkSendCommand(MessageCommandCancelUpgrade, unit,
612 						   0, 0, NoUnitP, nullptr, FlushCommands);
613 	}
614 }
615 
616 //Wyrmgus start
617 /**
618 ** Send command: Unit starts upgrading to.
619 **
620 ** @param unit     pointer to unit.
621 ** @param what     pointer to unit-type of the unit upgrade.
622 ** @param flush    Flag flush all pending commands.
623 */
SendCommandTransformInto(CUnit & unit,CUnitType & what,int flush)624 void SendCommandTransformInto(CUnit &unit, CUnitType &what, int flush)
625 {
626 	if (!IsNetworkGame()) {
627 		CommandLog("transform-into", &unit, flush, -1, -1, NoUnitP, what.Ident.c_str(), -1);
628 		CommandTransformIntoType(unit, what);
629 	} else {
630 		NetworkSendCommand(MessageCommandUpgrade, unit, 2, 0, NoUnitP, &what, flush); //use X as a way to mark that this is a transformation and not an upgrade
631 	}
632 }
633 //Wyrmgus end
634 
635 /**
636 ** Send command: Building/unit research.
637 **
638 ** @param unit     pointer to unit.
639 ** @param what     research-type of the research.
640 ** @param flush    Flag flush all pending commands.
641 */
642 //Wyrmgus start
643 //void SendCommandResearch(CUnit &unit, CUpgrade &what, int flush)
SendCommandResearch(CUnit & unit,CUpgrade & what,int player,int flush)644 void SendCommandResearch(CUnit &unit, CUpgrade &what, int player, int flush)
645 //Wyrmgus end
646 {
647 	if (!IsNetworkGame()) {
648 		//Wyrmgus start
649 //		CommandLog("research", &unit, flush, -1, -1, NoUnitP, what.Ident.c_str(), -1);
650 //		CommandResearch(unit, what, flush);
651 		CommandLog("research", &unit, flush, -1, -1, NoUnitP, what.Ident.c_str(), player);
652 		CommandResearch(unit, what, player, flush);
653 		//Wyrmgus end
654 	} else {
655 		NetworkSendCommand(MessageCommandResearch, unit,
656 						   //Wyrmgus start
657 //						   what.ID, 0, NoUnitP, nullptr, flush);
658 						   what.ID, player, NoUnitP, nullptr, flush);
659 						   //Wyrmgus end
660 	}
661 }
662 
663 /**
664 ** Send command: Cancel Building/unit research.
665 **
666 ** @param unit pointer to unit.
667 */
SendCommandCancelResearch(CUnit & unit)668 void SendCommandCancelResearch(CUnit &unit)
669 {
670 	if (!IsNetworkGame()) {
671 		CommandLog("cancel-research", &unit, FlushCommands, -1, -1, NoUnitP, nullptr, -1);
672 		CommandCancelResearch(unit);
673 	} else {
674 		NetworkSendCommand(MessageCommandCancelResearch, unit,
675 						   0, 0, NoUnitP, nullptr, FlushCommands);
676 	}
677 }
678 
679 //Wyrmgus start
680 /**
681 ** Send command: Unit learn ability.
682 **
683 ** @param unit     pointer to unit.
684 ** @param what     upgrade-type of the ability.
685 */
SendCommandLearnAbility(CUnit & unit,CUpgrade & what)686 void SendCommandLearnAbility(CUnit &unit, CUpgrade &what)
687 {
688 	if (!IsNetworkGame()) {
689 		CommandLog("learn-ability", &unit, 0, -1, -1, NoUnitP, what.Ident.c_str(), -1);
690 		CommandLearnAbility(unit, what);
691 	} else {
692 		NetworkSendCommand(MessageCommandLearnAbility, unit,
693 						   what.ID, 0, NoUnitP, nullptr, 0);
694 	}
695 }
696 //Wyrmgus end
697 
698 /**
699 ** Send command: Unit spell cast on position/unit.
700 **
701 ** @param unit      pointer to unit.
702 ** @param pos       map tile position where to cast spell.
703 ** @param dest      Cast spell on unit (if exist).
704 ** @param spellid   Spell type id.
705 ** @param flush     Flag flush all pending commands.
706 */
SendCommandSpellCast(CUnit & unit,const Vec2i & pos,CUnit * dest,int spellid,int flush,int z)707 void SendCommandSpellCast(CUnit &unit, const Vec2i &pos, CUnit *dest, int spellid, int flush, int z)
708 {
709 	if (!IsNetworkGame()) {
710 		CommandLog("spell-cast", &unit, flush, pos.x, pos.y, dest, nullptr, spellid);
711 		CommandSpellCast(unit, pos, dest, *CSpell::Spells[spellid], flush, z);
712 	} else {
713 		NetworkSendCommand(MessageCommandSpellCast + spellid,
714 						   unit, pos.x, pos.y, dest, nullptr, flush);
715 	}
716 }
717 
718 /**
719 ** Send command: Unit auto spell cast.
720 **
721 ** @param unit      pointer to unit.
722 ** @param spellid   Spell type id.
723 ** @param on        1 for auto cast on, 0 for off.
724 */
SendCommandAutoSpellCast(CUnit & unit,int spellid,int on)725 void SendCommandAutoSpellCast(CUnit &unit, int spellid, int on)
726 {
727 	if (!IsNetworkGame()) {
728 		CommandLog("auto-spell-cast", &unit, FlushCommands, on, -1, NoUnitP, nullptr, spellid);
729 		CommandAutoSpellCast(unit, spellid, on);
730 	} else {
731 		NetworkSendCommand(MessageCommandSpellCast + spellid,
732 						   unit, on, -1, NoUnitP, nullptr, FlushCommands);
733 	}
734 }
735 
736 /**
737 ** Send command: Diplomacy changed.
738 **
739 ** @param player     Player which changes his state.
740 ** @param state      New diplomacy state.
741 ** @param opponent   Opponent.
742 */
SendCommandDiplomacy(int player,int state,int opponent)743 void SendCommandDiplomacy(int player, int state, int opponent)
744 {
745 	if (!IsNetworkGame()) {
746 		switch (state) {
747 			case DiplomacyNeutral:
748 				CommandLog("diplomacy", NoUnitP, 0, player, opponent,
749 						   NoUnitP, "neutral", -1);
750 				break;
751 			case DiplomacyAllied:
752 				CommandLog("diplomacy", NoUnitP, 0, player, opponent,
753 						   NoUnitP, "allied", -1);
754 				break;
755 			case DiplomacyEnemy:
756 				CommandLog("diplomacy", NoUnitP, 0, player, opponent,
757 						   NoUnitP, "enemy", -1);
758 				break;
759 			//Wyrmgus start
760 			case DiplomacyOverlord:
761 				CommandLog("diplomacy", NoUnitP, 0, player, opponent,
762 						   NoUnitP, "overlord", -1);
763 				break;
764 			case DiplomacyVassal:
765 				CommandLog("diplomacy", NoUnitP, 0, player, opponent,
766 						   NoUnitP, "vassal", -1);
767 				break;
768 			//Wyrmgus end
769 			case DiplomacyCrazy:
770 				CommandLog("diplomacy", NoUnitP, 0, player, opponent,
771 						   NoUnitP, "crazy", -1);
772 				break;
773 		}
774 		CommandDiplomacy(player, state, opponent);
775 	} else {
776 		NetworkSendExtendedCommand(ExtendedMessageDiplomacy,
777 								   -1, player, state, opponent, 0);
778 	}
779 }
780 
781 /**
782 ** Send command: Shared vision changed.
783 **
784 ** @param player     Player which changes his state.
785 ** @param state      New shared vision state.
786 ** @param opponent   Opponent.
787 */
SendCommandSharedVision(int player,bool state,int opponent)788 void SendCommandSharedVision(int player, bool state, int opponent)
789 {
790 	if (!IsNetworkGame()) {
791 		if (state == false) {
792 			CommandLog("shared-vision", NoUnitP, 0, player, opponent,
793 					   NoUnitP, "0", -1);
794 		} else {
795 			CommandLog("shared-vision", NoUnitP, 0, player, opponent,
796 					   NoUnitP, "1", -1);
797 		}
798 		CommandSharedVision(player, state, opponent);
799 	} else {
800 		NetworkSendExtendedCommand(ExtendedMessageSharedVision,
801 								   -1, player, state, opponent, 0);
802 	}
803 }
804 
805 //Wyrmgus start
806 /**
807 ** Send command: Faction changed.
808 **
809 ** @param player     Player which changes his faction.
810 ** @param faction    New faction.
811 */
SendCommandSetFaction(int player,int faction)812 void SendCommandSetFaction(int player, int faction)
813 {
814 	if (!IsNetworkGame()) {
815 		//FIXME: should add log of faction change here
816 		if (faction != -1) {
817 			Players[player].SetFaction(PlayerRaces.Factions[faction]);
818 		} else {
819 			Players[player].SetFaction(nullptr);
820 		}
821 	} else {
822 		NetworkSendExtendedCommand(ExtendedMessageSetFaction, -1, player, faction, 0, 0);
823 	}
824 }
825 //Wyrmgus end
826 
827 /**
828 ** Send command: Toggle resource autosell.
829 **
830 ** @param player     Player which toggles the resource autosell.
831 ** @param resource   The resource.
832 */
SendCommandAutosellResource(int player,int resource)833 void SendCommandAutosellResource(int player, int resource)
834 {
835 	if (!IsNetworkGame()) {
836 		Players[player].AutosellResource(resource);
837 	} else {
838 		NetworkSendExtendedCommand(ExtendedMessageAutosellResource, -1, player, resource, 0, 0);
839 	}
840 }
841 
842 //@}
843 
844 //----------------------------------------------------------------------------
845 // Parse the message, from the network.
846 //----------------------------------------------------------------------------
847 
848 /**@name parse */
849 //@{
850 
851 /**
852 ** Execute a command (from network).
853 **
854 ** @param msgnr    Network message type
855 ** @param unum     Unit number (slot) that receive the command.
856 ** @param x        optional X map position.
857 ** @param y        optional y map position.
858 ** @param dstnr    optional destination unit.
859 */
ExecCommand(unsigned char msgnr,UnitRef unum,unsigned short x,unsigned short y,UnitRef dstnr)860 void ExecCommand(unsigned char msgnr, UnitRef unum,
861 				 unsigned short x, unsigned short y, UnitRef dstnr)
862 {
863 	CUnit &unit = UnitManager.GetSlotUnit(unum);
864 	const Vec2i pos(x, y);
865 	const int arg1 = x;
866 	const int arg2 = y;
867 	//
868 	// Check if unit is already killed?
869 	//
870 	if (unit.Destroyed) {
871 		DebugPrint(" destroyed unit skipping %d\n" _C_ UnitNumber(unit));
872 		return;
873 	}
874 	Assert(unit.Type);
875 
876 	const int status = (msgnr & 0x80) >> 7;
877 	// Note: destroyed destination unit is handled by the action routines.
878 
879 	switch (msgnr & 0x7F) {
880 		case MessageSync:
881 			return;
882 		case MessageQuit:
883 			return;
884 		case MessageChat:
885 			return;
886 
887 		case MessageCommandStop:
888 			CommandLog("stop", &unit, FlushCommands, -1, -1, NoUnitP, nullptr, -1);
889 			CommandStopUnit(unit);
890 			break;
891 		case MessageCommandStand:
892 			CommandLog("stand-ground", &unit, status, -1, -1, NoUnitP, nullptr, -1);
893 			CommandStandGround(unit, status);
894 			break;
895 		case MessageCommandDefend: {
896 			if (dstnr != (unsigned short)0xFFFF) {
897 				CUnit &dest = UnitManager.GetSlotUnit(dstnr);
898 				Assert(dest.Type);
899 				CommandLog("defend", &unit, status, -1, -1, &dest, nullptr, -1);
900 				CommandDefend(unit, dest, status);
901 			}
902 			break;
903 		}
904 		case MessageCommandFollow: {
905 			if (dstnr != (unsigned short)0xFFFF) {
906 				CUnit &dest = UnitManager.GetSlotUnit(dstnr);
907 				Assert(dest.Type);
908 				CommandLog("follow", &unit, status, -1, -1, &dest, nullptr, -1);
909 				CommandFollow(unit, dest, status);
910 			}
911 			break;
912 		}
913 		case MessageCommandMove:
914 			//Wyrmgus start
915 //			CommandLog("move", &unit, status, pos.x, pos.y, NoUnitP, nullptr, -1);
916 //			CommandMove(unit, pos, status);
917 			if (!unit.CanMove()) { //FIXME: find better way to identify whether the unit should move or set a rally point
918 				CommandLog("rally-point", &unit, status, pos.x, pos.y, NoUnitP, nullptr, -1);
919 				CommandRallyPoint(unit, pos);
920 			} else {
921 				CommandLog("move", &unit, status, pos.x, pos.y, NoUnitP, nullptr, -1);
922 				CommandMove(unit, pos, status);
923 			}
924 			//Wyrmgus end
925 			break;
926 		//Wyrmgus start
927 		case MessageCommandPickUp: {
928 			if (dstnr != (unsigned short)0xFFFF) {
929 				CUnit &dest = UnitManager.GetSlotUnit(dstnr);
930 				Assert(dest.Type);
931 				CommandLog("pick-up", &unit, status, -1, -1, &dest, nullptr, -1);
932 				CommandPickUp(unit, dest, status);
933 			}
934 			break;
935 		}
936 		//Wyrmgus end
937 		case MessageCommandRepair: {
938 			CUnit *dest = NoUnitP;
939 			if (dstnr != (unsigned short)0xFFFF) {
940 				dest = &UnitManager.GetSlotUnit(dstnr);
941 				Assert(dest && dest->Type);
942 			}
943 			CommandLog("repair", &unit, status, pos.x, pos.y, dest, nullptr, -1);
944 			CommandRepair(unit, pos, dest, status);
945 			break;
946 		}
947 		case MessageCommandAutoRepair:
948 			CommandLog("auto-repair", &unit, status, arg1, arg2, NoUnitP, nullptr, 0);
949 			CommandAutoRepair(unit, arg1);
950 			break;
951 		case MessageCommandAttack: {
952 			CUnit *dest = NoUnitP;
953 			if (dstnr != (unsigned short)0xFFFF) {
954 				dest = &UnitManager.GetSlotUnit(dstnr);
955 				Assert(dest && dest->Type);
956 			}
957 			CommandLog("attack", &unit, status, pos.x, pos.y, dest, nullptr, -1);
958 			CommandAttack(unit, pos, dest, status);
959 			break;
960 		}
961 		case MessageCommandGround:
962 			CommandLog("attack-ground", &unit, status, pos.x, pos.y, NoUnitP, nullptr, -1);
963 			CommandAttackGround(unit, pos, status);
964 			break;
965 		//Wyrmgus start
966 		case MessageCommandUse: {
967 			if (dstnr != (unsigned short)0xFFFF) {
968 				CUnit &dest = UnitManager.GetSlotUnit(dstnr);
969 				Assert(dest.Type);
970 				CommandLog("use", &unit, status, -1, -1, &dest, nullptr, -1);
971 				CommandUse(unit, dest, status);
972 			}
973 			break;
974 		}
975 		case MessageCommandTrade: {
976 			if (dstnr != (unsigned short)0xFFFF) {
977 				CUnit &dest = UnitManager.GetSlotUnit(dstnr);
978 				Assert(dest.Type);
979 				CommandLog("trade", &unit, status, -1, -1, &dest, nullptr, -1);
980 				CommandTrade(unit, dest, status);
981 			}
982 			break;
983 		}
984 		//Wyrmgus end
985 		case MessageCommandPatrol:
986 			CommandLog("patrol", &unit, status, pos.x, pos.y, NoUnitP, nullptr, -1);
987 			CommandPatrolUnit(unit, pos, status);
988 			break;
989 		case MessageCommandBoard: {
990 			if (dstnr != (unsigned short)0xFFFF) {
991 				CUnit &dest = UnitManager.GetSlotUnit(dstnr);
992 				Assert(dest.Type);
993 				CommandLog("board", &unit, status, arg1, arg2, &dest, nullptr, -1);
994 				CommandBoard(unit, dest, status);
995 			}
996 			break;
997 		}
998 		case MessageCommandUnload: {
999 			CUnit *dest = nullptr;
1000 			if (dstnr != (unsigned short)0xFFFF) {
1001 				dest = &UnitManager.GetSlotUnit(dstnr);
1002 				Assert(dest && dest->Type);
1003 			}
1004 			CommandLog("unload", &unit, status, pos.x, pos.y, dest, nullptr, -1);
1005 			CommandUnload(unit, pos, dest, status);
1006 			break;
1007 		}
1008 		case MessageCommandBuild:
1009 			CommandLog("build", &unit, status, pos.x, pos.y, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1);
1010 			CommandBuildBuilding(unit, pos, *UnitTypes[dstnr], status);
1011 			break;
1012 		case MessageCommandDismiss:
1013 			CommandLog("dismiss", &unit, FlushCommands, arg1, -1, nullptr, nullptr, -1);
1014 			CommandDismiss(unit, arg1 > 0);
1015 			break;
1016 		case MessageCommandResourceLoc:
1017 			CommandLog("resource-loc", &unit, status, pos.x, pos.y, NoUnitP, nullptr, -1);
1018 			CommandResourceLoc(unit, pos, status);
1019 			break;
1020 		case MessageCommandResource: {
1021 			if (dstnr != (unsigned short)0xFFFF) {
1022 				CUnit &dest = UnitManager.GetSlotUnit(dstnr);
1023 				Assert(dest.Type);
1024 				CommandLog("resource", &unit, status, -1, -1, &dest, nullptr, -1);
1025 				CommandResource(unit, dest, status);
1026 			}
1027 			break;
1028 		}
1029 		case MessageCommandReturn: {
1030 			CUnit *dest = (dstnr != (unsigned short)0xFFFF) ? &UnitManager.GetSlotUnit(dstnr) : nullptr;
1031 			CommandLog("return", &unit, status, -1, -1, dest, nullptr, -1);
1032 			CommandReturnGoods(unit, dest, status);
1033 			break;
1034 		}
1035 		case MessageCommandTrain:
1036 			//Wyrmgus start
1037 //			CommandLog("train", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1);
1038 //			CommandTrainUnit(unit, *UnitTypes[dstnr], status);
1039 			CommandLog("train", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), arg1); // use X as a way to mark the player
1040 			CommandTrainUnit(unit, *UnitTypes[dstnr], arg1, status);
1041 			//Wyrmgus end
1042 			break;
1043 		case MessageCommandCancelTrain:
1044 			// We need (short)x for the last slot -1
1045 			if (dstnr != (unsigned short)0xFFFF) {
1046 				CommandLog("cancel-train", &unit, FlushCommands, -1, -1, NoUnitP,
1047 						   UnitTypes[dstnr]->Ident.c_str(), (short)x);
1048 				CommandCancelTraining(unit, (short)x, UnitTypes[dstnr]);
1049 			} else {
1050 				CommandLog("cancel-train", &unit, FlushCommands, -1, -1, NoUnitP, nullptr, (short)x);
1051 				CommandCancelTraining(unit, (short)x, nullptr);
1052 			}
1053 			break;
1054 		case MessageCommandUpgrade:
1055 			//Wyrmgus start
1056 			/*
1057 			CommandLog("upgrade-to", &unit, status, -1, -1, NoUnitP,
1058 					   UnitTypes[dstnr]->Ident.c_str(), -1);
1059 			CommandUpgradeTo(unit, *UnitTypes[dstnr], status);
1060 			break;
1061 			*/
1062 			if (arg1 == 2) { //use X as a way to mark whether this is an upgrade or a transformation
1063 				CommandLog("transform-into", &unit, status, -1, -1, NoUnitP,
1064 						   UnitTypes[dstnr]->Ident.c_str(), -1);
1065 				CommandTransformIntoType(unit, *UnitTypes[dstnr]);
1066 			} else {
1067 				CommandLog("upgrade-to", &unit, status, -1, -1, NoUnitP,
1068 						   UnitTypes[dstnr]->Ident.c_str(), -1);
1069 				CommandUpgradeTo(unit, *UnitTypes[dstnr], status);
1070 			}
1071 			break;
1072 			//Wyrmgus end
1073 		case MessageCommandCancelUpgrade:
1074 			CommandLog("cancel-upgrade-to", &unit, FlushCommands, -1, -1, NoUnitP, nullptr, -1);
1075 			CommandCancelUpgradeTo(unit);
1076 			break;
1077 		case MessageCommandResearch:
1078 			CommandLog("research", &unit, status, -1, -1, NoUnitP,
1079 					   //Wyrmgus start
1080 //					   AllUpgrades[arg1]->Ident.c_str(), -1);
1081 					   AllUpgrades[arg1]->Ident.c_str(), arg2);
1082 					   //Wyrmgus end
1083 			//Wyrmgus start
1084 //			CommandResearch(unit, *AllUpgrades[arg1], status);
1085 			CommandResearch(unit, *AllUpgrades[arg1], arg2, status);
1086 			//Wyrmgus end
1087 			break;
1088 		case MessageCommandCancelResearch:
1089 			CommandLog("cancel-research", &unit, FlushCommands, -1, -1, NoUnitP, nullptr, -1);
1090 			CommandCancelResearch(unit);
1091 			break;
1092 		//Wyrmgus start
1093 		case MessageCommandLearnAbility:
1094 			CommandLog("learn-ability", &unit, 0, -1, -1, NoUnitP,
1095 					   AllUpgrades[arg1]->Ident.c_str(), -1);
1096 			CommandLearnAbility(unit, *AllUpgrades[arg1]);
1097 			break;
1098 		case MessageCommandQuest: {
1099 			CommandLog("quest", &unit, 0, 0, 0, NoUnitP, Quests[arg1]->Ident.c_str(), -1);
1100 			CommandQuest(unit, Quests[arg1]);
1101 			break;
1102 		}
1103 		case MessageCommandBuy: {
1104 			if (dstnr != (unsigned short)0xFFFF) {
1105 				CUnit &dest = UnitManager.GetSlotUnit(dstnr);
1106 				Assert(dest.Type);
1107 				CommandLog("buy", &unit, 0, -1, -1, &dest, nullptr, arg1);
1108 				CommandBuy(unit, &dest, arg1);
1109 			}
1110 			break;
1111 		}
1112 		case MessageCommandProduceResource: {
1113 			CommandLog("produce-resource", &unit, 0, 0, -1, NoUnitP, nullptr, arg1);
1114 			CommandProduceResource(unit, arg1);
1115 			break;
1116 		}
1117 		case MessageCommandSellResource: {
1118 			CommandLog("sell-resource", &unit, 0, arg1, -1, NoUnitP, nullptr, arg2);
1119 			CommandSellResource(unit, arg1, arg2);
1120 			break;
1121 		}
1122 		case MessageCommandBuyResource: {
1123 			CommandLog("buy-resource", &unit, 0, arg1, -1, NoUnitP, nullptr, arg2);
1124 			CommandBuyResource(unit, arg1, arg2);
1125 			break;
1126 		}
1127 		//Wyrmgus end
1128 		default: {
1129 			int id = (msgnr & 0x7f) - MessageCommandSpellCast;
1130 			if (arg2 != (unsigned short)0xFFFF) {
1131 				CUnit *dest = nullptr;
1132 				if (dstnr != (unsigned short)0xFFFF) {
1133 					dest = &UnitManager.GetSlotUnit(dstnr);
1134 					Assert(dest && dest->Type);
1135 				}
1136 				CommandLog("spell-cast", &unit, status, pos.x, pos.y, dest, nullptr, id);
1137 				CommandSpellCast(unit, pos, dest, *CSpell::Spells[id], status);
1138 			} else {
1139 				CommandLog("auto-spell-cast", &unit, status, arg1, -1, NoUnitP, nullptr, id);
1140 				CommandAutoSpellCast(unit, id, arg1);
1141 			}
1142 			break;
1143 		}
1144 	}
1145 }
1146 
GetDiplomacyName(enum _diplomacy_ e)1147 static const char *GetDiplomacyName(enum _diplomacy_ e)
1148 {
1149 	Assert(int(e) < 4);
1150 	const char *diplomacyNames[] = {"allied", "neutral", "enemy", "crazy"};
1151 
1152 	return diplomacyNames[int(e)];
1153 }
1154 
1155 /**
1156 ** Execute an extended command (from network).
1157 **
1158 ** @param type     Network extended message type
1159 ** @param status   Bit 7 of message type
1160 ** @param arg1     Messe argument 1
1161 ** @param arg2     Messe argument 2
1162 ** @param arg3     Messe argument 3
1163 ** @param arg4     Messe argument 4
1164 */
ExecExtendedCommand(unsigned char type,int status,unsigned char arg1,unsigned short arg2,unsigned short arg3,unsigned short arg4)1165 void ExecExtendedCommand(unsigned char type, int status,
1166 						 unsigned char arg1, unsigned short arg2, unsigned short arg3,
1167 						 unsigned short arg4)
1168 {
1169 	// Note: destroyed units are handled by the action routines.
1170 
1171 	switch (type) {
1172 		case ExtendedMessageDiplomacy: {
1173 			const char *diplomacyName = GetDiplomacyName(_diplomacy_(arg3));
1174 			CommandLog("diplomacy", NoUnitP, 0, arg2, arg4, NoUnitP, diplomacyName, -1);
1175 			CommandDiplomacy(arg2, arg3, arg4);
1176 			break;
1177 		}
1178 		case ExtendedMessageSharedVision:
1179 			if (arg3 == 0) {
1180 				CommandLog("shared-vision", NoUnitP, 0, arg2, arg4, NoUnitP, "0", -1);
1181 			} else {
1182 				CommandLog("shared-vision", NoUnitP, 0, arg2, arg4, NoUnitP, "1", -1);
1183 			}
1184 			CommandSharedVision(arg2, arg3 ? true : false, arg4);
1185 			break;
1186 		//Wyrmgus start
1187 		case ExtendedMessageSetFaction: {
1188 			//FIXME: should add log for faction change here
1189 			Players[arg2].SetFaction(PlayerRaces.Factions[arg3]);
1190 			break;
1191 		}
1192 		case ExtendedMessageAutosellResource: {
1193 			Players[arg2].AutosellResource(arg3);
1194 			break;
1195 		}
1196 		//Wyrmgus end
1197 		default:
1198 			DebugPrint("Unknown extended message %u/%s %u %u %u %u\n" _C_
1199 					   type _C_ status ? "flush" : "-" _C_
1200 					   arg1 _C_ arg2 _C_ arg3 _C_ arg4);
1201 			break;
1202 	}
1203 }
1204 
1205 //@}
1206