CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

EVENT.CPP (48137B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/EVENT.CPP 1     3/03/97 10:24a Joe_bostic $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : EVENT.CPP                                                    *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : 12/09/94                                                     *
     28  *                                                                                             *
     29  *                  Last Update : November 10, 1995 [BRR]                                      *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   EventClass::EventClass -- Construct an id and cell based event.                           *
     34  *   EventClass::EventClass -- Construct simple target type event.                             *
     35  *   EventClass::EventClass -- Constructor for mission change events.                          *
     36  *   EventClass::EventClass -- Constructor for navigation computer events.                     *
     37  *   EventClass::EventClass -- Constructor for object types affecting cells event.             *
     38  *   EventClass::EventClass -- Constructor for sidebar build events.                           *
     39  *   EventClass::EventClass -- Constructs event to transfer special flags.                     *
     40  *   EventClass::EventClass -- Default constructor for event objects.                          *
     41  *   EventClass::EventClass -- Event for sequencing animations.                                *
     42  *   EventClass::EventClass -- Megamission assigned to unit.                                   *
     43  *   EventClass::Execute -- Execute a queued command.                                          *
     44  *   EventClass::EventClass -- construct a variable-sized event                                *
     45  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     46 
     47 #include "function.h"
     48 #ifdef WIN32
     49 #include "ccdde.h"
     50 #endif	//WIN32
     51 
     52 #ifdef FIXIT_VERSION_3		//	Stalemate games.
     53 #include "WolStrng.h"
     54 #endif
     55 
     56 /***************************************************************************
     57 ** Table of what data is really used in the EventClass struct for different
     58 ** events.  This table must be kept current with the EventType enum.
     59 */
     60 unsigned char EventClass::EventLength[EventClass::LAST_EVENT] = {
     61 	0,															// EMPTY
     62 	size_of(EventClass, Data.General ),				// ALLY
     63 	size_of(EventClass, Data.MegaMission ),		// MEGAMISSION
     64 	size_of(EventClass, Data.MegaMission_F ),		// MEGAMISSION_F
     65 	size_of(EventClass, Data.Target ),				// IDLE
     66 	size_of(EventClass, Data.Target ),				// SCATTER
     67 	0,															// DESTRUCT
     68 	0,															// DEPLOY
     69 	size_of(EventClass, Data.Place ),				// PLACE
     70 	0,															// OPTIONS
     71 	size_of(EventClass, Data.General ),				// GAMESPEED
     72 	size_of(EventClass, Data.Specific ),			// PRODUCE
     73 	size_of(EventClass, Data.Specific.Type ),		// SUSPEND
     74 	size_of(EventClass, Data.Specific.Type ),		// ABANDON
     75 	size_of(EventClass, Data.Target ),				// PRIMARY
     76 	size_of(EventClass, Data.Special ),				// SPECIAL_PLACE
     77 	0,															// EXIT
     78 	size_of(EventClass, Data.Anim ),					// ANIMATION
     79 	size_of(EventClass, Data.Target ),				// REPAIR
     80 	size_of(EventClass, Data.Target ),				// SELL
     81 	size_of(EventClass, Data.SellCell),				// SELLCELL
     82 	size_of(EventClass, Data.Options ),				// SPECIAL
     83 	0,															// FRAMESYNC
     84 	0,															//	MESSAGE
     85 	size_of(EventClass, Data.FrameInfo.Delay ),	// RESPONSE_TIME
     86 	size_of(EventClass, Data.FrameInfo ),			// FRAMEINFO
     87 	0,															//	SAVEGAME
     88 	size_of(EventClass, Data.NavCom ),				// ARCHIVE
     89 	size_of(EventClass, Data.Variable.Size),		// ADDPLAYER
     90 	size_of(EventClass, Data.Timing ),				// TIMING
     91 	size_of(EventClass, Data.ProcessTime ),		// PROCESS_TIME
     92 #ifdef FIXIT_VERSION_3		//	Stalemate games.
     93 	0,												//	PROPOSE_DRAW
     94 	0,												//	RETRACT_DRAW
     95 #endif
     96 };
     97 
     98 char * EventClass::EventNames[EventClass::LAST_EVENT] = {
     99 	"EMPTY",
    100 	"ALLY",
    101 	"MEGAMISSION",
    102 	"MEGAMISSION_F",
    103 	"IDLE",
    104 	"SCATTER",
    105 	"DESTRUCT",
    106 	"DEPLOY",
    107 	"PLACE",
    108 	"OPTIONS",
    109 	"GAMESPEED",
    110 	"PRODUCE",
    111 	"SUSPEND",
    112 	"ABANDON",
    113 	"PRIMARY",
    114 	"SPECIAL_PLACE",
    115 	"EXIT",
    116 	"ANIMATION",
    117 	"REPAIR",
    118 	"SELL",
    119 	"SELLCELL",
    120 	"SPECIAL",
    121 	"FRAMESYNC",
    122 	"MESSAGE",
    123 	"RESPONSE_TIME",
    124 	"FRAMEINFO",
    125 	"SAVEGAME",
    126 	"ARCHIVE",
    127 	"ADDPLAYER",
    128 	"TIMING",
    129 	"PROCESS_TIME",
    130 #ifdef FIXIT_VERSION_3		//	Stalemate games.
    131 	"PROPOSE_DRAW",
    132 	"RETRACT_DRAW",
    133 #endif
    134 };
    135 
    136 
    137 /***********************************************************************************************
    138  * EventClass::EventClass -- Constructs event to transfer special flags.                       *
    139  *                                                                                             *
    140  *    This constructs an event that will transfer the special flags.                           *
    141  *                                                                                             *
    142  * INPUT:   data  -- The special flags to be transported to all linked computers.              *
    143  *                                                                                             *
    144  * OUTPUT:  none                                                                               *
    145  *                                                                                             *
    146  * WARNINGS:   none                                                                            *
    147  *                                                                                             *
    148  * HISTORY:                                                                                    *
    149  *   06/25/1995 JLB : Created.                                                                 *
    150  *=============================================================================================*/
    151 EventClass::EventClass(SpecialClass data)
    152 {
    153 	ID = PlayerPtr->ID;
    154 	Type = SPECIAL;
    155 	Frame = ::Frame;
    156 	Data.Options.Data = data;
    157 }
    158 
    159 
    160 /***********************************************************************************************
    161  * EventClass::EventClass -- Construct simple target type event.                               *
    162  *                                                                                             *
    163  *    This will construct a generic event that needs only a target parameter. The actual       *
    164  *    event and target values are specified as parameters.                                     *
    165  *                                                                                             *
    166  * INPUT:   type  -- The event type to construct.                                              *
    167  *                                                                                             *
    168  *          target-- The target value that this event is to apply to.                          *
    169  *                                                                                             *
    170  * OUTPUT:  none                                                                               *
    171  *                                                                                             *
    172  * WARNINGS:   none                                                                            *
    173  *                                                                                             *
    174  * HISTORY:                                                                                    *
    175  *   06/25/1995 JLB : Created.                                                                 *
    176  *=============================================================================================*/
    177 EventClass::EventClass(EventType type, TargetClass target)
    178 {
    179 	ID = PlayerPtr->ID;
    180 	Type = type;
    181 	Frame = ::Frame;
    182 	Data.Target.Whom = target;
    183 }
    184 
    185 
    186 EventClass::EventClass(EventType type, CELL cell)
    187 {
    188 	ID = PlayerPtr->ID;
    189 	Type = type;
    190 	Frame = ::Frame;
    191 	Data.SellCell.Cell = cell;
    192 }
    193 
    194 
    195 /***********************************************************************************************
    196  * EventClass::EventClass -- Default constructor for event objects.                            *
    197  *                                                                                             *
    198  *    This constructs a simple event object that requires no parameters other than the         *
    199  *    type of event it is.                                                                     *
    200  *                                                                                             *
    201  * INPUT:   type  -- The type of event to construct.                                           *
    202  *                                                                                             *
    203  * OUTPUT:  none                                                                               *
    204  *                                                                                             *
    205  * WARNINGS:   none                                                                            *
    206  *                                                                                             *
    207  * HISTORY:                                                                                    *
    208  *   12/27/1994 JLB : Created.                                                                 *
    209  *=============================================================================================*/
    210 EventClass::EventClass(EventType type)
    211 {
    212 	ID = PlayerPtr->ID;
    213 	Type = type;
    214 	Frame = ::Frame;
    215 }
    216 
    217 
    218 /***********************************************************************************************
    219  * EventClass::EventClass -- Constructor for general-purpose-data events.                      *
    220  *                                                                                             *
    221  * INPUT:   type  -- The type of event to construct.                                           *
    222  *            val   -- data value                                                              *
    223  *                                                                                             *
    224  * OUTPUT:  none                                                                               *
    225  *                                                                                             *
    226  * WARNINGS:   none                                                                            *
    227  *                                                                                             *
    228  * HISTORY:                                                                                    *
    229  *   12/27/1994 JLB : Created.                                                                 *
    230  *=============================================================================================*/
    231 EventClass::EventClass(EventType type, int val)
    232 {
    233 	ID = PlayerPtr->ID;
    234 	Type = type;
    235 	Data.General.Value = val;
    236 	Frame = ::Frame;
    237 }
    238 
    239 
    240 /***********************************************************************************************
    241  * EventClass::EventClass -- Constructor for navigation computer events.                       *
    242  *                                                                                             *
    243  *    Constructor for events that are used to assign the navigation computer.                  *
    244  *                                                                                             *
    245  * INPUT:   type     -- The type of event (this constructor can be used by other navigation    *
    246  *                      type events).                                                          *
    247  *                                                                                             *
    248  *          src      -- The object that the event should apply to.                             *
    249  *                                                                                             *
    250  *          dest     -- The destination (or target) that the event needs to complete.          *
    251  *                                                                                             *
    252  * OUTPUT:  none                                                                               *
    253  *                                                                                             *
    254  * WARNINGS:   none                                                                            *
    255  *                                                                                             *
    256  * HISTORY:                                                                                    *
    257  *   12/27/1994 JLB : Created.                                                                 *
    258  *=============================================================================================*/
    259 EventClass::EventClass(EventType type, TargetClass src, TargetClass dest)
    260 {
    261 	ID = PlayerPtr->ID;
    262 	Type = type;
    263 	Frame = ::Frame;
    264 	Data.NavCom.Whom = src;
    265 	Data.NavCom.Where = TargetClass(dest);
    266 }
    267 
    268 
    269 /***********************************************************************************************
    270  * EventClass::EventClass -- Event for sequencing animations.                                  *
    271  *                                                                                             *
    272  *    This constructor is used for animations that must be created through the event system.   *
    273  *                                                                                             *
    274  * INPUT:   anim  -- The animation that will be created.                                       *
    275  *                                                                                             *
    276  *          coord -- The location where the animation is to be created.                        *
    277  *                                                                                             *
    278  * OUTPUT:  none                                                                               *
    279  *                                                                                             *
    280  * WARNINGS:   none                                                                            *
    281  *                                                                                             *
    282  * HISTORY:                                                                                    *
    283  *   05/19/1995 JLB : Created.                                                                 *
    284  *=============================================================================================*/
    285 EventClass::EventClass(AnimType anim, HousesType owner, COORDINATE coord, int visible)
    286 {
    287 	ID = PlayerPtr->ID;
    288 	Type = ANIMATION;
    289 	Frame = ::Frame;
    290 	Data.Anim.What = anim;
    291 	Data.Anim.Owner = owner;
    292 	Data.Anim.Where = coord;
    293 	Data.Anim.Visible = visible;
    294 }
    295 
    296 
    297 /***********************************************************************************************
    298  * EventClass::EventClass -- Megamission assigned to unit.                                     *
    299  *                                                                                             *
    300  *    This is the event that is used to assign most missions to units. It combines both the    *
    301  *    mission and the target (navcom and tarcom).                                              *
    302  *                                                                                             *
    303  * INPUT:   src      -- The object that this mission is to apply to.                           *
    304  *                                                                                             *
    305  *          mission  -- The mission to assign to this object.                                  *
    306  *                                                                                             *
    307  *          target   -- The target to assign to this object's TarCom.                          *
    308  *                                                                                             *
    309  *          destination -- The destination to assign to this object's NavCom.                  *
    310  *                                                                                             *
    311  * OUTPUT:  none                                                                               *
    312  *                                                                                             *
    313  * WARNINGS:   none                                                                            *
    314  *                                                                                             *
    315  * HISTORY:                                                                                    *
    316  *   05/18/1995 JLB : Created.                                                                 *
    317  *=============================================================================================*/
    318 EventClass::EventClass(TargetClass src, MissionType mission, TargetClass target, TargetClass destination)
    319 {
    320 	ID = PlayerPtr->ID;
    321 	Type = MEGAMISSION;
    322 	Frame = ::Frame;
    323 	Data.MegaMission.Whom = src;
    324 	Data.MegaMission.Mission = mission;
    325 	Data.MegaMission.Target = target;
    326 	Data.MegaMission.Destination = destination;
    327 }
    328 
    329 
    330 /***********************************************************************************************
    331  * EventClass::EventClass -- Megamission assigned to unit.                                     *
    332  *                                                                                             *
    333  *    This is the event that is used to assign most missions to units. It combines both the    *
    334  *    mission and the target (navcom and tarcom).  This variation is used for formation moves. *
    335  *                                                                                             *
    336  * INPUT:   src      -- The object that this mission is to apply to.                           *
    337  *                                                                                             *
    338  *          mission  -- The mission to assign to this object.                                  *
    339  *                                                                                             *
    340  *          target   -- The target to assign to this object's TarCom.                          *
    341  *                                                                                             *
    342  *          destination -- The destination to assign to this object's NavCom.                  *
    343  *                                                                                             *
    344  *          speed    -- The formation override speed for this move.                            *
    345  *                                                                                             *
    346  *          maxspeed -- The formation override maximum speed for this move.                    *
    347  *                                                                                             *
    348  * OUTPUT:  none                                                                               *
    349  *                                                                                             *
    350  * WARNINGS:   none                                                                            *
    351  *                                                                                             *
    352  * HISTORY:                                                                                    *
    353  *   05/18/1995 JLB : Created.                                                                 *
    354  *=============================================================================================*/
    355 EventClass::EventClass(TargetClass src, MissionType mission, TargetClass target, TargetClass destination, SpeedType speed, MPHType maxspeed)
    356 {
    357 	ID = PlayerPtr->ID;
    358 	Type = MEGAMISSION_F;
    359 	Frame = ::Frame;
    360 	Data.MegaMission_F.Whom = src;
    361 	Data.MegaMission_F.Mission = mission;
    362 	Data.MegaMission_F.Target = TargetClass(target);
    363 	Data.MegaMission_F.Destination = TargetClass(destination);
    364 	Data.MegaMission_F.Speed = speed;
    365 	Data.MegaMission_F.MaxSpeed = maxspeed;
    366 }
    367 
    368 
    369 /***********************************************************************************************
    370  * EventClass::EventClass -- Constructor for sidebar build events.                             *
    371  *                                                                                             *
    372  *    This constructor is used for events that deal with an object type and an object ID.      *
    373  *    Typically, this is used exclusively by the sidebar.                                      *
    374  *                                                                                             *
    375  * INPUT:   type     -- The event type of this object.                                         *
    376  *                                                                                             *
    377  *          object   -- The object type number.                                                *
    378  *                                                                                             *
    379  *          id       -- The object sub-type number.                                            *
    380  *                                                                                             *
    381  * OUTPUT:  none                                                                               *
    382  *                                                                                             *
    383  * WARNINGS:   none                                                                            *
    384  *                                                                                             *
    385  * HISTORY:                                                                                    *
    386  *   05/18/1995 JLB : Created.                                                                 *
    387  *=============================================================================================*/
    388 EventClass::EventClass(EventType type, RTTIType object, int id)
    389 {
    390 	ID = PlayerPtr->ID;
    391 	Type = type;
    392 	Frame = ::Frame;
    393 	Data.Specific.Type = object;
    394 	Data.Specific.ID = id;
    395 }
    396 
    397 
    398 /***********************************************************************************************
    399  * EventClass::EventClass -- Constructor for object types affecting cells event.               *
    400  *                                                                                             *
    401  *    This constructor is used for those events that have an object type and associated cell.  *
    402  *    Typically, this is for building placement after construction has completed.              *
    403  *                                                                                             *
    404  * INPUT:   type     -- The event type for this object.                                        *
    405  *                                                                                             *
    406  *          object   -- The object type number (actual object is probably inferred from the    *
    407  *                      sidebar data).                                                         *
    408  *                                                                                             *
    409  *          cell     -- The cell location where this event is to occur.                        *
    410  *                                                                                             *
    411  * OUTPUT:  none                                                                               *
    412  *                                                                                             *
    413  * WARNINGS:   none                                                                            *
    414  *                                                                                             *
    415  * HISTORY:                                                                                    *
    416  *   05/18/1995 JLB : Created.                                                                 *
    417  *=============================================================================================*/
    418 EventClass::EventClass(EventType type, RTTIType object, CELL cell)
    419 {
    420 	ID = PlayerPtr->ID;
    421 	Type = type;
    422 	Frame = ::Frame;
    423 	Data.Place.Type = object;
    424 	Data.Place.Cell = cell;
    425 }
    426 
    427 
    428 /***********************************************************************************************
    429  * EventClass::EventClass -- Construct an id and cell based event.                             *
    430  *                                                                                             *
    431  *    This constructor is used for those events that require an ID number and a cell location. *
    432  *                                                                                             *
    433  * INPUT:   type  -- The event type this will be.                                              *
    434  *                                                                                             *
    435  *          id    -- The arbitrary id number to assign.                                        *
    436  *                                                                                             *
    437  *          cell  -- The location for this event.                                              *
    438  *                                                                                             *
    439  * OUTPUT:  none                                                                               *
    440  *                                                                                             *
    441  * WARNINGS:   none                                                                            *
    442  *                                                                                             *
    443  * HISTORY:                                                                                    *
    444  *   05/18/1995 JLB : Created.                                                                 *
    445  *=============================================================================================*/
    446 EventClass::EventClass(EventType type, int id, CELL cell)
    447 {
    448 	ID = PlayerPtr->ID;
    449 	Type = type;
    450 	Frame = ::Frame;
    451 	Data.Special.ID 	= id;
    452 	Data.Special.Cell = cell;
    453 }
    454 
    455 
    456 /***********************************************************************************************
    457  * EventClass::EventClass -- construct a variable-sized event                                  *
    458  *                                                                                             *
    459  * INPUT:                                                                                      *
    460  *		ptr		ptr to data associated with this event														  *
    461  *                                                                                             *
    462  * OUTPUT:                                                                                     *
    463  *		none.																												  *
    464  *                                                                                             *
    465  * WARNINGS:                                                                                   *
    466  *		none.																												  *
    467  *                                                                                             *
    468  * HISTORY:                                                                                    *
    469  *   11/10/1995 BRR : Created.                                                                 *
    470  *=============================================================================================*/
    471 EventClass::EventClass(EventType type, void * ptr, unsigned long size)
    472 {
    473 	ID = PlayerPtr->ID;
    474 	Type = type;
    475 	Frame = ::Frame;
    476 	Data.Variable.Pointer = ptr;
    477 	Data.Variable.Size = size;
    478 }
    479 
    480 
    481 /***********************************************************************************************
    482  * EventClass::Execute -- Execute a queued command.                                            *
    483  *                                                                                             *
    484  *    This routine executes an event. The even must already have been confirmed by any         *
    485  *    remote machine before calling this routine.                                              *
    486  *                                                                                             *
    487  * INPUT:   none                                                                               *
    488  *                                                                                             *
    489  * OUTPUT:  none                                                                               *
    490  *                                                                                             *
    491  * WARNINGS:   none                                                                            *
    492  *                                                                                             *
    493  * HISTORY:                                                                                    *
    494  *   12/27/1994 JLB : Created.                                                                 *
    495  *=============================================================================================*/
    496 void EventClass::Execute(void)
    497 {
    498 	TechnoClass * techno;
    499 	AnimClass * anim = 0;
    500 	HouseClass * house = 0;
    501 //	CELL cell = 0;
    502 	char txt[80];
    503 	bool formation = false;
    504 //	RTTIType rt;
    505 
    506 	if (Debug_Print_Events) {
    507 		printf("(%d) Executing %s ID:%d Frame:%d ",
    508 			::Frame, EventNames[Type], ID, Frame);
    509 	}
    510 
    511 	switch (Type) {
    512 
    513 		/*
    514 		**	Update the archive target for this building.
    515 		*/
    516 		case ARCHIVE:
    517 			techno = Data.NavCom.Whom.As_Techno();
    518 			if (techno && techno->IsActive) {
    519 				techno->ArchiveTarget = Data.NavCom.Where.As_TARGET();
    520 			}
    521 			break;
    522 
    523 		/*
    524 		**	Make or break alliance.
    525 		*/
    526 		case ALLY:
    527 			house = Houses.Raw_Ptr(Data.General.Value);
    528 			if (Houses.Raw_Ptr(ID)->Is_Ally(house)) {
    529 				Houses.Raw_Ptr(ID)->Make_Enemy((HousesType)Data.General.Value);
    530 			} else {
    531 				Houses.Raw_Ptr(ID)->Make_Ally((HousesType)Data.General.Value);
    532 			}
    533 			break;
    534 
    535 		/*
    536 		**	Special self destruct action requested. This is active in the multiplayer mode.
    537 		*/
    538 		case DESTRUCT:
    539 			Houses.Raw_Ptr(ID)->Flag_To_Die();
    540 			break;
    541 
    542 		/*
    543 		**	Update the special control flags. This is necessary so that in a multiplay
    544 		**	game, all machines will agree on the rules. If these options change during
    545 		**	game play, then all players are informed that options have changed.
    546 		*/
    547 		case SPECIAL:
    548 			{
    549 				Special = Data.Options.Data;
    550 				HouseClass * house = Houses.Raw_Ptr(ID);
    551 
    552 				//sprintf(txt, Text_String(TXT_SPECIAL_WARNING), house->Name);	// Should be IniName? ST - 5/8/2019
    553 				sprintf(txt, Text_String(TXT_SPECIAL_WARNING), house->IniName);
    554 				Session.Messages.Add_Message(NULL, 0, txt,
    555 					house->RemapColor,
    556 					TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1200);
    557 				Map.Flag_To_Redraw(false);
    558 			}
    559 			break;
    560 
    561 		/*
    562 		**	Starts or stops repair on the specified object. This event is triggered by the
    563 		**	player clicking the repair wrench on a building.
    564 		*/
    565 		case REPAIR:
    566 			techno = Data.Target.Whom.As_Techno();
    567 			if (techno && techno->IsActive) {
    568 				techno->Repair(-1);
    569 			}
    570 			break;
    571 
    572 		/*
    573 		**	Tells a building/unit to sell. This event is triggered by the player clicking the
    574 		**	sell animating cursor over the building or unit.
    575 		*/
    576 		case SELL:
    577 			techno = Data.Target.Whom.As_Techno();
    578 			if (techno && techno->IsActive && techno->House == Houses.Raw_Ptr(ID)) {
    579 				if (techno->What_Am_I() == RTTI_BUILDING || (techno->What_Am_I() == RTTI_UNIT && Map[techno->Center_Coord()].Cell_Building() != 0)) {
    580 					techno->Sell_Back(-1);
    581 				}
    582 			} else {
    583 //				if (Is_Target_Cell(Data.Target.Whom)) {
    584 //					Houses.Raw_Ptr(ID)->Sell_Wall(As_Cell(Data.Target.Whom));
    585 //				}
    586 			}
    587 			break;
    588 
    589 		/*
    590 		**	Tells the wall at the specified location to sell off.
    591 		*/
    592 		case SELLCELL:
    593 //			cell = Data.SellCell.Cell;
    594 			Houses.Raw_Ptr(ID)->Sell_Wall(Data.SellCell.Cell);
    595 			break;
    596 
    597 		/*
    598 		**	This even is used to trigger an animation that is generated as a direct
    599 		**	result of player intervention.
    600 		*/
    601 		case ANIMATION:
    602 			anim = new AnimClass(Data.Anim.What, Data.Anim.Where);
    603 			if (anim) {
    604 				anim->Set_Owner(Data.Anim.Owner);
    605 				anim->Set_Visible_Flags(static_cast<unsigned int>(Data.Anim.Visible));
    606 				/*
    607 				**	Beacons have a 30-second kill time.
    608 				*/
    609 				if (Data.Anim.What == ANIM_BEACON) {
    610 					FILETIME ft;
    611 					GetSystemTimeAsFileTime(&ft);
    612 
    613 					unsigned long long kill_time = ((unsigned long long)ft.dwLowDateTime + ((unsigned long long)ft.dwHighDateTime << 32ULL)) + 300000000ULL;
    614 					anim->Kill_At(kill_time);
    615 				}
    616 			}
    617 			break;
    618 
    619 		/*
    620 		**	This event will place the specified object at the specified location.
    621 		**	The event is used to place newly constructed buildings down on the map. The
    622 		**	object type is specified. From this object type, the house can determine the
    623 		**	exact factory and real object pointer to use.
    624 		*/
    625 		case PLACE:
    626 			Houses.Raw_Ptr(ID)->Place_Object(Data.Place.Type, Data.Place.Cell);
    627 			break;
    628 
    629 		/*
    630 		**	This event starts production of the specified object type. The house can
    631 		**	determine from the type and ID value, what object to begin production on and
    632 		**	what factory to use.
    633 		*/
    634 		case PRODUCE:
    635 			Houses.Raw_Ptr(ID)->Begin_Production(Data.Specific.Type, Data.Specific.ID);
    636 			break;
    637 
    638 		/*
    639 		**	This event is generated when the player puts production on hold. From the
    640 		**	object type, the factory can be inferred.
    641 		*/
    642 		case SUSPEND:
    643 			Houses.Raw_Ptr(ID)->Suspend_Production(Data.Specific.Type);
    644 			break;
    645 
    646 		/*
    647 		**	This event is generated when the player cancels production of the specified
    648 		**	object type. From the object type, the exact factory can be inferred.
    649 		*/
    650 		case ABANDON:
    651 			Houses.Raw_Ptr(ID)->Abandon_Production(Data.Specific.Type);
    652 			break;
    653 
    654 		/*
    655 		**	Toggles the primary factory state of the specified building.
    656 		*/
    657 		case PRIMARY:
    658 			{
    659 				BuildingClass * building = Data.Target.Whom.As_Building();
    660 				if (building && building->IsActive) {
    661 					building->Toggle_Primary();
    662 				}
    663 			}
    664 			break;
    665 
    666 		/*
    667 		**	This is the general purpose mission control event. Most player
    668 		**	action routes through this event. It sets a unit's mission, TarCom,
    669 		**	and NavCom to the values specified.
    670 		*/
    671 		case MEGAMISSION_F:
    672 			techno = Data.MegaMission_F.Whom.As_Techno();
    673 			if (techno && techno->IsActive && techno->Is_Foot()) {
    674 				((FootClass *)techno)->IsFormationMove = true;
    675 				((FootClass *)techno)->FormationSpeed = Data.MegaMission_F.Speed;
    676 				((FootClass *)techno)->FormationMaxSpeed = Data.MegaMission_F.MaxSpeed;
    677 				FormMove = true;
    678 				FormSpeed = Data.MegaMission_F.Speed;
    679 				FormMaxSpeed = Data.MegaMission_F.MaxSpeed;
    680 				formation = true;
    681 			}
    682 			// Fall thru to next case...
    683 
    684 		case MEGAMISSION:
    685 			if (Debug_Print_Events) {
    686 				printf("Whom:%x Tgt:%x Dest:%x ",
    687 					Data.MegaMission.Whom.As_TARGET(),
    688 					Data.MegaMission.Target.As_TARGET(),
    689 					Data.MegaMission.Destination.As_TARGET());
    690 			}
    691 			techno = Data.MegaMission.Whom.As_Techno();
    692 			if (techno != NULL && techno->IsActive && techno->Strength > 0 && !techno->IsInLimbo) {
    693 
    694 				/*
    695 				**	Fetch a pointer to the object of the mission. If there is an error with
    696 				**	this object, such as it is dead, then bail.
    697 				*/
    698 				ObjectClass * object = NULL;
    699 				if (Data.MegaMission.Target.Is_Valid()) {
    700 					object = Data.MegaMission.Target.As_Object();
    701 					if (object != NULL && (!object->IsActive || object->Strength == 0 || object->IsInLimbo)) {
    702 						break;
    703 //						object = NULL;
    704 //						Data.MegaMission.Target.Invalidate();
    705 					}
    706 				}
    707 
    708 				/*
    709 				**	If the destination target is invalid because the object is dead, then
    710 				**	bail from processing this mega mission.
    711 				*/
    712 				if (Data.MegaMission.Destination.Is_Valid()) {
    713 					object = Data.MegaMission.Destination.As_Object();
    714 					if (object != NULL && (!object->IsActive || object->Strength == 0 || object->IsInLimbo)) {
    715 						break;
    716 //						object = NULL;
    717 //						Data.MegaMission.Destination.Invalidate();
    718 					}
    719 				}
    720 
    721 				/*
    722 				**	Break any existing tether or team contact, since it is now invalid.
    723 				*/
    724 				if (!techno->IsTethered) {
    725 					techno->Transmit_Message(RADIO_OVER_OUT);
    726 				}
    727 				if (techno->Is_Foot()) {
    728 					if (!formation) ((FootClass *)techno)->IsFormationMove = false;
    729 					if (((FootClass *)techno)->Team) {
    730 						((FootClass *)techno)->Team->Remove((FootClass *)techno);
    731 					}
    732 				}
    733 
    734 				if (object != NULL) {
    735 
    736 					// 2019/09/20 JAS - Added record of who clicked on the object
    737 					HouseClass* house = Houses.Raw_Ptr(ID);
    738 					bool is_allied = house != nullptr && house->Is_Ally(techno);
    739 					if (is_allied) {
    740 						object->Clicked_As_Target((HousesType)ID);
    741 					}
    742 				}
    743 
    744 				/*
    745 				**	Test to see if the navigation target should really be queued rather
    746 				**	than assigned to the object. This would be the case if this is a
    747 				**	special queued move mission and there is already a valid navigation
    748 				**	target for this unit.
    749 				*/
    750 				bool q = (Data.MegaMission.Mission == MISSION_QMOVE);
    751 
    752 				techno->Assign_Mission(Data.MegaMission.Mission);
    753 
    754 				if (techno->Is_Foot()) {
    755 					((FootClass*)techno)->SuspendedNavCom = TARGET_NONE;
    756 				}
    757 				techno->SuspendedTarCom = TARGET_NONE;
    758 
    759 				/*
    760 				**	Guard area mode is handled with care. The specified target is actually
    761 				**	assigned as the location that should be guarded. In addition, the
    762 				**	movement destination is immediately set to this new location.
    763 				*/
    764 				if (Data.MegaMission.Mission == MISSION_GUARD_AREA && techno->Is_Foot()) {
    765 					techno->Assign_Target(TARGET_NONE);
    766 					techno->Assign_Destination(Data.MegaMission.Target.As_TARGET());
    767 					techno->ArchiveTarget = Data.MegaMission.Target.As_TARGET();
    768 				} else if (Data.MegaMission.Mission == MISSION_ENTER &&
    769 							object != NULL &&
    770 							object->What_Am_I() == RTTI_BUILDING &&
    771 							*((BuildingClass*)object) == STRUCT_REFINERY) {
    772 					techno->Transmit_Message(RADIO_HELLO, (BuildingClass*)object);
    773 					techno->Assign_Destination(TARGET_NONE);
    774 				} else {
    775 					if (q && techno->Is_Foot()) {
    776 						((FootClass *)techno)->Queue_Navigation_List(Data.MegaMission.Destination.As_TARGET());
    777 					} else {
    778 						if (techno->Is_Foot()) {
    779 							((FootClass *)techno)->Clear_Navigation_List();
    780 						}
    781 						techno->Assign_Target(Data.MegaMission.Target.As_TARGET());
    782 						techno->Assign_Destination(Data.MegaMission.Destination.As_TARGET());
    783 					}
    784 				}
    785 
    786 				//
    787 				// Special case for ship repairing: If the assigned mission is to
    788 				// move, and 'techno' is a Vessel:
    789 				//   If the destination is a shipyard or sub pen, set the IsToSelfRepair flag
    790 				//   Otherwise, clear both IsToSelfRepair and IsSelfRepairing
    791 				//
    792 				RTTIType rt = techno->What_Am_I();
    793 //				rt = Data.MegaMission.Whom;
    794 				if (rt == RTTI_VESSEL && techno != NULL && techno->What_Am_I() == RTTI_VESSEL) {
    795 					VesselClass *ship = (VesselClass *)techno;
    796 					if (Data.MegaMission.Mission == MISSION_MOVE) {
    797 						if (object != NULL) {
    798 							if (object->What_Am_I() == RTTI_BUILDING &&
    799 								((BuildingClass *)object)->House->Is_Ally(techno) &&
    800 //							if ((RTTIType)Data.MegaMission.Destination == RTTI_BUILDING &&
    801 								(((BuildingClass *)object)->Class->Type == STRUCT_SHIP_YARD ||
    802 								((BuildingClass *)object)->Class->Type == STRUCT_SUB_PEN)) {
    803 								ship->IsToSelfRepair = true;
    804 							} else {
    805 								ship->IsToSelfRepair = false;
    806 								ship->IsSelfRepairing = false;
    807 							}
    808 						} else {
    809 							ship->IsToSelfRepair = false;
    810 							ship->IsSelfRepairing = false;
    811 						}
    812 					} else {
    813 						ship->IsToSelfRepair = false;
    814 						ship->IsSelfRepairing = false;
    815 					}
    816 				}
    817 
    818 #ifdef NEVER
    819 				if ((techno->What_Am_I() == RTTI_UNIT || techno->What_Am_I() == RTTI_INFANTRY) &&
    820 						Data.MegaMission.Mission == MISSION_GUARD_AREA) {
    821 
    822 					((FootClass *)techno)->ArchiveTarget = Data.MegaMission.Destination;
    823 				}
    824 #endif
    825 			}
    826 			break;
    827 
    828 		/*
    829 		**	Request that the unit/infantry/aircraft go into idle mode.
    830 		*/
    831 		case IDLE:
    832 			techno = Data.Target.Whom.As_Techno();
    833 			if (techno != NULL && techno->IsActive && !techno->IsInLimbo && !techno->IsTethered && techno->What_Am_I() != RTTI_BUILDING) {
    834 				techno->Transmit_Message(RADIO_OVER_OUT);
    835 				techno->Assign_Destination(TARGET_NONE);
    836 				techno->Assign_Target(TARGET_NONE);
    837 				techno->Enter_Idle_Mode();
    838 				if (techno->Is_Foot()) {
    839 					((FootClass *)techno)->Clear_Navigation_List();
    840 				}
    841 			}
    842 			break;
    843 
    844 		/*
    845 		**	Request that the unit/infantry/aircraft scatter from its current location.
    846 		*/
    847 		case SCATTER:
    848 			techno = Data.Target.Whom.As_Techno();
    849 			if (techno != NULL && techno->Is_Foot() && techno->IsActive && !techno->IsInLimbo && !techno->IsTethered) {
    850 				((FootClass *)techno)->IsScattering = true;
    851 				techno->Scatter(0, true, false);
    852 			}
    853 			break;
    854 
    855 		/*
    856 		**	If we are placing down the ion cannon blast then lets take
    857 		** care of it.
    858 		*/
    859 		case SPECIAL_PLACE:
    860 			Houses.Raw_Ptr(ID)->Place_Special_Blast((SpecialWeaponType)Data.Special.ID, Data.Special.Cell);
    861 			break;
    862 
    863 		/*
    864 		**	Exit the game.
    865 		** Give parting message while palette is fading to black.
    866 		*/
    867 		case EXIT:
    868 			Theme.Queue_Song(THEME_NONE);
    869 			Stop_Speaking();
    870 			Speak(VOX_CONTROL_EXIT);
    871 			while (Is_Speaking()) {
    872 				Call_Back();
    873 			}
    874 			GameActive = false;
    875 			break;
    876 
    877 		/*
    878 		**	Process the options menu, unless we're playing back a recording.
    879 		*/
    880 		case OPTIONS:
    881 			if (!Session.Play) {
    882 				SpecialDialog = SDLG_OPTIONS;
    883 			}
    884 			break;
    885 
    886 		/*
    887 		**	Process the options Game Speed
    888 		*/
    889 		case GAMESPEED:
    890 			Options.GameSpeed = Data.General.Value;
    891 			break;
    892 
    893 		/*
    894 		**	Adjust connection timing for multiplayer games
    895 		*/
    896 		case RESPONSE_TIME:
    897 			Session.MaxAhead = Data.FrameInfo.Delay;
    898 			break;
    899 
    900 		/*
    901 		**	Save a multiplayer game (this event is only generated in multiplayer mode)
    902 		*/
    903 		case SAVEGAME:
    904 			/*
    905 			** Show the user what's going on with a message box (but only if
    906 			** we're not already inside a dialog box routine!)
    907 			*/
    908 			if (SpecialDialog == SDLG_NONE) {
    909 				CDTimerClass<SystemTimerClass> timer;
    910 				//timer.Start();
    911 				timer = TICKS_PER_SECOND * 4;
    912 
    913 				WWMessageBox().Process(TXT_SAVING_GAME, TXT_NONE);
    914 
    915 				Save_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));
    916 
    917 				while (timer > 0) {
    918 					Call_Back();
    919 				}
    920 
    921 				HidPage.Clear();
    922 				Map.Flag_To_Redraw(true);
    923 				Map.Render();
    924 			}
    925 			else {
    926 				Save_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));
    927 			}
    928 			break;
    929 
    930 		/*
    931 		** Add a new player to the game:
    932 		** - Form a network connection to him
    933 		** - Add his name, ID, House etc to our list of players
    934 		** - Re-sort the ID array
    935 		** - Place his units on the map
    936 		*/
    937 		case ADDPLAYER:
    938 			int i;
    939 			printf("ADDPLAYER EVENT!\n");
    940 			for (i=0;i<(int)Data.Variable.Size;i++) {
    941 				printf("%d\n", ((char *)Data.Variable.Pointer)[i]);
    942 			}
    943 			if (ID != PlayerPtr->ID) {
    944 				delete [] Data.Variable.Pointer;
    945 			}
    946 			break;
    947 
    948 		//
    949 		// This event tells all systems to use new timing values.  It's like
    950 		// RESPONSE_TIME, only it works.  It's only used with the
    951 		// COMM_MULTI_E_COMP protocol.
    952 		//
    953 		case TIMING:
    954 #if(TIMING_FIX)
    955 			//
    956 			// If MaxAhead is about to increase, we're vulnerable to a Packet-
    957 			// Received-Too-Late error, if any system generates an event after
    958 			// this TIMING event, but before it executes.  So, record the
    959 			// period of vulnerability's frame start & end values, so we
    960 			// can reschedule these events to execute after it's over.
    961 			//
    962 			if (Data.Timing.MaxAhead > Session.MaxAhead) {
    963 				NewMaxAheadFrame1 = Frame;
    964 				NewMaxAheadFrame2 = Frame + Data.Timing.MaxAhead;
    965 			}
    966 #endif
    967 			Session.DesiredFrameRate = Data.Timing.DesiredFrameRate;
    968 			Session.MaxAhead = Data.Timing.MaxAhead;
    969 
    970 #ifndef WOLAPI_INTEGRATION
    971 			/*
    972 			** If spawned from WChat then we should be getting poked every minute. If not then
    973 			** deliberately break the max ahead value
    974 			*/
    975 #ifdef WIN32
    976 			if (Special.IsFromWChat) {
    977 				Session.MaxAhead += DDEServer.Time_Since_Heartbeat()/(70*60);
    978 			}
    979 #endif	//WIN32
    980 #endif	//	!WOLAPI_INTEGRATION
    981 			if (Debug_Print_Events) {
    982 				printf("DesiredFrameRate:%d MaxAhead:%d ",
    983 					Session.DesiredFrameRate,
    984 					Session.MaxAhead);
    985 			}
    986 
    987 			break;
    988 
    989 		//
    990 		// This event tells all systems what the other systems' process
    991 		// timing requirements are; it's used to compute a desired frame rate
    992 		// for the game.
    993 		//
    994 		case PROCESS_TIME:
    995 			for (i = 0; i < Session.Players.Count(); i++) {
    996 				if (ID == Session.Players[i]->Player.ID) {
    997 					Session.Players[i]->Player.ProcessTime = Data.ProcessTime.AverageTicks;
    998 					break;
    999 				}
   1000 			}
   1001 			break;
   1002 
   1003 #ifdef FIXIT_VERSION_3		//	Stalemate games.
   1004 		case PROPOSE_DRAW:
   1005 			if( ID == PlayerPtr->ID )
   1006 			{
   1007 				if( Scen.bOtherProposesDraw )
   1008 				{
   1009 					//	Both sides agree to draw. Game will end in a tie.
   1010 					Scen.bLocalProposesDraw = true;
   1011 					break;
   1012 				}
   1013 				Scen.bLocalProposesDraw = true;
   1014 				//PG Session.Messages.Add_Message( NULL, 0, TXT_WOL_DRAW_PROPOSED_LOCAL, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );
   1015 			}
   1016 			else
   1017 			{
   1018 				if( Scen.bLocalProposesDraw )
   1019 				{
   1020 					//	Both sides agree to draw. Game will end in a tie.
   1021 					Scen.bOtherProposesDraw = true;
   1022 					break;
   1023 				}
   1024 				char szMessage[ 100 ];
   1025 				for (i = 0; i < Session.Players.Count(); i++) 
   1026 				{
   1027 					if (ID == Session.Players[i]->Player.ID) 
   1028 					{
   1029 						//PG sprintf( szMessage, TXT_WOL_DRAW_PROPOSED_OTHER, Session.Players[i]->Name );
   1030 						break;
   1031 					}
   1032 				}
   1033 				Scen.bOtherProposesDraw = true;
   1034 				Session.Messages.Add_Message( NULL, 0, szMessage, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );
   1035 			}
   1036 			Sound_Effect( VOC_INCOMING_MESSAGE );
   1037 			break;
   1038 
   1039 		case RETRACT_DRAW:
   1040 			if( ID == PlayerPtr->ID )
   1041 			{
   1042 				Scen.bLocalProposesDraw = false;
   1043 				//PG Session.Messages.Add_Message( NULL, 0, TXT_WOL_DRAW_RETRACTED_LOCAL, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );
   1044 			}
   1045 			else
   1046 			{
   1047 				char szMessage[ 100 ];
   1048 				for (i = 0; i < Session.Players.Count(); i++) 
   1049 				{
   1050 					if (ID == Session.Players[i]->Player.ID) 
   1051 					{
   1052 						//PG sprintf( szMessage, TXT_WOL_DRAW_RETRACTED_OTHER, Session.Players[i]->Name );
   1053 						break;
   1054 					}
   1055 				}
   1056 				Scen.bOtherProposesDraw = false;
   1057 				Session.Messages.Add_Message( NULL, 0, szMessage, PCOLOR_GOLD, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE );
   1058 			}
   1059 			Sound_Effect( VOC_INCOMING_MESSAGE );
   1060 			break;
   1061 #endif
   1062 
   1063 		/*
   1064 		**	Default: do nothing.
   1065 		*/
   1066 		default:
   1067 			break;
   1068 	}
   1069 
   1070 	if (Debug_Print_Events) {
   1071 		printf("\n");
   1072 	}
   1073 
   1074 }