EVENT.CPP 35 KB

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