CnC_Remastered_Collection

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

EVENT.CPP (37191B)


      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:   F:\projects\c&c\vcs\code\event.cpv   2.17   16 Oct 1995 16:50:28   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 : June 25, 1995 [JLB]                                          *
     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  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     45 
     46 #include "function.h"
     47 #include "ccdde.h"
     48 
     49 /***************************************************************************
     50 ** Table of what data is really used in the EventClass struct for different
     51 ** events.  This table must be kept current with the EventType enum.
     52 */
     53 unsigned char EventClass::EventLength[EventClass::LAST_EVENT] = {
     54 	0,															// EMPTY
     55 	size_of(EventClass, Data.General ),				// ALLY
     56 	size_of(EventClass, Data.MegaMission ),		// MEGAMISSION
     57 	size_of(EventClass, Data.Target ),				// IDLE
     58 	size_of(EventClass, Data.Target ),				// SCATTER
     59 	0,															// DESTRUCT
     60 	0,															// DEPLOY
     61 	size_of(EventClass, Data.Place ),				// PLACE
     62 	0,															// OPTIONS
     63 	size_of(EventClass, Data.General ),				// GAMESPEED
     64 	size_of(EventClass, Data.Specific ),			// PRODUCE
     65 	size_of(EventClass, Data.Specific.Type ),		// SUSPEND
     66 	size_of(EventClass, Data.Specific.Type ),		// ABANDON
     67 	size_of(EventClass, Data.Target ),				// PRIMARY
     68 	size_of(EventClass, Data.Special ),				// SPECIAL_PLACE
     69 	0,															// EXIT
     70 	size_of(EventClass, Data.Anim ),					// ANIMATION
     71 	size_of(EventClass, Data.Target ),				// REPAIR
     72 	size_of(EventClass, Data.Target ),				// SELL
     73 	size_of(EventClass, Data.Options ),				// SPECIAL
     74 	0,															// FRAMESYNC
     75 	0,															//	MESSAGE
     76 	size_of(EventClass, Data.FrameInfo.Delay ),	// RESPONSE_TIME
     77 	size_of(EventClass, Data.FrameInfo ),			// FRAMEINFO
     78 	size_of(EventClass, Data.NavCom ),			// ARCHIVE
     79 	size_of(EventClass, Data.Timing ),				// TIMING
     80 	size_of(EventClass, Data.ProcessTime ),		// PROCESS_TIME
     81 };
     82 
     83 char * EventClass::EventNames[EventClass::LAST_EVENT] = {
     84 	"EMPTY",
     85 	"ALLY",
     86 	"MEGAMISSION",
     87 	"IDLE",
     88 	"SCATTER",
     89 	"DESTRUCT",
     90 	"DEPLOY",
     91 	"PLACE",
     92 	"OPTIONS",
     93 	"GAMESPEED",
     94 	"PRODUCE",
     95 	"SUSPEND",
     96 	"ABANDON",
     97 	"PRIMARY",
     98 	"SPECIAL_PLACE",
     99 	"EXIT",
    100 	"ANIMATION",
    101 	"REPAIR",
    102 	"SELL",
    103 	"SPECIAL",
    104 	"FRAMESYNC",
    105 	"MESSAGE",
    106 	"RESPONSE_TIME",
    107 	"FRAMEINFO",
    108 	"ARCHIVE",
    109 	"TIMING",
    110 	"PROCESS_TIME",
    111 };
    112 
    113 
    114 /***********************************************************************************************
    115  * EventClass::EventClass -- Constructs event to transfer special flags.                       *
    116  *                                                                                             *
    117  *    This constructs an event that will transfer the special flags.                           *
    118  *                                                                                             *
    119  * INPUT:   data  -- The special flags to be transported to all linked computers.              *
    120  *                                                                                             *
    121  * OUTPUT:  none                                                                               *
    122  *                                                                                             *
    123  * WARNINGS:   none                                                                            *
    124  *                                                                                             *
    125  * HISTORY:                                                                                    *
    126  *   06/25/1995 JLB : Created.                                                                 *
    127  *=============================================================================================*/
    128 EventClass::EventClass(SpecialClass data)
    129 {
    130 	ID = Houses.ID(PlayerPtr);
    131 	Type = SPECIAL;
    132 	Frame = ::Frame;
    133 	Data.Options.Data = data;
    134 }
    135 
    136 
    137 /***********************************************************************************************
    138  * EventClass::EventClass -- Construct simple target type event.                               *
    139  *                                                                                             *
    140  *    This will construct a generic event that needs only a target parameter. The actual       *
    141  *    event and target values are specified as parameters.                                     *
    142  *                                                                                             *
    143  * INPUT:   type  -- The event type to construct.                                              *
    144  *                                                                                             *
    145  *          target-- The target value that this event is to apply to.                          *
    146  *                                                                                             *
    147  * OUTPUT:  none                                                                               *
    148  *                                                                                             *
    149  * WARNINGS:   none                                                                            *
    150  *                                                                                             *
    151  * HISTORY:                                                                                    *
    152  *   06/25/1995 JLB : Created.                                                                 *
    153  *=============================================================================================*/
    154 EventClass::EventClass(EventType type, TARGET target)
    155 {
    156 	ID = Houses.ID(PlayerPtr);
    157 	Type = type;
    158 	Frame = ::Frame;
    159 	Data.Target.Whom = target;
    160 }
    161 
    162 
    163 /***********************************************************************************************
    164  * EventClass::EventClass -- Default constructor for event objects.                            *
    165  *                                                                                             *
    166  *    This constructs a simple event object that requires no parameters other than the         *
    167  *    type of event it is.                                                                     *
    168  *                                                                                             *
    169  * INPUT:   type  -- The type of event to construct.                                           *
    170  *                                                                                             *
    171  * OUTPUT:  none                                                                               *
    172  *                                                                                             *
    173  * WARNINGS:   none                                                                            *
    174  *                                                                                             *
    175  * HISTORY:                                                                                    *
    176  *   12/27/1994 JLB : Created.                                                                 *
    177  *=============================================================================================*/
    178 EventClass::EventClass(EventType type)
    179 {
    180 	ID = Houses.ID(PlayerPtr);
    181 	Type = type;
    182 	Frame = ::Frame;
    183 }
    184 
    185 
    186 /***********************************************************************************************
    187  * EventClass::EventClass -- Constructor for general-purpose-data events.                      *
    188  *                                                                                             *
    189  * INPUT:   type  -- The type of event to construct.                                           *
    190  *            val   -- data value                                                              *
    191  *                                                                                             *
    192  * OUTPUT:  none                                                                               *
    193  *                                                                                             *
    194  * WARNINGS:   none                                                                            *
    195  *                                                                                             *
    196  * HISTORY:                                                                                    *
    197  *   12/27/1994 JLB : Created.                                                                 *
    198  *=============================================================================================*/
    199 EventClass::EventClass(EventType type, int val)
    200 {
    201 	ID = Houses.ID(PlayerPtr);
    202 	Type = type;
    203 	Data.General.Value = val;
    204 	Frame = ::Frame;
    205 }
    206 
    207 
    208 /***********************************************************************************************
    209  * EventClass::EventClass -- Constructor for navigation computer events.                       *
    210  *                                                                                             *
    211  *    Constructor for events that are used to assign the navigation computer.                  *
    212  *                                                                                             *
    213  * INPUT:   type     -- The type of event (this constructor can be used by other navigation    *
    214  *                      type events).                                                          *
    215  *                                                                                             *
    216  *          src      -- The object that the event should apply to.                             *
    217  *                                                                                             *
    218  *          dest     -- The destination (or target) that the event needs to complete.          *
    219  *                                                                                             *
    220  * OUTPUT:  none                                                                               *
    221  *                                                                                             *
    222  * WARNINGS:   none                                                                            *
    223  *                                                                                             *
    224  * HISTORY:                                                                                    *
    225  *   12/27/1994 JLB : Created.                                                                 *
    226  *=============================================================================================*/
    227 EventClass::EventClass(EventType type, TARGET src, TARGET dest)
    228 {
    229 	ID = Houses.ID(PlayerPtr);
    230 	Type = type;
    231 	Frame = ::Frame;
    232 	Data.NavCom.Whom = src;
    233 	Data.NavCom.Where = dest;
    234 }
    235 
    236 
    237 /***********************************************************************************************
    238  * EventClass::EventClass -- Event for sequencing animations.                                  *
    239  *                                                                                             *
    240  *    This constructor is used for animations that must be created through the event system.   *
    241  *                                                                                             *
    242  * INPUT:   anim  -- The animation that will be created.                                       *
    243  *                                                                                             *
    244  *          coord -- The location where the animation is to be created.                        *
    245  *                                                                                             *
    246  * OUTPUT:  none                                                                               *
    247  *                                                                                             *
    248  * WARNINGS:   none                                                                            *
    249  *                                                                                             *
    250  * HISTORY:                                                                                    *
    251  *   05/19/1995 JLB : Created.                                                                 *
    252  *=============================================================================================*/
    253 EventClass::EventClass(AnimType anim, HousesType owner, COORDINATE coord, int visible)
    254 {
    255 	ID = Houses.ID(PlayerPtr);
    256 	Type = ANIMATION;
    257 	Frame = ::Frame;
    258 	Data.Anim.What = anim;
    259 	Data.Anim.Owner = owner;
    260 	Data.Anim.Where = coord;
    261 	Data.Anim.Visible = visible;
    262 }
    263 
    264 
    265 /***********************************************************************************************
    266  * EventClass::EventClass -- Megamission assigned to unit.                                     *
    267  *                                                                                             *
    268  *    This is the event that is used to assign most missions to units. It combines both the    *
    269  *    mission and the target (navcom and tarcom).                                              *
    270  *                                                                                             *
    271  * INPUT:   src      -- The object that this mission is to apply to.                           *
    272  *                                                                                             *
    273  *          mission  -- The mission to assign to this object.                                  *
    274  *                                                                                             *
    275  *          target   -- The target to assign to this object's TarCom.                          *
    276  *                                                                                             *
    277  *          destination -- The destination to assign to this object's NavCom.                  *
    278  *                                                                                             *
    279  * OUTPUT:  none                                                                               *
    280  *                                                                                             *
    281  * WARNINGS:   none                                                                            *
    282  *                                                                                             *
    283  * HISTORY:                                                                                    *
    284  *   05/18/1995 JLB : Created.                                                                 *
    285  *=============================================================================================*/
    286 EventClass::EventClass(TARGET src, MissionType mission, TARGET target, TARGET destination)
    287 {
    288 	ID = Houses.ID(PlayerPtr);
    289 	Type = MEGAMISSION;
    290 	Frame = ::Frame;
    291 	Data.MegaMission.Whom = src;
    292 	Data.MegaMission.Mission = mission;
    293 	Data.MegaMission.Target = target;
    294 	Data.MegaMission.Destination = destination;
    295 }
    296 
    297 
    298 /***********************************************************************************************
    299  * EventClass::EventClass -- Constructor for sidebar build events.                             *
    300  *                                                                                             *
    301  *    This constructor is used for events that deal with an object type and an object ID.      *
    302  *    Typically, this is used exclusively by the sidebar.                                      *
    303  *                                                                                             *
    304  * INPUT:   type     -- The event type of this object.                                         *
    305  *                                                                                             *
    306  *          object   -- The object type number.                                                *
    307  *                                                                                             *
    308  *          id       -- The object sub-type number.                                            *
    309  *                                                                                             *
    310  * OUTPUT:  none                                                                               *
    311  *                                                                                             *
    312  * WARNINGS:   none                                                                            *
    313  *                                                                                             *
    314  * HISTORY:                                                                                    *
    315  *   05/18/1995 JLB : Created.                                                                 *
    316  *=============================================================================================*/
    317 EventClass::EventClass(EventType type, RTTIType object, int id)
    318 {
    319 	ID = Houses.ID(PlayerPtr);
    320 	Type = type;
    321 	Frame = ::Frame;
    322 	Data.Specific.Type = object;
    323 	Data.Specific.ID = id;
    324 }
    325 
    326 
    327 /***********************************************************************************************
    328  * EventClass::EventClass -- Constructor for object types affecting cells event.               *
    329  *                                                                                             *
    330  *    This constructor is used for those events that have an object type and associated cell.  *
    331  *    Typically, this is for building placement after construction has completed.              *
    332  *                                                                                             *
    333  * INPUT:   type     -- The event type for this object.                                        *
    334  *                                                                                             *
    335  *          object   -- The object type number (actual object is probably inferred from the    *
    336  *                      sidebar data).                                                         *
    337  *                                                                                             *
    338  *          cell     -- The cell location where this event is to occur.                        *
    339  *                                                                                             *
    340  * OUTPUT:  none                                                                               *
    341  *                                                                                             *
    342  * WARNINGS:   none                                                                            *
    343  *                                                                                             *
    344  * HISTORY:                                                                                    *
    345  *   05/18/1995 JLB : Created.                                                                 *
    346  *=============================================================================================*/
    347 EventClass::EventClass(EventType type, RTTIType object, CELL cell)
    348 {
    349 	ID = Houses.ID(PlayerPtr);
    350 	Type = type;
    351 	Frame = ::Frame;
    352 	Data.Place.Type = object;
    353 	Data.Place.Cell = cell;
    354 }
    355 
    356 
    357 /***********************************************************************************************
    358  * EventClass::EventClass -- Construct an id and cell based event.                             *
    359  *                                                                                             *
    360  *    This constructor is used for those events that require an ID number and a cell location. *
    361  *                                                                                             *
    362  * INPUT:   type  -- The event type this will be.                                              *
    363  *                                                                                             *
    364  *          id    -- The arbitrary id number to assign.                                        *
    365  *                                                                                             *
    366  *          cell  -- The location for this event.                                              *
    367  *                                                                                             *
    368  * OUTPUT:  none                                                                               *
    369  *                                                                                             *
    370  * WARNINGS:   none                                                                            *
    371  *                                                                                             *
    372  * HISTORY:                                                                                    *
    373  *   05/18/1995 JLB : Created.                                                                 *
    374  *=============================================================================================*/
    375 EventClass::EventClass(EventType type, int id, CELL cell)
    376 {
    377 	ID = Houses.ID(PlayerPtr);
    378 	Type = type;
    379 	Frame = ::Frame;
    380 	Data.Special.ID 	= id;
    381 	Data.Special.Cell = cell;
    382 }
    383 
    384 
    385 /***********************************************************************************************
    386  * EventClass::Execute -- Execute a queued command.                                            *
    387  *                                                                                             *
    388  *    This routine executes an event. The even must already have been confirmed by any         *
    389  *    remote machine before calling this routine.                                              *
    390  *                                                                                             *
    391  * INPUT:   none                                                                               *
    392  *                                                                                             *
    393  * OUTPUT:  none                                                                               *
    394  *                                                                                             *
    395  * WARNINGS:   none                                                                            *
    396  *                                                                                             *
    397  * HISTORY:                                                                                    *
    398  *   12/27/1994 JLB : Created.                                                                 *
    399  *=============================================================================================*/
    400 void EventClass::Execute(void)
    401 {
    402 	TechnoClass * techno;
    403 	AnimClass * anim = 0;
    404 	HouseClass * house = 0;
    405 	char txt[80];
    406 	int i;
    407 //#if (0)
    408 if (Type < 0 || Type > PROCESS_TIME){
    409 char tempbuf[128];
    410 sprintf (tempbuf, "Packet type %d received\n", Type);
    411 CCDebugString (tempbuf);
    412 
    413 sprintf (tempbuf, "	ID = %d\n", ID);
    414 CCDebugString (tempbuf);
    415 
    416 sprintf (tempbuf, "	Frame = %d\n", Frame);
    417 CCDebugString (tempbuf);
    418 
    419 sprintf (tempbuf, "	MPlayer ID = %d\n", MPlayerID);
    420 CCDebugString (tempbuf);
    421 
    422 }
    423 //#endif	//(0)
    424 
    425 
    426 	switch (Type) {
    427 		/*
    428 		**	Update the archive target for this building.
    429 		*/
    430 		case ARCHIVE:
    431 			techno = As_Techno(Data.NavCom.Whom);
    432 			if (techno && techno->IsActive) {
    433 				techno->ArchiveTarget = Data.NavCom.Where;
    434 			}
    435 			break;
    436 
    437 		/*
    438 		**	Make or break alliance.
    439 		*/
    440 		case ALLY:
    441 			house = Houses.Raw_Ptr(Data.General.Value);
    442 			if (Houses.Raw_Ptr(ID)->Is_Ally(house)) {
    443 				Houses.Raw_Ptr(ID)->Make_Enemy((HousesType)Data.General.Value);
    444 			} else {
    445 				Houses.Raw_Ptr(ID)->Make_Ally((HousesType)Data.General.Value);
    446 			}
    447 			break;
    448 
    449 		/*
    450 		**	Special self destruct action requested. This is active in the multiplayer mode.
    451 		*/
    452 		case DESTRUCT:
    453 CCDebugString ("C&C95 - Resignation packet received\n");
    454 			Houses.Raw_Ptr(ID)->Flag_To_Die();
    455 			Houses.Raw_Ptr(ID)->Resigned = true;
    456 			break;
    457 
    458 		/*
    459 		**	Update the special control flags. This is necessary so that in a multiplay
    460 		**	game, all machines will agree on the rules. If these options change during
    461 		**	game play, then all players are informed that options have changed.
    462 		*/
    463 		case SPECIAL:
    464 			{
    465 				Special = Data.Options.Data;
    466 				HouseClass * house = Houses.Raw_Ptr(ID);
    467 
    468 				sprintf(txt, Text_String(TXT_SPECIAL_WARNING), house->Name);
    469 				Messages.Add_Message(txt, MPlayerTColors[house->RemapColor],
    470 					TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1200, 0, 0);
    471 				Map.Flag_To_Redraw(false);
    472 			}
    473 			break;
    474 
    475 		/*
    476 		**	Starts or stops repair on the specified object. This event is triggered by the
    477 		**	player clicking the repair wrench on a building.
    478 		*/
    479 		case REPAIR:
    480 CCDebugString ("C&C95 - Repair packet received\n");
    481 			techno = As_Techno(Data.Target.Whom);
    482 			if (techno && techno->IsActive) {
    483 				techno->Repair(-1);
    484 			}
    485 			break;
    486 
    487 		/*
    488 		**	Tells a building/unit to sell. This event is triggered by the player clicking the
    489 		**	sell animating cursor over the building or unit.
    490 		*/
    491 		case SELL:
    492 CCDebugString ("C&C95 - Sell packet received\n");
    493 			techno = As_Techno(Data.Target.Whom);
    494 			if (techno && techno->IsActive && techno->House == Houses.Raw_Ptr(ID)) {
    495 				techno->Sell_Back(-1);
    496 			} else {
    497 				if (Is_Target_Cell(Data.Target.Whom)) {
    498 					Houses.Raw_Ptr(ID)->Sell_Wall(As_Cell(Data.Target.Whom));
    499 				}
    500 			}
    501 			break;
    502 
    503 		/*
    504 		**	This even is used to trigger an animation that is generated as a direct
    505 		**	result of player intervention.
    506 		*/
    507 		case ANIMATION:
    508 			anim = new AnimClass(Data.Anim.What, Data.Anim.Where);
    509 			if (anim) {
    510 				anim->Set_Owner(Data.Anim.Owner);
    511 
    512 				if (Special.IsVisibleTarget)
    513 				{
    514 					anim->Set_Visible_Flags(static_cast<unsigned int>(-1));
    515 				}
    516 				else
    517 				{
    518 					anim->Set_Visible_Flags(static_cast<unsigned int>(Data.Anim.Visible));
    519 				}
    520 
    521 				/*
    522 				**	Beacons have a 30-second kill time.
    523 				*/
    524 				if (Data.Anim.What == ANIM_BEACON) {
    525 					FILETIME ft;
    526 					GetSystemTimeAsFileTime(&ft);
    527 
    528 					unsigned long long kill_time = ((unsigned long long)ft.dwLowDateTime + ((unsigned long long)ft.dwHighDateTime << 32ULL)) + 300000000ULL;
    529 					anim->Kill_At(kill_time);
    530 				}
    531 			}
    532 			break;
    533 
    534 		/*
    535 		**	This event will place the specified object at the specified location.
    536 		**	The event is used to place newly constructed buildings down on the map. The
    537 		**	object type is specified. From this object type, the house can determine the
    538 		**	exact factory and real object pointer to use.
    539 		*/
    540 		case PLACE:
    541 CCDebugString ("C&C95 - Place packet received\n");
    542 			Houses.Raw_Ptr(ID)->Place_Object(Data.Place.Type, Data.Place.Cell);
    543 			break;
    544 
    545 		/*
    546 		**	This event starts production of the speicified object type. The house can
    547 		**	determine from the type and ID value, what object to begin production on and
    548 		**	what factory to use.
    549 		*/
    550 		case PRODUCE:
    551 CCDebugString ("C&C95 - Produce packet received\n");
    552 			Houses.Raw_Ptr(ID)->Begin_Production(Data.Specific.Type, Data.Specific.ID);
    553 			break;
    554 
    555 		/*
    556 		**	This event is generated when the player puts production on hold. From the
    557 		**	object type, the factory can be inferred.
    558 		*/
    559 		case SUSPEND:
    560 CCDebugString ("C&C95 - Suspend packet received\n");
    561 			Houses.Raw_Ptr(ID)->Suspend_Production(Data.Specific.Type);
    562 			break;
    563 
    564 		/*
    565 		**	This event is generated when the player cancels production of the specified
    566 		**	object type. From the object type, the exact factory can be inferred.
    567 		*/
    568 		case ABANDON:
    569 CCDebugString ("C&C95 - Abandon packet received\n");
    570 			Houses.Raw_Ptr(ID)->Abandon_Production(Data.Specific.Type);
    571 			break;
    572 
    573 		/*
    574 		**	Toggles the primary factory state of the specified building.
    575 		*/
    576 		case PRIMARY:{
    577 CCDebugString ("C&C95 - Primary building packet received\n");
    578 				BuildingClass * building = As_Building(Data.Target.Whom);
    579 				if (building && building->IsActive) {
    580 					building->Toggle_Primary();
    581 				}
    582 			}
    583 			break;
    584 
    585 		/*
    586 		**	This is the general purpose mission control event. Most player
    587 		**	action routes through this event. It sets a unit's mission, TarCom,
    588 		**	and NavCom to the values specified.
    589 		*/
    590 		case MEGAMISSION:
    591 			techno = As_Techno(Data.MegaMission.Whom);
    592 			if (techno && techno->IsActive) {
    593 
    594 				/*
    595 				**	Fetch a pointer to the object of the mission.
    596 				*/
    597 				ObjectClass * object;
    598 				if (Target_Legal(Data.MegaMission.Target)) {
    599 					object = As_Object(Data.MegaMission.Target);
    600 				} else {
    601 					object = As_Object(Data.MegaMission.Destination);
    602 				}
    603 
    604 				/*
    605 				**	Break any existing team contact, since it is now invalid.
    606 				*/
    607 				if (!techno->IsTethered) {
    608 					techno->Transmit_Message(RADIO_OVER_OUT);
    609 				}
    610 				switch (techno->What_Am_I()) {
    611 					case RTTI_INFANTRY:
    612 					case RTTI_UNIT:
    613 						if (((FootClass *)techno)->Team) {
    614 							((FootClass *)techno)->Team->Remove((FootClass *)techno);
    615 						}
    616 						break;
    617 				}
    618 
    619 				if (object) {
    620 					
    621 					// 2019/09/20 JAS - Added record of who clicked on the object
    622 					HouseClass* house = Houses.Raw_Ptr(ID);
    623 					bool is_allied = house != nullptr && house->Is_Ally(techno);
    624 					if (is_allied || Special.IsVisibleTarget) {
    625 						object->Clicked_As_Target((HousesType)ID); 
    626 					}
    627 				}
    628 				techno->Assign_Mission(Data.MegaMission.Mission);
    629 
    630 				/*
    631 				**	Guard area mode is handled with care. The specified target is actually
    632 				**	assigned as the location that should be guarded. In addition, the
    633 				**	movement destination is immediately set to this new location.
    634 				*/
    635 				if (Data.MegaMission.Mission == MISSION_GUARD_AREA &&
    636 //					Target_Legal(Data.MegaMission.Target) &&
    637 					(techno->What_Am_I() == RTTI_INFANTRY || techno->What_Am_I() == RTTI_UNIT || techno->What_Am_I() == RTTI_AIRCRAFT)) {
    638 
    639 					techno->ArchiveTarget = Data.MegaMission.Target;
    640 					techno->Assign_Target(TARGET_NONE);
    641 					techno->Assign_Destination(Data.MegaMission.Target);
    642 				} else if (Data.MegaMission.Mission == MISSION_ENTER &&
    643 							object != NULL &&
    644 							object->What_Am_I() == RTTI_BUILDING &&
    645 							*((BuildingClass*)object) == STRUCT_REFINERY) {
    646 					techno->Transmit_Message(RADIO_HELLO, (BuildingClass*)object);
    647 					techno->Assign_Destination(TARGET_NONE);
    648 				} else {
    649 					techno->Assign_Target(Data.MegaMission.Target);
    650 					techno->Assign_Destination(Data.MegaMission.Destination);
    651 				}
    652 
    653 #ifdef NEVER
    654 				if ((techno->What_Am_I() == RTTI_UNIT || techno->What_Am_I() == RTTI_INFANTRY) &&
    655 						Data.MegaMission.Mission == MISSION_GUARD_AREA) {
    656 
    657 					techno->ArchiveTarget = Data.MegaMission.Destination;
    658 				}
    659 #endif
    660 			}
    661 			break;
    662 
    663 		/*
    664 		**	Request that the unit/infantry/aircraft go into idle mode.
    665 		*/
    666 		case IDLE:
    667 			techno = As_Techno(Data.Target.Whom);
    668 			if (techno && techno->IsActive && !techno->IsInLimbo && !techno->IsTethered) {
    669 				techno->Assign_Destination(TARGET_NONE);
    670 				techno->Assign_Target(TARGET_NONE);
    671 				techno->Enter_Idle_Mode();
    672 			}
    673 			break;
    674 
    675 		/*
    676 		**	Request that the unit/infantry/aircraft scatter from its current location.
    677 		*/
    678 		case SCATTER:
    679 			techno = As_Techno(Data.Target.Whom);
    680 			if (techno && techno->IsActive && !techno->IsInLimbo && !techno->IsTethered) {
    681 				techno->Scatter(0, true);
    682 			}
    683 			break;
    684 
    685 		/*
    686 		**	If we are placing down the ion cannon blast then lets take
    687 		** care of it.
    688 		*/
    689 		case SPECIAL_PLACE:
    690 CCDebugString ("C&C95 - Special blast packet received\n");
    691 			Houses.Raw_Ptr(ID)->Place_Special_Blast((SpecialWeaponType)Data.Special.ID, Data.Special.Cell);
    692 			break;
    693 
    694 		/*
    695 		**	Exit the game.
    696 		** Give parting message while palette is fading to black.
    697 		*/
    698 		case EXIT:
    699 CCDebugString ("C&C95 - Exit game packet received\n");
    700 			Theme.Queue_Song(THEME_NONE);
    701 			Stop_Speaking();
    702 			Speak(VOX_CONTROL_EXIT);
    703 			while (Is_Speaking()) {
    704 				Call_Back();
    705 			}
    706 			GameActive = false;
    707 			break;
    708 
    709 		/*
    710 		**	Process the options menu.
    711 		*/
    712 		case OPTIONS:
    713 			SpecialDialog = SDLG_OPTIONS;
    714 			break;
    715 
    716 		/*
    717 		**	Process the options Game Speed
    718 		*/
    719 		case GAMESPEED:
    720 CCDebugString ("C&C95 - Game speed packet received\n");
    721 			Options.GameSpeed = Data.General.Value;
    722 			break;
    723 
    724 		/*
    725 		**	Adjust connection timing for multiplayer games
    726 		*/
    727 		case RESPONSE_TIME:
    728 char flip[128];
    729 sprintf (flip, "C&C95 - Changing MaxAhead to %d frames\n", Data.FrameInfo.Delay);
    730 CCDebugString (flip);
    731 			MPlayerMaxAhead = Data.FrameInfo.Delay;
    732 			break;
    733 
    734 		//
    735 		// This event tells all systems to use new timing values.  It's like
    736 		// RESPONSE_TIME, only it works.  It's only used with the
    737 		// COMM_MULTI_E_COMP protocol.
    738 		//
    739 		case TIMING:
    740 CCDebugString ("C&C95 - Timing packet received\n");
    741 //#if(TIMING_FIX)
    742 			//
    743 			// If MaxAhead is about to increase, we're vulnerable to a Packet-
    744 			// Received-Too-Late error, if any system generates an event after
    745 			// this TIMING event, but before it executes.  So, record the
    746 			// period of vulnerability's frame start & end values, so we
    747 			// can reschedule these events to execute after it's over.
    748 			//
    749 			if (Data.Timing.MaxAhead > MPlayerMaxAhead) {
    750 				NewMaxAheadFrame1 = Frame;
    751 				NewMaxAheadFrame2 = Frame + Data.Timing.MaxAhead;
    752 			}
    753 //#endif
    754 
    755 			DesiredFrameRate = Data.Timing.DesiredFrameRate;
    756 			MPlayerMaxAhead = Data.Timing.MaxAhead;
    757 
    758 sprintf (flip, "C&C95 -  Timing packet: DesiredFrameRate = %d\n", Data.Timing.DesiredFrameRate);
    759 CCDebugString (flip);
    760 sprintf (flip, "C&C95 -  Timing packet: MaxAhead = %d\n", Data.Timing.MaxAhead);
    761 CCDebugString (flip);
    762 
    763 			/*
    764 			** If spawned from WChat then we should be getting poked every minute. If not then
    765 			** deliberately break the max ahead value
    766 			*/
    767 			if (Special.IsFromWChat){
    768 				MPlayerMaxAhead += DDEServer.Time_Since_Heartbeat()/(70*60);
    769 //if (DDEServer.Time_Since_Heartbeat() >= 70*60) CCDebugString ("C&C95 - Missed a heartbeat\n");
    770 			}
    771 			break;
    772 
    773 		//
    774 		// This event tells all systems what the other systems' process
    775 		// timing requirements are; it's used to compute a desired frame rate
    776 		// for the game.
    777 		//
    778 		case PROCESS_TIME:
    779 			for (i = 0; i < MPlayerCount; i++) {
    780 				if (MPlayerID == ::MPlayerID[i]) {
    781 					TheirProcessTime[i] = Data.ProcessTime.AverageTicks;
    782 
    783 char flip[128];
    784 sprintf (flip, "C&C95 - Received PROCESS_TIME packet of %04x ticks\n", Data.ProcessTime.AverageTicks);
    785 CCDebugString (flip);
    786 
    787 					break;
    788 				}
    789 			}
    790 			break;
    791 
    792 		/*
    793 		**	Default: do nothing.
    794 		*/
    795 		default:
    796 			break;
    797 	}
    798 }