EVENT.CPP 36 KB

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