flagbase.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. // flagbase.cpp
  19. // Project: Postal
  20. //
  21. // This module implements the flag object for capture the flag gameplay.
  22. //
  23. // History:
  24. //
  25. // 06/30/97 BRH Started this file for the challenge levels.
  26. //
  27. // 07/12/97 BRH Added FlagID so that flags can be matched with their
  28. // bases. Added loading/saving thereof. Also added
  29. // EditModify dialog so that the value can be set.
  30. //
  31. // 07/14/97 BRH Changed to using the CSmash::Flagbase bits to identify
  32. // the base. Also added checking for Flags to update
  33. // and incrementing the m_sFlagbaseCaptured value in realm
  34. // when the proper flag meets the base.
  35. //
  36. // 07/16/97 BRH Changed to using the correct base files rather than
  37. // the bandguy as a placeholder.
  38. //
  39. // 08/03/97 JMI Init() was setting the looping parms on a phot which no
  40. // longer exists. Now the looping parms are passed via the
  41. // Get() call in GetResources() instead so they will get set
  42. // via the CAnim3D which should know which ones are okay to
  43. // use.
  44. //
  45. // 08/11/97 BRH Added flagbase color option as a variable that is loaded
  46. // and saved and can be changed in the EditModify dialog.
  47. //
  48. // 08/18/97 JMI Changed State_Dead to call DeadRender3D() (which used to be
  49. // known/called as just another Render() overload).
  50. //
  51. // 08/28/97 BRH Set the correct bits to detect the flag base. Finished
  52. // the code for capturing the flagbase.
  53. //
  54. ////////////////////////////////////////////////////////////////////////////////
  55. #define FLAGBASE_CPP
  56. #include "RSPiX.h"
  57. #include "flagbase.h"
  58. #include "flag.h"
  59. #include "SampleMaster.h"
  60. ////////////////////////////////////////////////////////////////////////////////
  61. // Macros/types/etc.
  62. ////////////////////////////////////////////////////////////////////////////////
  63. #define GUI_FLAGID_EDIT_ID 103
  64. #define GUI_COLOR_EDIT_ID 104
  65. ////////////////////////////////////////////////////////////////////////////////
  66. // Variables/data
  67. ////////////////////////////////////////////////////////////////////////////////
  68. // These are default values -- actually values are set using the editor!
  69. double CFlagbase::ms_dInRange = 30 * 30; // Sq distance to base
  70. // Let this auto-init to 0
  71. short CFlagbase::ms_sFileCount;
  72. /// Throwing Animation Files ////////////////////////////////////////////////////
  73. // An array of pointers to resource names (one for each channel of the animation)
  74. static char* ms_apszRedResNames[] =
  75. {
  76. "3d/rbase.sop",
  77. "3d/rbase.mesh",
  78. "3d/rbase.tex",
  79. "3d/rbase.hot",
  80. "3d/rbase.bounds",
  81. "3d/rbase.floor",
  82. NULL,
  83. NULL
  84. };
  85. static char* ms_apszBlueResNames[] =
  86. {
  87. "3d/bbase.sop",
  88. "3d/bbase.mesh",
  89. "3d/bbase.tex",
  90. "3d/bbase.hot",
  91. "3d/bbase.bounds",
  92. "3d/bbase.floor",
  93. NULL,
  94. NULL
  95. };
  96. // These are the points that are checked on the attribute map relative to his origin
  97. static RP3d ms_apt3dAttribCheck[] =
  98. {
  99. {-6, 0, -6},
  100. { 0, 0, -6},
  101. { 6, 0, -6},
  102. {-6, 0, 6},
  103. { 0, 0, 6},
  104. { 6, 0, 6},
  105. };
  106. ////////////////////////////////////////////////////////////////////////////////
  107. // Load object (should call base class version!)
  108. ////////////////////////////////////////////////////////////////////////////////
  109. short CFlagbase::Load( // Returns 0 if successfull, non-zero otherwise
  110. RFile* pFile, // In: File to load from
  111. bool bEditMode, // In: True for edit mode, false otherwise
  112. short sFileCount, // In: File count (unique per file, never 0)
  113. ULONG ulFileVersion) // In: Version of file format to load.
  114. {
  115. short sResult = 0;
  116. // Call the base load function to get ID, position, etc.
  117. sResult = CThing3d::Load(pFile, bEditMode, sFileCount, ulFileVersion);
  118. if (sResult == 0)
  119. {
  120. // Load common data just once per file (not with each object)
  121. if (ms_sFileCount != sFileCount)
  122. {
  123. ms_sFileCount = sFileCount;
  124. // Load static data
  125. switch (ulFileVersion)
  126. {
  127. default:
  128. case 1:
  129. pFile->Read(&ms_dInRange);
  130. break;
  131. }
  132. }
  133. // Load other values
  134. switch (ulFileVersion)
  135. {
  136. default:
  137. case 45:
  138. pFile->Read(&m_u16Color);
  139. case 44:
  140. case 43:
  141. case 42:
  142. case 41:
  143. case 40:
  144. case 39:
  145. case 38:
  146. case 37:
  147. case 36:
  148. case 35:
  149. case 34:
  150. case 33:
  151. case 32:
  152. case 31:
  153. case 30:
  154. case 29:
  155. case 28:
  156. case 27:
  157. case 26:
  158. case 25:
  159. case 24:
  160. case 23:
  161. case 22:
  162. case 21:
  163. case 20:
  164. case 19:
  165. case 18:
  166. case 17:
  167. case 16:
  168. case 15:
  169. case 14:
  170. case 13:
  171. case 12:
  172. case 11:
  173. case 10:
  174. case 9:
  175. case 8:
  176. case 7:
  177. case 6:
  178. case 5:
  179. case 4:
  180. case 3:
  181. case 2:
  182. case 1:
  183. case 0:
  184. pFile->Read(&m_u16FlagID);
  185. break;
  186. }
  187. // Make sure there were no file errors or format errors . . .
  188. if (!pFile->Error() && sResult == 0)
  189. {
  190. // Get resources
  191. sResult = GetResources();
  192. }
  193. else
  194. {
  195. sResult = -1;
  196. TRACE("CFlagbase::Load(): Error reading from file!\n");
  197. }
  198. }
  199. else
  200. {
  201. TRACE("CFlagbase::Load(): CDoofus::Load() failed.\n");
  202. }
  203. return sResult;
  204. }
  205. ////////////////////////////////////////////////////////////////////////////////
  206. // Save object (should call base class version!)
  207. ////////////////////////////////////////////////////////////////////////////////
  208. short CFlagbase::Save( // Returns 0 if successfull, non-zero otherwise
  209. RFile* pFile, // In: File to save to
  210. short sFileCount) // In: File count (unique per file, never 0)
  211. {
  212. // Swap the hotspot we want to save in.
  213. short sResult;
  214. // Call the base class save to save the instance ID, position, etc
  215. CThing3d::Save(pFile, sFileCount);
  216. // Save common data just once per file (not with each object)
  217. if (ms_sFileCount != sFileCount)
  218. {
  219. ms_sFileCount = sFileCount;
  220. // Save static data
  221. pFile->Write(&ms_dInRange);
  222. }
  223. // Save additinal stuff here.
  224. pFile->Write(&m_u16Color);
  225. pFile->Write(&m_u16FlagID);
  226. if (!pFile->Error())
  227. {
  228. sResult = SUCCESS;
  229. }
  230. else
  231. {
  232. TRACE("CFlagbase::Save() - Error writing to file\n");
  233. sResult = -1;
  234. }
  235. return sResult;
  236. }
  237. ////////////////////////////////////////////////////////////////////////////////
  238. // Init - Call this after the resources are in place
  239. ////////////////////////////////////////////////////////////////////////////////
  240. short CFlagbase::Init(void)
  241. {
  242. short sResult = 0;
  243. // Prepare shadow (get resources and setup sprite).
  244. sResult = PrepareShadow();
  245. // Init other stuff
  246. m_dVel = 0.0;
  247. m_dRot = 0.0;
  248. // Set to different starting state based on the design of the animation, but
  249. // for now, ok. Then also set his current animation.
  250. m_state = CFlagbase::State_Wait;
  251. m_panimCur = &m_animFlagWave;
  252. m_lAnimTime = 0;
  253. m_lTimer = m_pRealm->m_time.GetGameTime() + 500;
  254. m_smash.m_bits = CSmash::FlagBase;
  255. m_smash.m_pThing = this;
  256. m_sBrightness = 0; // Default Brightness level
  257. return sResult;
  258. }
  259. ////////////////////////////////////////////////////////////////////////////////
  260. // Startup object
  261. ////////////////////////////////////////////////////////////////////////////////
  262. short CFlagbase::Startup(void) // Returns 0 if successfull, non-zero otherwise
  263. {
  264. short sResult = 0;
  265. // Set the current height, previous time, and Nav Net
  266. CThing3d::Startup();
  267. // Init other stuff
  268. Init();
  269. return sResult;
  270. }
  271. ////////////////////////////////////////////////////////////////////////////////
  272. // Shutdown object
  273. ////////////////////////////////////////////////////////////////////////////////
  274. short CFlagbase::Shutdown(void) // Returns 0 if successfull, non-zero otherwise
  275. {
  276. short sResult = 0;
  277. m_trans.Make1();
  278. return sResult;
  279. }
  280. ////////////////////////////////////////////////////////////////////////////////
  281. // Update object
  282. ////////////////////////////////////////////////////////////////////////////////
  283. void CFlagbase::Update(void)
  284. {
  285. short sHeight = m_sPrevHeight;
  286. long lThisTime;
  287. long lTimeDifference;
  288. long lSqDistanceToDude = 0;
  289. CSmash* pSmashed = NULL;
  290. if (!m_sSuspend)
  291. {
  292. // Get new time
  293. lThisTime = m_pRealm->m_time.GetGameTime();
  294. lTimeDifference = lThisTime - m_lPrevTime;
  295. // Calculate elapsed time in seconds
  296. double dSeconds = (double)(lThisTime - m_lPrevTime) / 1000.0;
  297. // Check for new messages that may change the state
  298. ProcessMessages();
  299. switch(m_state)
  300. {
  301. case CFlagbase::State_Wait:
  302. if (lThisTime > m_lTimer)
  303. {
  304. m_state = CFlagbase::State_Guard;
  305. }
  306. // Update sphere.
  307. m_smash.m_sphere.sphere.X = m_dX;
  308. m_smash.m_sphere.sphere.Y = m_dY;
  309. m_smash.m_sphere.sphere.Z = m_dZ;
  310. m_smash.m_sphere.sphere.lRadius = 20; //m_spriteBase.m_sRadius;
  311. // Update the smash.
  312. m_pRealm->m_smashatorium.Update(&m_smash);
  313. break;
  314. //-----------------------------------------------------------------------
  315. // Guard - normal operation
  316. //-----------------------------------------------------------------------
  317. case CFlagbase::State_Guard:
  318. m_pRealm->m_smashatorium.QuickCheckReset(&m_smash, CSmash::Flag, 0, 0);
  319. while (m_pRealm->m_smashatorium.QuickCheckNext(&pSmashed))
  320. {
  321. if (pSmashed->m_pThing->GetClassID() == CFlagID)
  322. {
  323. if (((CFlag*) (pSmashed->m_pThing))->m_u16FlagID == m_u16FlagID)
  324. {
  325. m_pRealm->m_sFlagbaseCaptured++;
  326. m_state = State_Dead;
  327. }
  328. }
  329. }
  330. break;
  331. //-----------------------------------------------------------------------
  332. // Blownup - You were blown up so pop up into the air and come down dead
  333. //-----------------------------------------------------------------------
  334. case CFlagbase::State_BlownUp:
  335. // Make her animate
  336. m_lAnimTime += lTimeDifference;
  337. if (!WhileBlownUp())
  338. m_state = State_Dead;
  339. else
  340. {
  341. UpdateFirePosition();
  342. }
  343. break;
  344. //-----------------------------------------------------------------------
  345. // Dead - You are dead, so lay there and decompose, then go away
  346. //-----------------------------------------------------------------------
  347. case CFlagbase::State_Dead:
  348. CHood* phood = m_pRealm->m_phood;
  349. // Render current dead frame into background to stay.
  350. m_pRealm->m_scene.DeadRender3D(
  351. phood->m_pimBackground, // Destination image.
  352. &m_sprite, // Tree of 3D sprites to render.
  353. phood); // Dst clip rect.
  354. delete this;
  355. return;
  356. break;
  357. }
  358. // Update sphere.
  359. m_smash.m_sphere.sphere.X = m_dX;
  360. m_smash.m_sphere.sphere.Y = m_dY;
  361. m_smash.m_sphere.sphere.Z = m_dZ;
  362. m_smash.m_sphere.sphere.lRadius = 20; //m_spriteBase.m_sRadius;
  363. // Update the smash.
  364. m_pRealm->m_smashatorium.Update(&m_smash);
  365. // Save time for next time
  366. m_lPrevTime = lThisTime;
  367. m_lAnimPrevUpdateTime = m_lAnimTime;
  368. }
  369. }
  370. ////////////////////////////////////////////////////////////////////////////////
  371. // Called by editor to init new object at specified position
  372. ////////////////////////////////////////////////////////////////////////////////
  373. short CFlagbase::EditNew( // Returns 0 if successfull, non-zero otherwise
  374. short sX, // In: New x coord
  375. short sY, // In: New y coord
  376. short sZ) // In: New z coord
  377. {
  378. short sResult = 0;
  379. sResult = CThing3d::EditNew(sX, sY, sZ);
  380. if (sResult == SUCCESS)
  381. {
  382. // Load resources
  383. sResult = GetResources();
  384. if (sResult == SUCCESS)
  385. {
  386. sResult = Init();
  387. }
  388. }
  389. else
  390. {
  391. sResult = -1;
  392. }
  393. return sResult;
  394. }
  395. ////////////////////////////////////////////////////////////////////////////////
  396. // Edit Move
  397. ////////////////////////////////////////////////////////////////////////////////
  398. short CFlagbase::EditMove(short sX, short sY, short sZ)
  399. {
  400. short sResult = CThing3d::EditMove(sX, sY, sZ);
  401. return sResult;
  402. }
  403. ////////////////////////////////////////////////////////////////////////////////
  404. // Give Edit a rectangle around this object
  405. ////////////////////////////////////////////////////////////////////////////////
  406. void CFlagbase::EditRect(RRect* pRect)
  407. {
  408. // Call base class.
  409. CThing3d::EditRect(pRect);
  410. }
  411. ////////////////////////////////////////////////////////////////////////////////
  412. // Called by editor to get the hotspot of an object in 2D.
  413. // (virtual (Overridden here)).
  414. ////////////////////////////////////////////////////////////////////////////////
  415. void CFlagbase::EditHotSpot( // Returns nothiing.
  416. short* psX, // Out: X coord of 2D hotspot relative to
  417. // EditRect() pos.
  418. short* psY) // Out: Y coord of 2D hotspot relative to
  419. // EditRect() pos.
  420. {
  421. // Get rectangle.
  422. RRect rc;
  423. EditRect(&rc);
  424. // Get 2D hotspot.
  425. short sX;
  426. short sY;
  427. Map3Dto2D(
  428. m_dX,
  429. m_dY,
  430. m_dZ,
  431. &sX,
  432. &sY);
  433. // Get relation.
  434. *psX = sX - rc.sX;
  435. *psY = sY - rc.sY;
  436. }
  437. ////////////////////////////////////////////////////////////////////////////////
  438. // Called by editor to modify object
  439. ////////////////////////////////////////////////////////////////////////////////
  440. short CFlagbase::EditModify(void)
  441. {
  442. short sResult = 0;
  443. U16 u16OrigColor = m_u16Color;
  444. RGuiItem* pGuiItem = NULL;
  445. RGuiItem* pguiRoot = RGuiItem::LoadInstantiate(FullPathVD("res/editor/flagbase.gui"));
  446. if (pguiRoot != NULL)
  447. {
  448. REdit* peditFlagID = (REdit*) pguiRoot->GetItemFromId(GUI_FLAGID_EDIT_ID);
  449. REdit* peditColor = (REdit*) pguiRoot->GetItemFromId(GUI_COLOR_EDIT_ID);
  450. if (peditFlagID != NULL && peditColor != NULL)
  451. {
  452. ASSERT(peditFlagID->m_type == RGuiItem::Edit);
  453. ASSERT(peditColor->m_type == RGuiItem::Edit);
  454. peditFlagID->SetText("%d", m_u16FlagID);
  455. peditFlagID->Compose();
  456. peditColor->SetText("%d", m_u16Color);
  457. peditColor->Compose();
  458. sResult = DoGui(pguiRoot);
  459. if (sResult == 1)
  460. {
  461. m_u16FlagID = peditFlagID->GetVal();
  462. m_u16Color = MIN((long) (CFlag::EndOfColors - 1), peditColor->GetVal());
  463. }
  464. }
  465. }
  466. delete pguiRoot;
  467. // If the user switched colors, get the new resources
  468. if (m_u16Color != u16OrigColor)
  469. {
  470. FreeResources();
  471. GetResources();
  472. }
  473. return 0;
  474. }
  475. ////////////////////////////////////////////////////////////////////////////////
  476. // Get all required resources
  477. ////////////////////////////////////////////////////////////////////////////////
  478. short CFlagbase::GetResources(void) // Returns 0 if successfull, non-zero otherwise
  479. {
  480. short sResult = 0;
  481. switch (m_u16Color)
  482. {
  483. default:
  484. case CFlag::Red:
  485. sResult = m_animFlagWave.Get(ms_apszRedResNames, RChannel_LoopAtStart | RChannel_LoopAtEnd);
  486. break;
  487. case CFlag::Blue:
  488. sResult = m_animFlagWave.Get(ms_apszBlueResNames, RChannel_LoopAtStart | RChannel_LoopAtEnd);
  489. break;
  490. }
  491. if (sResult == 0)
  492. {
  493. // Add new animation loads here
  494. }
  495. else
  496. {
  497. TRACE("CFlagbase::GetResources - Failed to open 3D flag waving animation\n");
  498. }
  499. return sResult;
  500. }
  501. ////////////////////////////////////////////////////////////////////////////////
  502. // Free all resources
  503. ////////////////////////////////////////////////////////////////////////////////
  504. short CFlagbase::FreeResources(void) // Returns 0 if successfull, non-zero otherwise
  505. {
  506. m_animFlagWave.Release();
  507. return 0;
  508. }
  509. ////////////////////////////////////////////////////////////////////////////////
  510. // Message handlers
  511. ////////////////////////////////////////////////////////////////////////////////
  512. ////////////////////////////////////////////////////////////////////////////////
  513. // Shot Message
  514. ////////////////////////////////////////////////////////////////////////////////
  515. ////////////////////////////////////////////////////////////////////////////////
  516. // Explosion message
  517. ////////////////////////////////////////////////////////////////////////////////
  518. void CFlagbase::OnExplosionMsg(Explosion_Message* pMessage)
  519. {
  520. if (
  521. m_state != State_BlownUp &&
  522. m_state != State_Die &&
  523. m_state != State_Dead)
  524. {
  525. // CCharacter::OnExplosionMsg(pMessage);
  526. // PlaySample(g_smidBlownupFemaleYell);
  527. // m_ePreviousState = m_state;
  528. m_state = State_BlownUp;
  529. // m_panimPrev = m_panimCur;
  530. // m_panimCur = &m_animDie;
  531. m_lAnimTime = 0;
  532. // m_stockpile.m_sHitPoints = 0;
  533. m_lTimer = m_pRealm->m_time.GetGameTime();
  534. m_dExtHorzVel *= 1.4; //2.5;
  535. m_dExtVertVel *= 1.1; //1.4;
  536. // Send it spinning.
  537. m_dExtRotVelY = GetRandom() % 720;
  538. m_dExtRotVelZ = GetRandom() % 720;
  539. // m_panimCur = &m_animDie;
  540. }
  541. }
  542. ////////////////////////////////////////////////////////////////////////////////
  543. // Burning message
  544. ////////////////////////////////////////////////////////////////////////////////
  545. void CFlagbase::OnBurnMsg(Burn_Message* pMessage)
  546. {
  547. // For now we made the sentry fireproof, the only
  548. // way it can be destroyed is by blowing it up.
  549. }
  550. ////////////////////////////////////////////////////////////////////////////////
  551. // EOF
  552. ////////////////////////////////////////////////////////////////////////////////