123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
- // software: you can redistribute it and/or modify it under the terms of
- // the GNU General Public License as published by the Free Software Foundation,
- // either version 3 of the License, or (at your option) any later version.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- /* $Header: F:\projects\c&c\vcs\code\event.cpv 2.17 16 Oct 1995 16:50:28 JOE_BOSTIC $ */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : EVENT.CPP *
- * *
- * Programmer : Joe L. Bostic *
- * *
- * Start Date : 12/09/94 *
- * *
- * Last Update : June 25, 1995 [JLB] *
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * EventClass::EventClass -- Construct an id and cell based event. *
- * EventClass::EventClass -- Construct simple target type event. *
- * EventClass::EventClass -- Constructor for mission change events. *
- * EventClass::EventClass -- Constructor for navigation computer events. *
- * EventClass::EventClass -- Constructor for object types affecting cells event. *
- * EventClass::EventClass -- Constructor for sidebar build events. *
- * EventClass::EventClass -- Constructs event to transfer special flags. *
- * EventClass::EventClass -- Default constructor for event objects. *
- * EventClass::EventClass -- Event for sequencing animations. *
- * EventClass::EventClass -- Megamission assigned to unit. *
- * EventClass::Execute -- Execute a queued command. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include "ccdde.h"
- /***************************************************************************
- ** Table of what data is really used in the EventClass struct for different
- ** events. This table must be kept current with the EventType enum.
- */
- unsigned char EventClass::EventLength[EventClass::LAST_EVENT] = {
- 0, // EMPTY
- size_of(EventClass, Data.General ), // ALLY
- size_of(EventClass, Data.MegaMission ), // MEGAMISSION
- size_of(EventClass, Data.Target ), // IDLE
- size_of(EventClass, Data.Target ), // SCATTER
- 0, // DESTRUCT
- 0, // DEPLOY
- size_of(EventClass, Data.Place ), // PLACE
- 0, // OPTIONS
- size_of(EventClass, Data.General ), // GAMESPEED
- size_of(EventClass, Data.Specific ), // PRODUCE
- size_of(EventClass, Data.Specific.Type ), // SUSPEND
- size_of(EventClass, Data.Specific.Type ), // ABANDON
- size_of(EventClass, Data.Target ), // PRIMARY
- size_of(EventClass, Data.Special ), // SPECIAL_PLACE
- 0, // EXIT
- size_of(EventClass, Data.Anim ), // ANIMATION
- size_of(EventClass, Data.Target ), // REPAIR
- size_of(EventClass, Data.Target ), // SELL
- size_of(EventClass, Data.Options ), // SPECIAL
- 0, // FRAMESYNC
- 0, // MESSAGE
- size_of(EventClass, Data.FrameInfo.Delay ), // RESPONSE_TIME
- size_of(EventClass, Data.FrameInfo ), // FRAMEINFO
- size_of(EventClass, Data.NavCom ), // ARCHIVE
- size_of(EventClass, Data.Timing ), // TIMING
- size_of(EventClass, Data.ProcessTime ), // PROCESS_TIME
- };
- char * EventClass::EventNames[EventClass::LAST_EVENT] = {
- "EMPTY",
- "ALLY",
- "MEGAMISSION",
- "IDLE",
- "SCATTER",
- "DESTRUCT",
- "DEPLOY",
- "PLACE",
- "OPTIONS",
- "GAMESPEED",
- "PRODUCE",
- "SUSPEND",
- "ABANDON",
- "PRIMARY",
- "SPECIAL_PLACE",
- "EXIT",
- "ANIMATION",
- "REPAIR",
- "SELL",
- "SPECIAL",
- "FRAMESYNC",
- "MESSAGE",
- "RESPONSE_TIME",
- "FRAMEINFO",
- "ARCHIVE",
- "TIMING",
- "PROCESS_TIME",
- };
- /***********************************************************************************************
- * EventClass::EventClass -- Constructs event to transfer special flags. *
- * *
- * This constructs an event that will transfer the special flags. *
- * *
- * INPUT: data -- The special flags to be transported to all linked computers. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/25/1995 JLB : Created. *
- *=============================================================================================*/
- EventClass::EventClass(SpecialClass data)
- {
- ID = Houses.ID(PlayerPtr);
- Type = SPECIAL;
- Frame = ::Frame;
- Data.Options.Data = data;
- }
- /***********************************************************************************************
- * EventClass::EventClass -- Construct simple target type event. *
- * *
- * This will construct a generic event that needs only a target parameter. The actual *
- * event and target values are specified as parameters. *
- * *
- * INPUT: type -- The event type to construct. *
- * *
- * target-- The target value that this event is to apply to. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/25/1995 JLB : Created. *
- *=============================================================================================*/
- EventClass::EventClass(EventType type, TARGET target)
- {
- ID = Houses.ID(PlayerPtr);
- Type = type;
- Frame = ::Frame;
- Data.Target.Whom = target;
- }
- /***********************************************************************************************
- * EventClass::EventClass -- Default constructor for event objects. *
- * *
- * This constructs a simple event object that requires no parameters other than the *
- * type of event it is. *
- * *
- * INPUT: type -- The type of event to construct. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 12/27/1994 JLB : Created. *
- *=============================================================================================*/
- EventClass::EventClass(EventType type)
- {
- ID = Houses.ID(PlayerPtr);
- Type = type;
- Frame = ::Frame;
- }
- /***********************************************************************************************
- * EventClass::EventClass -- Constructor for general-purpose-data events. *
- * *
- * INPUT: type -- The type of event to construct. *
- * val -- data value *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 12/27/1994 JLB : Created. *
- *=============================================================================================*/
- EventClass::EventClass(EventType type, int val)
- {
- ID = Houses.ID(PlayerPtr);
- Type = type;
- Data.General.Value = val;
- Frame = ::Frame;
- }
- /***********************************************************************************************
- * EventClass::EventClass -- Constructor for navigation computer events. *
- * *
- * Constructor for events that are used to assign the navigation computer. *
- * *
- * INPUT: type -- The type of event (this constructor can be used by other navigation *
- * type events). *
- * *
- * src -- The object that the event should apply to. *
- * *
- * dest -- The destination (or target) that the event needs to complete. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 12/27/1994 JLB : Created. *
- *=============================================================================================*/
- EventClass::EventClass(EventType type, TARGET src, TARGET dest)
- {
- ID = Houses.ID(PlayerPtr);
- Type = type;
- Frame = ::Frame;
- Data.NavCom.Whom = src;
- Data.NavCom.Where = dest;
- }
- /***********************************************************************************************
- * EventClass::EventClass -- Event for sequencing animations. *
- * *
- * This constructor is used for animations that must be created through the event system. *
- * *
- * INPUT: anim -- The animation that will be created. *
- * *
- * coord -- The location where the animation is to be created. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/19/1995 JLB : Created. *
- *=============================================================================================*/
- EventClass::EventClass(AnimType anim, HousesType owner, COORDINATE coord, int visible)
- {
- ID = Houses.ID(PlayerPtr);
- Type = ANIMATION;
- Frame = ::Frame;
- Data.Anim.What = anim;
- Data.Anim.Owner = owner;
- Data.Anim.Where = coord;
- Data.Anim.Visible = visible;
- }
- /***********************************************************************************************
- * EventClass::EventClass -- Megamission assigned to unit. *
- * *
- * This is the event that is used to assign most missions to units. It combines both the *
- * mission and the target (navcom and tarcom). *
- * *
- * INPUT: src -- The object that this mission is to apply to. *
- * *
- * mission -- The mission to assign to this object. *
- * *
- * target -- The target to assign to this object's TarCom. *
- * *
- * destination -- The destination to assign to this object's NavCom. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/18/1995 JLB : Created. *
- *=============================================================================================*/
- EventClass::EventClass(TARGET src, MissionType mission, TARGET target, TARGET destination)
- {
- ID = Houses.ID(PlayerPtr);
- Type = MEGAMISSION;
- Frame = ::Frame;
- Data.MegaMission.Whom = src;
- Data.MegaMission.Mission = mission;
- Data.MegaMission.Target = target;
- Data.MegaMission.Destination = destination;
- }
- /***********************************************************************************************
- * EventClass::EventClass -- Constructor for sidebar build events. *
- * *
- * This constructor is used for events that deal with an object type and an object ID. *
- * Typically, this is used exclusively by the sidebar. *
- * *
- * INPUT: type -- The event type of this object. *
- * *
- * object -- The object type number. *
- * *
- * id -- The object sub-type number. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/18/1995 JLB : Created. *
- *=============================================================================================*/
- EventClass::EventClass(EventType type, RTTIType object, int id)
- {
- ID = Houses.ID(PlayerPtr);
- Type = type;
- Frame = ::Frame;
- Data.Specific.Type = object;
- Data.Specific.ID = id;
- }
- /***********************************************************************************************
- * EventClass::EventClass -- Constructor for object types affecting cells event. *
- * *
- * This constructor is used for those events that have an object type and associated cell. *
- * Typically, this is for building placement after construction has completed. *
- * *
- * INPUT: type -- The event type for this object. *
- * *
- * object -- The object type number (actual object is probably inferred from the *
- * sidebar data). *
- * *
- * cell -- The cell location where this event is to occur. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/18/1995 JLB : Created. *
- *=============================================================================================*/
- EventClass::EventClass(EventType type, RTTIType object, CELL cell)
- {
- ID = Houses.ID(PlayerPtr);
- Type = type;
- Frame = ::Frame;
- Data.Place.Type = object;
- Data.Place.Cell = cell;
- }
- /***********************************************************************************************
- * EventClass::EventClass -- Construct an id and cell based event. *
- * *
- * This constructor is used for those events that require an ID number and a cell location. *
- * *
- * INPUT: type -- The event type this will be. *
- * *
- * id -- The arbitrary id number to assign. *
- * *
- * cell -- The location for this event. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/18/1995 JLB : Created. *
- *=============================================================================================*/
- EventClass::EventClass(EventType type, int id, CELL cell)
- {
- ID = Houses.ID(PlayerPtr);
- Type = type;
- Frame = ::Frame;
- Data.Special.ID = id;
- Data.Special.Cell = cell;
- }
- /***********************************************************************************************
- * EventClass::Execute -- Execute a queued command. *
- * *
- * This routine executes an event. The even must already have been confirmed by any *
- * remote machine before calling this routine. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 12/27/1994 JLB : Created. *
- *=============================================================================================*/
- void EventClass::Execute(void)
- {
- TechnoClass * techno;
- AnimClass * anim = 0;
- HouseClass * house = 0;
- char txt[80];
- int i;
- //#if (0)
- if (Type < 0 || Type > PROCESS_TIME){
- char tempbuf[128];
- sprintf (tempbuf, "Packet type %d received\n", Type);
- CCDebugString (tempbuf);
- sprintf (tempbuf, " ID = %d\n", ID);
- CCDebugString (tempbuf);
- sprintf (tempbuf, " Frame = %d\n", Frame);
- CCDebugString (tempbuf);
- sprintf (tempbuf, " MPlayer ID = %d\n", MPlayerID);
- CCDebugString (tempbuf);
- }
- //#endif //(0)
- switch (Type) {
- /*
- ** Update the archive target for this building.
- */
- case ARCHIVE:
- techno = As_Techno(Data.NavCom.Whom);
- if (techno && techno->IsActive) {
- techno->ArchiveTarget = Data.NavCom.Where;
- }
- break;
- /*
- ** Make or break alliance.
- */
- case ALLY:
- house = Houses.Raw_Ptr(Data.General.Value);
- if (Houses.Raw_Ptr(ID)->Is_Ally(house)) {
- Houses.Raw_Ptr(ID)->Make_Enemy((HousesType)Data.General.Value);
- } else {
- Houses.Raw_Ptr(ID)->Make_Ally((HousesType)Data.General.Value);
- }
- break;
- /*
- ** Special self destruct action requested. This is active in the multiplayer mode.
- */
- case DESTRUCT:
- CCDebugString ("C&C95 - Resignation packet received\n");
- Houses.Raw_Ptr(ID)->Flag_To_Die();
- Houses.Raw_Ptr(ID)->Resigned = true;
- break;
- /*
- ** Update the special control flags. This is necessary so that in a multiplay
- ** game, all machines will agree on the rules. If these options change during
- ** game play, then all players are informed that options have changed.
- */
- case SPECIAL:
- {
- Special = Data.Options.Data;
- HouseClass * house = Houses.Raw_Ptr(ID);
- sprintf(txt, Text_String(TXT_SPECIAL_WARNING), house->Name);
- Messages.Add_Message(txt, MPlayerTColors[house->RemapColor],
- TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW, 1200, 0, 0);
- Map.Flag_To_Redraw(false);
- }
- break;
- /*
- ** Starts or stops repair on the specified object. This event is triggered by the
- ** player clicking the repair wrench on a building.
- */
- case REPAIR:
- CCDebugString ("C&C95 - Repair packet received\n");
- techno = As_Techno(Data.Target.Whom);
- if (techno && techno->IsActive) {
- techno->Repair(-1);
- }
- break;
- /*
- ** Tells a building/unit to sell. This event is triggered by the player clicking the
- ** sell animating cursor over the building or unit.
- */
- case SELL:
- CCDebugString ("C&C95 - Sell packet received\n");
- techno = As_Techno(Data.Target.Whom);
- if (techno && techno->IsActive && techno->House == Houses.Raw_Ptr(ID)) {
- techno->Sell_Back(-1);
- } else {
- if (Is_Target_Cell(Data.Target.Whom)) {
- Houses.Raw_Ptr(ID)->Sell_Wall(As_Cell(Data.Target.Whom));
- }
- }
- break;
- /*
- ** This even is used to trigger an animation that is generated as a direct
- ** result of player intervention.
- */
- case ANIMATION:
- anim = new AnimClass(Data.Anim.What, Data.Anim.Where);
- if (anim) {
- anim->Set_Owner(Data.Anim.Owner);
- if (Special.IsVisibleTarget)
- {
- anim->Set_Visible_Flags(static_cast<unsigned int>(-1));
- }
- else
- {
- anim->Set_Visible_Flags(static_cast<unsigned int>(Data.Anim.Visible));
- }
- /*
- ** Beacons have a 30-second kill time.
- */
- if (Data.Anim.What == ANIM_BEACON) {
- FILETIME ft;
- GetSystemTimeAsFileTime(&ft);
- unsigned long long kill_time = ((unsigned long long)ft.dwLowDateTime + ((unsigned long long)ft.dwHighDateTime << 32ULL)) + 300000000ULL;
- anim->Kill_At(kill_time);
- }
- }
- break;
- /*
- ** This event will place the specified object at the specified location.
- ** The event is used to place newly constructed buildings down on the map. The
- ** object type is specified. From this object type, the house can determine the
- ** exact factory and real object pointer to use.
- */
- case PLACE:
- CCDebugString ("C&C95 - Place packet received\n");
- Houses.Raw_Ptr(ID)->Place_Object(Data.Place.Type, Data.Place.Cell);
- break;
- /*
- ** This event starts production of the speicified object type. The house can
- ** determine from the type and ID value, what object to begin production on and
- ** what factory to use.
- */
- case PRODUCE:
- CCDebugString ("C&C95 - Produce packet received\n");
- Houses.Raw_Ptr(ID)->Begin_Production(Data.Specific.Type, Data.Specific.ID);
- break;
- /*
- ** This event is generated when the player puts production on hold. From the
- ** object type, the factory can be inferred.
- */
- case SUSPEND:
- CCDebugString ("C&C95 - Suspend packet received\n");
- Houses.Raw_Ptr(ID)->Suspend_Production(Data.Specific.Type);
- break;
- /*
- ** This event is generated when the player cancels production of the specified
- ** object type. From the object type, the exact factory can be inferred.
- */
- case ABANDON:
- CCDebugString ("C&C95 - Abandon packet received\n");
- Houses.Raw_Ptr(ID)->Abandon_Production(Data.Specific.Type);
- break;
- /*
- ** Toggles the primary factory state of the specified building.
- */
- case PRIMARY:{
- CCDebugString ("C&C95 - Primary building packet received\n");
- BuildingClass * building = As_Building(Data.Target.Whom);
- if (building && building->IsActive) {
- building->Toggle_Primary();
- }
- }
- break;
- /*
- ** This is the general purpose mission control event. Most player
- ** action routes through this event. It sets a unit's mission, TarCom,
- ** and NavCom to the values specified.
- */
- case MEGAMISSION:
- techno = As_Techno(Data.MegaMission.Whom);
- if (techno && techno->IsActive) {
- /*
- ** Fetch a pointer to the object of the mission.
- */
- ObjectClass * object;
- if (Target_Legal(Data.MegaMission.Target)) {
- object = As_Object(Data.MegaMission.Target);
- } else {
- object = As_Object(Data.MegaMission.Destination);
- }
- /*
- ** Break any existing team contact, since it is now invalid.
- */
- if (!techno->IsTethered) {
- techno->Transmit_Message(RADIO_OVER_OUT);
- }
- switch (techno->What_Am_I()) {
- case RTTI_INFANTRY:
- case RTTI_UNIT:
- if (((FootClass *)techno)->Team) {
- ((FootClass *)techno)->Team->Remove((FootClass *)techno);
- }
- break;
- }
- if (object) {
-
- // 2019/09/20 JAS - Added record of who clicked on the object
- HouseClass* house = Houses.Raw_Ptr(ID);
- bool is_allied = house != nullptr && house->Is_Ally(techno);
- if (is_allied || Special.IsVisibleTarget) {
- object->Clicked_As_Target((HousesType)ID);
- }
- }
- techno->Assign_Mission(Data.MegaMission.Mission);
- /*
- ** Guard area mode is handled with care. The specified target is actually
- ** assigned as the location that should be guarded. In addition, the
- ** movement destination is immediately set to this new location.
- */
- if (Data.MegaMission.Mission == MISSION_GUARD_AREA &&
- // Target_Legal(Data.MegaMission.Target) &&
- (techno->What_Am_I() == RTTI_INFANTRY || techno->What_Am_I() == RTTI_UNIT || techno->What_Am_I() == RTTI_AIRCRAFT)) {
- techno->ArchiveTarget = Data.MegaMission.Target;
- techno->Assign_Target(TARGET_NONE);
- techno->Assign_Destination(Data.MegaMission.Target);
- } else if (Data.MegaMission.Mission == MISSION_ENTER &&
- object != NULL &&
- object->What_Am_I() == RTTI_BUILDING &&
- *((BuildingClass*)object) == STRUCT_REFINERY) {
- techno->Transmit_Message(RADIO_HELLO, (BuildingClass*)object);
- techno->Assign_Destination(TARGET_NONE);
- } else {
- techno->Assign_Target(Data.MegaMission.Target);
- techno->Assign_Destination(Data.MegaMission.Destination);
- }
- #ifdef NEVER
- if ((techno->What_Am_I() == RTTI_UNIT || techno->What_Am_I() == RTTI_INFANTRY) &&
- Data.MegaMission.Mission == MISSION_GUARD_AREA) {
- techno->ArchiveTarget = Data.MegaMission.Destination;
- }
- #endif
- }
- break;
- /*
- ** Request that the unit/infantry/aircraft go into idle mode.
- */
- case IDLE:
- techno = As_Techno(Data.Target.Whom);
- if (techno && techno->IsActive && !techno->IsInLimbo && !techno->IsTethered) {
- techno->Assign_Destination(TARGET_NONE);
- techno->Assign_Target(TARGET_NONE);
- techno->Enter_Idle_Mode();
- }
- break;
- /*
- ** Request that the unit/infantry/aircraft scatter from its current location.
- */
- case SCATTER:
- techno = As_Techno(Data.Target.Whom);
- if (techno && techno->IsActive && !techno->IsInLimbo && !techno->IsTethered) {
- techno->Scatter(0, true);
- }
- break;
- /*
- ** If we are placing down the ion cannon blast then lets take
- ** care of it.
- */
- case SPECIAL_PLACE:
- CCDebugString ("C&C95 - Special blast packet received\n");
- Houses.Raw_Ptr(ID)->Place_Special_Blast((SpecialWeaponType)Data.Special.ID, Data.Special.Cell);
- break;
- /*
- ** Exit the game.
- ** Give parting message while palette is fading to black.
- */
- case EXIT:
- CCDebugString ("C&C95 - Exit game packet received\n");
- Theme.Queue_Song(THEME_NONE);
- Stop_Speaking();
- Speak(VOX_CONTROL_EXIT);
- while (Is_Speaking()) {
- Call_Back();
- }
- GameActive = false;
- break;
- /*
- ** Process the options menu.
- */
- case OPTIONS:
- SpecialDialog = SDLG_OPTIONS;
- break;
- /*
- ** Process the options Game Speed
- */
- case GAMESPEED:
- CCDebugString ("C&C95 - Game speed packet received\n");
- Options.GameSpeed = Data.General.Value;
- break;
- /*
- ** Adjust connection timing for multiplayer games
- */
- case RESPONSE_TIME:
- char flip[128];
- sprintf (flip, "C&C95 - Changing MaxAhead to %d frames\n", Data.FrameInfo.Delay);
- CCDebugString (flip);
- MPlayerMaxAhead = Data.FrameInfo.Delay;
- break;
- //
- // This event tells all systems to use new timing values. It's like
- // RESPONSE_TIME, only it works. It's only used with the
- // COMM_MULTI_E_COMP protocol.
- //
- case TIMING:
- CCDebugString ("C&C95 - Timing packet received\n");
- //#if(TIMING_FIX)
- //
- // If MaxAhead is about to increase, we're vulnerable to a Packet-
- // Received-Too-Late error, if any system generates an event after
- // this TIMING event, but before it executes. So, record the
- // period of vulnerability's frame start & end values, so we
- // can reschedule these events to execute after it's over.
- //
- if (Data.Timing.MaxAhead > MPlayerMaxAhead) {
- NewMaxAheadFrame1 = Frame;
- NewMaxAheadFrame2 = Frame + Data.Timing.MaxAhead;
- }
- //#endif
- DesiredFrameRate = Data.Timing.DesiredFrameRate;
- MPlayerMaxAhead = Data.Timing.MaxAhead;
- sprintf (flip, "C&C95 - Timing packet: DesiredFrameRate = %d\n", Data.Timing.DesiredFrameRate);
- CCDebugString (flip);
- sprintf (flip, "C&C95 - Timing packet: MaxAhead = %d\n", Data.Timing.MaxAhead);
- CCDebugString (flip);
- /*
- ** If spawned from WChat then we should be getting poked every minute. If not then
- ** deliberately break the max ahead value
- */
- if (Special.IsFromWChat){
- MPlayerMaxAhead += DDEServer.Time_Since_Heartbeat()/(70*60);
- //if (DDEServer.Time_Since_Heartbeat() >= 70*60) CCDebugString ("C&C95 - Missed a heartbeat\n");
- }
- break;
- //
- // This event tells all systems what the other systems' process
- // timing requirements are; it's used to compute a desired frame rate
- // for the game.
- //
- case PROCESS_TIME:
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID == ::MPlayerID[i]) {
- TheirProcessTime[i] = Data.ProcessTime.AverageTicks;
- char flip[128];
- sprintf (flip, "C&C95 - Received PROCESS_TIME packet of %04x ticks\n", Data.ProcessTime.AverageTicks);
- CCDebugString (flip);
- break;
- }
- }
- break;
- /*
- ** Default: do nothing.
- */
- default:
- break;
- }
- }
|