demon.cpp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265
  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. // Demon.cpp
  19. // Project: Postal
  20. //
  21. // History:
  22. // 06/09/97 BRH Started this from from SoundThing.cpp
  23. //
  24. // 06/10/97 BRH Added comments for deaths and added a comment counter
  25. // so it doesn't say something all of the time.
  26. //
  27. // 06/11/97 BRH Changed the demon icon.
  28. //
  29. // 06/17/97 JMI Converted all occurrences of rand() to GetRand() and
  30. // srand() to SeedRand().
  31. //
  32. // 06/29/97 JMI Converted EditRect(), EditRender(), and/or Render() to
  33. // use Map3Dto2D().
  34. //
  35. // 06/30/97 BRH Took out the cache samples in the Preload function for
  36. // now so that the sounds won't be preloaded. If we
  37. // decide to have a memory based setting for this as an
  38. // option, then it can check it here and decide to load
  39. // the samples or not. Also changed the PlaySample
  40. // calls to PlaySampleThenPurge to keep the memory usage
  41. // down.
  42. //
  43. // 07/09/97 JMI Now uses m_pRealm->Make2dResPath() to get the fullpath
  44. // for 2D image components.
  45. //
  46. // 07/09/97 JMI Changed Preload() to take a pointer to the calling realm
  47. // as a parameter.
  48. //
  49. // 07/17/97 JMI Changed m_psndChannel to m_siLastPlayInstance.
  50. // Now uses new SampleMaster interface for volume and play
  51. // instance reference.
  52. // Then, removed m_psndChannel b/c this class really didn't
  53. // use it.
  54. //
  55. // 07/18/97 JMI Got rid of bogus immitation PlaySample functions.
  56. // Now there is one PlaySample() function. Also, you now
  57. // MUST specify a category and you don't have to specify a
  58. // SoundInstance ptr to specify a volume.
  59. //
  60. // 07/20/97 BRH Changed weapon case statements to use the CDude's
  61. // enumerated type so that if the keys are switched
  62. // around again, the comments will still be correctly
  63. // associated with their weapon type.
  64. //
  65. // 08/05/97 JMI Changed priority to use Z position rather than 2D
  66. // projected Y position.
  67. //
  68. // 08/26/97 BRH Got rid of a few phrases and added a few others in their
  69. // place. Now there is only one Going Postal instead of 4,
  70. // and a few other phrases that weren't being used are now
  71. // in.
  72. //
  73. // 12/02/97 JMI Added new m_sSoundBank member (edittable via EditModify()
  74. // that allows one to specify a sound bank index for
  75. // additional sounds).
  76. // Also, removed unused vars:
  77. // m_lNextStartTime, m_lLastStartTime, m_sWhichTime,
  78. // m_bEnabled, m_bRepeats, m_bInitiallyEnabled,
  79. // m_bInitiallyRepeats, m_lMinTime[], m_lRndTime[],
  80. // m_szResName, and m_id.
  81. // Also, now loads the GUI off the HD b/c the Add On packs
  82. // new assets (such as Demon.GUI) will have to be on the
  83. // HD so we can require the user have the original Postal
  84. // CD in the drive while playing.
  85. // Also, now saves position and defaults to position on the
  86. // the screen (that way older levels that didn't save the
  87. // position will have the demon on the screen).
  88. //
  89. // 01/07/98 BRH Added level specific new Demon sounds for the Add On Pack
  90. //
  91. //////////////////////////////////////////////////////////////////////////////
  92. //
  93. // This CThing-derived class will play sounds with various options.
  94. //
  95. //////////////////////////////////////////////////////////////////////////////
  96. #define DEMON_CPP
  97. #include "RSPiX.h"
  98. #include "demon.h"
  99. #include "game.h"
  100. #include "dude.h"
  101. // To help identify the m_sSoundBank number for each new Add on level
  102. #define DEMON_SHANTY_LEVEL 1
  103. #define DEMON_RESORT_LEVEL 2
  104. #define DEMON_WALMART_LEVEL 3
  105. #define DEMON_EARTHQUAKE_LEVEL 4
  106. ////////////////////////////////////////////////////////////////////////////////
  107. // Static variables
  108. ////////////////////////////////////////////////////////////////////////////////
  109. long CDemon::ms_lMinIdleTime = 2000; // Time before saying next thing
  110. long CDemon::ms_lBonusKillTime = 5000; // Kill an amount in this time, get bonus
  111. // Sound banks of explosion comments indexed by m_sSoundBank.
  112. SampleMasterID* CDemon::ms_apsmidExplosion[NumSoundBanks][NumExplosionComments] =
  113. {
  114. { // 0 == Normal.
  115. &g_smidDemonSlam,
  116. &g_smidDemonYes1,
  117. &g_smidDemonGoodOne,
  118. &g_smidDemonHa,
  119. &g_smidDemonButtSauce,
  120. &g_smidDemonHesOut,
  121. &g_smidDemonInHell,
  122. &g_smidDemonBuckwheat4,
  123. },
  124. { // 1 = Shanty Town
  125. &g_smidDemonKeepTheChange,
  126. &g_smidDemonPropertyValues,
  127. &g_smidDemonCantHaveAnyNice,
  128. &g_smidDemonWelfareReform,
  129. &g_smidDemonGrenadeWorksGreat,
  130. &g_smidDemonYouBlewItUp,
  131. &g_smidDemonKeepTheChange,
  132. &g_smidDemonAltLifestyles,
  133. },
  134. { // 2 = Resort
  135. &g_smidDemonProsecutionRests,
  136. &g_smidDemonCaseDismissed,
  137. &g_smidDemonCheckOutEarly,
  138. &g_smidDemonHoleInOne,
  139. &g_smidDemonRippedBday,
  140. &g_smidDemonShakeItUpBaby,
  141. &g_smidDemonWatchItWiggle,
  142. &g_smidDemonNoDecency,
  143. },
  144. { // 3 = Wal Mart
  145. &g_smidDemonSatisfactGnty,
  146. &g_smidDemonCustomerRight,
  147. &g_smidDemonCleanupAisle5,
  148. &g_smidDemonBrownBagBody,
  149. &g_smidDemonBastardsWCoupons,
  150. &g_smidDemonNoRefunds,
  151. &g_smidDemonWhatLaneClosed,
  152. &g_smidDemonTenItemsOrLess,
  153. },
  154. { // 4 = Earthquake
  155. &g_smidDemonYouBlewItUp,
  156. &g_smidDemonKillingGoodSoal,
  157. &g_smidDemonAngelOfDeath,
  158. &g_smidDemonAwwBoBo,
  159. &g_smidDemonYouBlewItUp,
  160. &g_smidDemonDeathMyFriend,
  161. &g_smidDemonDieWeakling,
  162. &g_smidDemonIsThereDoctor,
  163. }
  164. };
  165. // Sound banks of burn comments indexed by m_sSoundBank.
  166. SampleMasterID* CDemon::ms_apsmidBurn[NumSoundBanks][NumBurnComments] =
  167. {
  168. { // 0 == Normal.
  169. &g_smidDemonSmellChicken,
  170. &g_smidDemonFeelHeat,
  171. &g_smidDemonBurn,
  172. &g_smidDemonBurnBaby,
  173. },
  174. { // 1 = Shanty Town
  175. &g_smidDemonSmellsSourMilk,
  176. &g_smidDemonBegForThis,
  177. &g_smidDemonFreezingWarm,
  178. &g_smidDemonBurningGovtCheese,
  179. },
  180. { // 2 = Resort
  181. &g_smidDemonIsThereDoctor,
  182. &g_smidDemonOutHotTowels,
  183. &g_smidDemonFreezingWarm,
  184. &g_smidDemonILoveGoodBBQ,
  185. },
  186. { // 3 = Wal Mart
  187. &g_smidDemonIsItHotOrJustMe,
  188. &g_smidDemonBlueLightSpecial,
  189. &g_smidDemonSmellBurning,
  190. &g_smidDemonBastardsWCoupons,
  191. },
  192. { // 4 = Earthquake
  193. &g_smidDemonSeeYouInHellHa,
  194. &g_smidDemonILoveGoodBBQ,
  195. &g_smidDemonWhusy,
  196. &g_smidDemonShakeItUpBaby,
  197. }
  198. };
  199. // Sound banks of suicide comments indexed by m_sSoundBank.
  200. SampleMasterID* CDemon::ms_apsmidSuicide[NumSoundBanks][NumSuicideComments] =
  201. {
  202. { // 0 == Normal.
  203. &g_smidDemonNoRegrets,
  204. },
  205. { // 1 = Shanty Town
  206. &g_smidDemonTodayGoodToDie,
  207. },
  208. { // 2 = Resort
  209. &g_smidDemonShowNoMercy,
  210. },
  211. { // 3 = Wal Mart
  212. &g_smidDemonDontSellPostal1,
  213. },
  214. { // 4 = Earthquake
  215. &g_smidDemonDeathMyMaster,
  216. }
  217. };
  218. // Sound banks of writhing comments indexed by m_sSoundBank.
  219. SampleMasterID* CDemon::ms_apsmidWrithing[NumSoundBanks][NumWrithingComments] =
  220. {
  221. { // 0 == Normal.
  222. &g_smidDemonSissy1,
  223. &g_smidDemonSissy2,
  224. &g_smidDemonThatHurt1,
  225. &g_smidDemonThatHurt2,
  226. &g_smidDemonBleed,
  227. },
  228. { // 1 = Shanty Town
  229. &g_smidDemonBegForThis,
  230. &g_smidDemonDoItQuietly,
  231. &g_smidDemonDieLikeDogYouAre,
  232. &g_smidDemonIsThereDoctor,
  233. &g_smidDemonWhusy,
  234. },
  235. { // 2 = Resort
  236. &g_smidDemonWontAffectTip,
  237. &g_smidDemonYouNeedMasage,
  238. &g_smidDemonDizkneeland,
  239. &g_smidDemonHeCheckedOut,
  240. &g_smidDemonWatchItWiggle,
  241. },
  242. { // 3 = Wal Mart
  243. &g_smidDemonDontSellPostal2,
  244. &g_smidDemonNoRefunds,
  245. &g_smidWalMartCleanupAisle17,
  246. &g_smidWalMartCleanupAisle6b,
  247. &g_smidWWalMartCleanupAisle6,
  248. },
  249. { // 4 = Earthquake
  250. &g_smidDemonRemainStillInjured,
  251. &g_smidDemonPinnedDown,
  252. &g_smidDemonAwwBoBo,
  253. &g_smidDemonFeelWrathDog,
  254. &g_smidDemonDieWeakling,
  255. }
  256. };
  257. // Sound banks of kill series comments indexed by m_sSoundBank.
  258. SampleMasterID* CDemon::ms_apsmidKillSeries[NumSoundBanks][NumKillSeriesComments] =
  259. {
  260. { // 0 == Normal.
  261. &g_smidDemonTheMan,
  262. &g_smidDemonKickAss,
  263. &g_smidDemonOJ,
  264. &g_smidDemonPostal,
  265. &g_smidDemonBuckwheat4,
  266. &g_smidDemonLikeYou,
  267. &g_smidDemonGoPostal4,
  268. },
  269. { // 1 = Shanty Town
  270. &g_smidDemonDamnImGood,
  271. &g_smidDemonJudgeJuryExe,
  272. &g_smidDemonExterminatorsBack,
  273. &g_smidDemonAngelOfDeath,
  274. &g_smidDemonPropertyValues,
  275. &g_smidDemonJudgeJuryExe,
  276. &g_smidDemonKickAss,
  277. },
  278. { // 2 = Resort
  279. &g_smidDemonRichBastards,
  280. &g_smidDemonBuckwheat4,
  281. &g_smidDemonLikeYou,
  282. &g_smidDemonKillForMasage,
  283. &g_smidDemonWhoPeedInPool,
  284. &g_smidDemonRichBastards,
  285. &g_smidDemonCaseDismissed,
  286. },
  287. { // 3 = Wal Mart
  288. &g_smidDemonShowNoMercy,
  289. &g_smidDemonBuckwheat4,
  290. &g_smidDemonMadeInUSABaby,
  291. &g_smidDemonCleanupAisle5,
  292. &g_smidDemonLowPriceQnty,
  293. &g_smidDemonSeeYouInHellHa,
  294. &g_smidDemonNoRefunds,
  295. },
  296. { // 4 = Earthquake
  297. &g_smidDemonBuckwheat4,
  298. &g_smidDemonAngelOfDeath,
  299. &g_smidDemonShowNoMercy,
  300. &g_smidDemonSeeYouInHellHa,
  301. &g_smidDemonShakeItUpBaby,
  302. &g_smidDemonKillingGoodSoal,
  303. &g_smidDemonDamnImGood,
  304. }
  305. };
  306. ////////////////////////////////////////////////////////////////////////////////
  307. // Macros/types/etc.
  308. ////////////////////////////////////////////////////////////////////////////////
  309. #define IMAGE_FILE "demon.bmp"
  310. #define GUI_FILE_NAME "res/editor/Demon.gui"
  311. #define GUI_ID_BANK 1000
  312. ////////////////////////////////////////////////////////////////////////////////
  313. // Preload - cache the sounds that may be used.
  314. ////////////////////////////////////////////////////////////////////////////////
  315. short CDemon::Preload(
  316. CRealm* prealm) // In: Calling realm.
  317. {
  318. #if 0
  319. // Tell samplemaster to cache (preload) this sample
  320. CacheSample(g_smidDemonBleed);
  321. CacheSample(g_smidDemonBlowup);
  322. CacheSample(g_smidDemonBurn);
  323. CacheSample(g_smidDemonBurnBaby);
  324. CacheSample(g_smidDemonButtSauce);
  325. CacheSample(g_smidDemonSmellChicken);
  326. CacheSample(g_smidDemonDie1);
  327. CacheSample(g_smidDemonDie2);
  328. CacheSample(g_smidDemonSissy1);
  329. CacheSample(g_smidDemonSissy2);
  330. CacheSample(g_smidDemonEvil);
  331. CacheSample(g_smidDemonFeelHeat);
  332. CacheSample(g_smidDemonGetEm1);
  333. CacheSample(g_smidDemonGetEm2);
  334. CacheSample(g_smidDemonGone1);
  335. CacheSample(g_smidDemonGone2);
  336. CacheSample(g_smidDemonGoodOne);
  337. CacheSample(g_smidDemonGoPostal4);
  338. CacheSample(g_smidDemonHa);
  339. CacheSample(g_smidDemonHesOut);
  340. CacheSample(g_smidDemonInHell);
  341. CacheSample(g_smidDemonLikeItHot);
  342. CacheSample(g_smidDemonKickAss);
  343. CacheSample(g_smidDemonLaugh1);
  344. CacheSample(g_smidDemonLaugh2);
  345. CacheSample(g_smidDemonLikeYou);
  346. CacheSample(g_smidDemonNoRegrets);
  347. CacheSample(g_smidDemonOhBaby);
  348. CacheSample(g_smidDemonOJ);
  349. CacheSample(g_smidDemonOnlyWeapons);
  350. CacheSample(g_smidDemonPostal);
  351. CacheSample(g_smidDemonSlam);
  352. CacheSample(g_smidDemonThatHurt1);
  353. CacheSample(g_smidDemonThatHurt2);
  354. CacheSample(g_smidDemonTheGipper);
  355. CacheSample(g_smidDemonTheGun);
  356. CacheSample(g_smidDemonWeapon);
  357. CacheSample(g_smidDemonYes1);
  358. CacheSample(g_smidDemonYes2);
  359. CacheSample(g_smidDemonBuckwheat4);
  360. CacheSample(g_smidDemonTheMan);
  361. #endif
  362. return 0;
  363. }
  364. ////////////////////////////////////////////////////////////////////////////////
  365. // Load object (should call base class version!)
  366. ////////////////////////////////////////////////////////////////////////////////
  367. short CDemon::Load( // Returns 0 if successfull, non-zero otherwise
  368. RFile* pFile, // In: File to load from
  369. bool bEditMode, // In: True for edit mode, false otherwise
  370. short sFileCount, // In: File count (unique per file, never 0)
  371. ULONG ulFileVersion) // In: Version of file format to load.
  372. {
  373. short sResult = CThing::Load(pFile, bEditMode, sFileCount, ulFileVersion);
  374. if (sResult == 0)
  375. {
  376. switch (ulFileVersion)
  377. {
  378. default:
  379. case 47:
  380. pFile->Read(&m_sSoundBank);
  381. pFile->Read(&m_dX);
  382. pFile->Read(&m_dY);
  383. pFile->Read(&m_dZ);
  384. break;
  385. case 46:
  386. case 45:
  387. case 44:
  388. case 43:
  389. case 42:
  390. case 41:
  391. case 40:
  392. case 39:
  393. case 38:
  394. case 37:
  395. case 36:
  396. case 35:
  397. case 34:
  398. case 33:
  399. case 32:
  400. case 31:
  401. case 30:
  402. case 29:
  403. case 28:
  404. case 27:
  405. case 26:
  406. case 25:
  407. case 24:
  408. case 23:
  409. case 22:
  410. case 21:
  411. case 20:
  412. case 19:
  413. case 18:
  414. case 17:
  415. case 16:
  416. case 15:
  417. case 14:
  418. case 13:
  419. case 12:
  420. case 11:
  421. case 10:
  422. case 9:
  423. case 8:
  424. case 7:
  425. case 6:
  426. case 5:
  427. case 4:
  428. case 3:
  429. case 2:
  430. case 1:
  431. {
  432. // For backwards compatability.
  433. long alDummy[2];
  434. char szResNameDummy[RSP_MAX_PATH];
  435. pFile->Read(&alDummy[0]/*(long*)&m_bInitiallyEnabled*/);
  436. pFile->Read(&alDummy[0]/*(long*)&m_bInitiallyRepeats*/);
  437. pFile->Read(alDummy/*m_lMinTime*/, 2);
  438. pFile->Read(alDummy/*m_lRndTime*/, 2);
  439. pFile->Read(szResNameDummy/*m_szResName*/);
  440. break;
  441. }
  442. }
  443. // Make sure there were no file errors or format errors . . .
  444. if (!pFile->Error() && sResult == 0)
  445. {
  446. sResult = Init();
  447. }
  448. else
  449. {
  450. sResult = -1;
  451. TRACE("CDemon::Load(): Error reading from file!\n");
  452. }
  453. }
  454. return sResult;
  455. }
  456. ////////////////////////////////////////////////////////////////////////////////
  457. // Save object (should call base class version!)
  458. ////////////////////////////////////////////////////////////////////////////////
  459. short CDemon::Save( // Returns 0 if successfull, non-zero otherwise
  460. RFile* pFile, // In: File to save to
  461. short sFileCount) // In: File count (unique per file, never 0)
  462. {
  463. short sResult = CThing::Save(pFile, sFileCount);
  464. if (sResult == 0)
  465. {
  466. pFile->Write(m_sSoundBank);
  467. pFile->Write(&m_dX);
  468. pFile->Write(&m_dY);
  469. pFile->Write(&m_dZ);
  470. // Make sure there were no file errors
  471. sResult = pFile->Error();
  472. }
  473. return sResult;
  474. }
  475. ////////////////////////////////////////////////////////////////////////////////
  476. // Startup object
  477. ////////////////////////////////////////////////////////////////////////////////
  478. short CDemon::Startup(void) // Returns 0 if successfull, non-zero otherwise
  479. {
  480. return 0;
  481. }
  482. ////////////////////////////////////////////////////////////////////////////////
  483. // Shutdown object
  484. ////////////////////////////////////////////////////////////////////////////////
  485. short CDemon::Shutdown(void) // Returns 0 if successfull, non-zero otherwise
  486. {
  487. return 0;
  488. }
  489. ////////////////////////////////////////////////////////////////////////////////
  490. // Suspend object
  491. ////////////////////////////////////////////////////////////////////////////////
  492. void CDemon::Suspend(void)
  493. {
  494. m_sSuspend++;
  495. }
  496. ////////////////////////////////////////////////////////////////////////////////
  497. // Resume object
  498. ////////////////////////////////////////////////////////////////////////////////
  499. void CDemon::Resume(void)
  500. {
  501. m_sSuspend--;
  502. // If we're actually going to start updating again....
  503. if (m_sSuspend == 0)
  504. {
  505. }
  506. }
  507. ////////////////////////////////////////////////////////////////////////////////
  508. // Update object
  509. ////////////////////////////////////////////////////////////////////////////////
  510. void CDemon::Update(void)
  511. {
  512. if (!m_sSuspend)
  513. {
  514. // Process messages.
  515. ProcessMessages();
  516. if (m_state == State_Delete)
  517. {
  518. delete this;
  519. return;
  520. }
  521. }
  522. }
  523. ////////////////////////////////////////////////////////////////////////////////
  524. // Render object
  525. ////////////////////////////////////////////////////////////////////////////////
  526. void CDemon::Render(void)
  527. {
  528. }
  529. ////////////////////////////////////////////////////////////////////////////////
  530. // Called by editor to init new object at specified position
  531. ////////////////////////////////////////////////////////////////////////////////
  532. short CDemon::EditNew( // Returns 0 if successfull, non-zero otherwise
  533. short sX, // In: New x coord
  534. short sY, // In: New y coord
  535. short sZ) // In: New z coord
  536. {
  537. short sResult = 0;
  538. // Use specified position
  539. m_dX = (double)sX;
  540. m_dY = (double)sY;
  541. m_dZ = (double)sZ;
  542. sResult = Init();
  543. // sResult = EditModify();
  544. return sResult;
  545. }
  546. ////////////////////////////////////////////////////////////////////////////////
  547. // Called by editor to modify object
  548. ////////////////////////////////////////////////////////////////////////////////
  549. short CDemon::EditModify(void)
  550. {
  551. short sResult = 0;
  552. // Load gui dialog
  553. RGuiItem* pgui = RGuiItem::LoadInstantiate(FullPath(GAME_PATH_HD, GUI_FILE_NAME));
  554. if (pgui != NULL)
  555. {
  556. // Init "bank" field.
  557. RGuiItem* pguiBankName = pgui->GetItemFromId(GUI_ID_BANK);
  558. ASSERT(pguiBankName != NULL);
  559. pguiBankName->SetText("%hd", m_sSoundBank);
  560. pguiBankName->Compose();
  561. // Run the dialog using this super-duper helper funciton
  562. if (DoGui(pgui) == 1)
  563. {
  564. // Get new values from dialog.
  565. m_sSoundBank = (short)pguiBankName->GetVal();
  566. // Keep it in range.
  567. if (m_sSoundBank < 0)
  568. {
  569. m_sSoundBank = 0;
  570. }
  571. else if (m_sSoundBank >= NumSoundBanks)
  572. {
  573. m_sSoundBank = NumSoundBanks - 1;
  574. }
  575. }
  576. else
  577. {
  578. sResult = 1;
  579. }
  580. // Done with GUI.
  581. delete pgui;
  582. }
  583. else
  584. {
  585. sResult = -1;
  586. }
  587. #if 0 // No settins via dialog currently require re-Init()age.
  588. // If everything's okay, init using new values
  589. if (sResult == 0)
  590. sResult = Init();
  591. #endif
  592. return sResult;
  593. }
  594. ////////////////////////////////////////////////////////////////////////////////
  595. // Called by editor to move object to specified position
  596. ////////////////////////////////////////////////////////////////////////////////
  597. short CDemon::EditMove( // Returns 0 if successfull, non-zero otherwise
  598. short sX, // In: New x coord
  599. short sY, // In: New y coord
  600. short sZ) // In: New z coord
  601. {
  602. m_dX = (double)sX;
  603. m_dY = (double)sY;
  604. m_dZ = (double)sZ;
  605. return 0;
  606. }
  607. ////////////////////////////////////////////////////////////////////////////////
  608. // Called by editor to get the clickable pos/area of an object in 2D.
  609. // (virtual (Overridden here)).
  610. ////////////////////////////////////////////////////////////////////////////////
  611. void CDemon::EditRect( // Returns nothiing.
  612. RRect* prc) // Out: Clickable pos/area of object.
  613. {
  614. Map3Dto2D(
  615. m_dX,
  616. m_dY,
  617. m_dZ,
  618. &(prc->sX),
  619. &(prc->sY) );
  620. prc->sW = 10; // Safety.
  621. prc->sH = 10; // Safety.
  622. if (m_pImage)
  623. {
  624. prc->sW = m_pImage->m_sWidth;
  625. prc->sH = m_pImage->m_sHeight;
  626. }
  627. prc->sX -= prc->sW / 2;
  628. prc->sY -= prc->sH;
  629. }
  630. ////////////////////////////////////////////////////////////////////////////////
  631. // Called by editor to get the hotspot of an object in 2D.
  632. // (virtual (Overridden here)).
  633. ////////////////////////////////////////////////////////////////////////////////
  634. void CDemon::EditHotSpot( // Returns nothiing.
  635. short* psX, // Out: X coord of 2D hotspot relative to
  636. // EditRect() pos.
  637. short* psY) // Out: Y coord of 2D hotspot relative to
  638. // EditRect() pos.
  639. {
  640. *psX = 5; // Safety.
  641. *psY = 5; // Safety.
  642. if (m_pImage)
  643. {
  644. *psX = m_pImage->m_sWidth / 2;
  645. *psY = m_pImage->m_sHeight;
  646. }
  647. }
  648. ////////////////////////////////////////////////////////////////////////////////
  649. // Called by editor to update object
  650. ////////////////////////////////////////////////////////////////////////////////
  651. void CDemon::EditUpdate(void)
  652. {
  653. }
  654. ////////////////////////////////////////////////////////////////////////////////
  655. // Called by editor to render object
  656. ////////////////////////////////////////////////////////////////////////////////
  657. void CDemon::EditRender(void)
  658. {
  659. // Setup simple, non-animating sprite
  660. m_sprite.m_sInFlags = 0;
  661. Map3Dto2D(
  662. m_dX,
  663. m_dY,
  664. m_dZ,
  665. &(m_sprite.m_sX2),
  666. &(m_sprite.m_sY2) );
  667. // Priority is based on bottom edge of sprite
  668. m_sprite.m_sPriority = m_dZ;
  669. // Center on image.
  670. m_sprite.m_sX2 -= m_pImage->m_sWidth / 2;
  671. m_sprite.m_sY2 -= m_pImage->m_sHeight;
  672. m_sprite.m_sLayer = CRealm::GetLayerViaAttrib(m_pRealm->GetLayer((short) m_dX, (short) m_dZ));
  673. m_sprite.m_pImage = m_pImage;
  674. // Update sprite in scene
  675. m_pRealm->m_scene.UpdateSprite(&m_sprite);
  676. }
  677. ////////////////////////////////////////////////////////////////////////////////
  678. // Init object
  679. ////////////////////////////////////////////////////////////////////////////////
  680. short CDemon::Init(void) // Returns 0 if successfull, non-zero otherwise
  681. {
  682. short sResult = 0;
  683. Kill();
  684. if (m_pImage == 0)
  685. {
  686. sResult = rspGetResource(&g_resmgrGame, m_pRealm->Make2dResPath(IMAGE_FILE), &m_pImage);
  687. if (sResult == 0)
  688. {
  689. // This is a questionable action on a resource managed item, but it's
  690. // okay if EVERYONE wants it to be an FSPR8.
  691. if (m_pImage->Convert(RImage::FSPR8) != RImage::FSPR8)
  692. {
  693. sResult = -1;
  694. TRACE("CDemon::GetResource() - Couldn't convert to FSPR8\n");
  695. }
  696. }
  697. }
  698. return sResult;
  699. }
  700. ////////////////////////////////////////////////////////////////////////////////
  701. // Kill object
  702. ////////////////////////////////////////////////////////////////////////////////
  703. short CDemon::Kill(void) // Returns 0 if successfull, non-zero otherwise
  704. {
  705. if (m_pImage != 0)
  706. rspReleaseResource(&g_resmgrGame, &m_pImage);
  707. m_pRealm->m_scene.RemoveSprite(&m_sprite);
  708. return 0;
  709. }
  710. ////////////////////////////////////////////////////////////////////////////////
  711. // Process our message queue.
  712. ////////////////////////////////////////////////////////////////////////////////
  713. void CDemon::ProcessMessages(void)
  714. {
  715. SampleMasterID* psmid = &g_smidNil;
  716. bool bFoundSample = false;
  717. long lThisTime = m_pRealm->m_time.GetGameTime();
  718. // Check queue of messages.
  719. GameMessage msg;
  720. while (m_MessageQueue.DeQ(&msg) == true)
  721. {
  722. if (msg.msg_Generic.eType == typeCheater)
  723. {
  724. psmid = &g_smidDemonSissy2;
  725. if (lThisTime > m_lIdleTime + ms_lMinIdleTime)
  726. {
  727. PlaySample( // Returns nothing.
  728. // Does not fail.
  729. *psmid, // In: Identifier of sample you want played.
  730. SampleMaster::Demon); // In: Sound Volume Category for user adjustment
  731. m_lIdleTime = lThisTime;
  732. }
  733. bFoundSample = true;
  734. }
  735. // If we haven't selected a sound yet...
  736. if (!bFoundSample && lThisTime > m_lIdleTime + ms_lMinIdleTime)
  737. {
  738. switch(msg.msg_Generic.eType)
  739. {
  740. // Delete Demon
  741. case typeObjectDelete:
  742. m_state = State_Delete;
  743. break;
  744. // Weapon Selector
  745. case typeWeaponSelect:
  746. switch (msg.msg_WeaponSelect.sWeapon)
  747. {
  748. case CDude::SemiAutomatic: // Machine Gun
  749. if (GetRand() % 2)
  750. {
  751. if (m_sSoundBank == DEMON_RESORT_LEVEL)
  752. psmid = &g_smidDemonNudityOffensive;
  753. else
  754. psmid = &g_smidDemonTheGun;
  755. }
  756. else
  757. {
  758. if (m_sSoundBank == DEMON_RESORT_LEVEL)
  759. psmid = &g_smidDemonWhoPeedInPool;
  760. else
  761. psmid = &g_smidDemonWeapon;
  762. }
  763. break;
  764. case CDude::Grenade: // Grenade
  765. psmid = &g_smidDemonShakeItUpBaby;
  766. break;
  767. case CDude::FireBomb: // Cocktail
  768. if (GetRand() % 2)
  769. psmid = &g_smidDemonLikeItHot;
  770. else
  771. psmid = &g_smidDemonAllMustDie;
  772. break;
  773. case CDude::Rocket: // Rocket
  774. psmid = &g_smidDemonBlowup;
  775. break;
  776. case CDude::Napalm: // Napalm
  777. switch (GetRand() % 4)
  778. {
  779. case 0:
  780. psmid = &g_smidDemonExterminatorsBack;
  781. break;
  782. case 1:
  783. psmid = &g_smidDemonLikeItHot;
  784. break;
  785. case 2:
  786. psmid = &g_smidDemonOhBaby;
  787. break;
  788. case 3:
  789. psmid = &g_smidDemonYes2;
  790. break;
  791. }
  792. break;
  793. case CDude::ShotGun: // Shot Gun
  794. switch (GetRand() % 4)
  795. {
  796. case 0:
  797. psmid = &g_smidDemonYes2;
  798. break;
  799. case 1:
  800. psmid = &g_smidDemonMadeInUSABaby;
  801. break;
  802. case 2:
  803. psmid = &g_smidDemonMadeInUSABaby;
  804. break;
  805. case 3:
  806. psmid = &g_smidDemonLaugh1;
  807. break;
  808. }
  809. break;
  810. case CDude::TimedMine: // Mines
  811. case CDude::ProximityMine:
  812. case CDude::RemoteMine:
  813. case CDude::BouncingBettyMine:
  814. if (GetRand() % 2)
  815. psmid = &g_smidDemonTheGipper;
  816. else
  817. psmid = &g_smidDemonEvil;
  818. break;
  819. case CDude::Heatseeker: // Heatseeker
  820. switch (GetRand() % 4)
  821. {
  822. case 0:
  823. psmid = &g_smidDemonSatisfactGnty;
  824. break;
  825. case 1:
  826. psmid = &g_smidDemonMadeInUSABaby;
  827. break;
  828. case 2:
  829. if (m_sSoundBank == DEMON_RESORT_LEVEL)
  830. psmid = &g_smidDemonTennisBalls;
  831. else
  832. psmid = &g_smidDemonTheGipper;
  833. break;
  834. case 3:
  835. psmid = &g_smidDemonLaugh2;
  836. break;
  837. }
  838. break;
  839. case CDude::SprayCannon: // Spray Cannon
  840. psmid = &g_smidDemonLaugh1;
  841. break;
  842. default:
  843. break;
  844. }
  845. bFoundSample = true;
  846. break;
  847. case typeWeaponFire:
  848. switch(msg.msg_WeaponFire.sWeapon)
  849. {
  850. case CDude::SemiAutomatic: // Machine Gun
  851. case CDude::ShotGun: // Shot Gun
  852. switch (GetRand() % 3)
  853. {
  854. case 0:
  855. psmid = &g_smidDemonEatLeadSucker;
  856. break;
  857. case 1:
  858. if (m_sSoundBank == DEMON_SHANTY_LEVEL)
  859. psmid = &g_smidDemonBegForThis;
  860. else if (m_sSoundBank == DEMON_WALMART_LEVEL)
  861. psmid = &g_smidDemonBastardsWCoupons;
  862. else
  863. psmid = &g_smidDemonDie2;
  864. break;
  865. case 2:
  866. if (m_sSoundBank == DEMON_SHANTY_LEVEL)
  867. psmid = &g_smidDemonWelfareReform;
  868. else if (m_sSoundBank == DEMON_WALMART_LEVEL)
  869. psmid = &g_smidDemonLikeFreeSample;
  870. else
  871. psmid = &g_smidDemonBleed;
  872. break;
  873. }
  874. bFoundSample = true;
  875. break;
  876. case CDude::Grenade: // Grenade
  877. psmid = &g_smidDemonGrenadeWorksGreat;
  878. break;
  879. case CDude::FireBomb: // Cocktail
  880. case CDude::Napalm: // Napalm
  881. switch (GetRand() % 3)
  882. {
  883. case 0:
  884. if (m_sSoundBank == DEMON_WALMART_LEVEL)
  885. psmid = &g_smidDemonWhatLaneClosed;
  886. else
  887. psmid = &g_smidDemonFeelWrathDog;
  888. break;
  889. case 1:
  890. if (m_sSoundBank == DEMON_WALMART_LEVEL)
  891. psmid = &g_smidDemonCustomerRight;
  892. else
  893. psmid = &g_smidDemonBurnBaby;
  894. break;
  895. case 2:
  896. psmid = &g_smidDemonFreezingWarm;
  897. break;
  898. }
  899. bFoundSample = true;
  900. break;
  901. case CDude::Rocket: // Rocket
  902. switch (m_sSoundBank)
  903. {
  904. case DEMON_SHANTY_LEVEL:
  905. psmid = &g_smidDemonBegForThis;
  906. break;
  907. case DEMON_WALMART_LEVEL:
  908. if (GetRand() % 2)
  909. psmid = &g_smidDemonTenItemsOrLess;
  910. else
  911. psmid = &g_smidDemonWhatLaneClosed;
  912. break;
  913. }
  914. break;
  915. case CDude::Heatseeker: // Heatseeker
  916. switch (GetRand() % 4)
  917. {
  918. case 0:
  919. if (m_sSoundBank == DEMON_WALMART_LEVEL)
  920. psmid = &g_smidDemonWhatLaneClosed;
  921. else
  922. psmid = &g_smidDemonGone1;
  923. break;
  924. case 1:
  925. if (m_sSoundBank == DEMON_RESORT_LEVEL)
  926. psmid = &g_smidDemonHoleInOne;
  927. else
  928. psmid = &g_smidDemonGone2;
  929. break;
  930. case 2:
  931. if (m_sSoundBank == DEMON_RESORT_LEVEL)
  932. psmid = &g_smidDemonTennisBalls;
  933. else
  934. psmid = &g_smidDemonGetEm1;
  935. break;
  936. case 3:
  937. psmid = &g_smidDemonGetEm2;
  938. break;
  939. }
  940. bFoundSample = true;
  941. break;
  942. case CDude::SprayCannon: // Spray Cannon
  943. psmid = &g_smidDemonShowNoMercy;
  944. break;
  945. default:
  946. break;
  947. }
  948. break;
  949. case typeExplosion:
  950. #if 1
  951. ASSERT(m_sSoundBank < NumSoundBanks);
  952. psmid = ms_apsmidExplosion[m_sSoundBank][GetRand() % NumExplosionComments];
  953. #else
  954. switch (GetRand() % 8)
  955. {
  956. case 0:
  957. psmid = &g_smidDemonSlam;
  958. break;
  959. case 1:
  960. psmid = &g_smidDemonYes1;
  961. break;
  962. case 2:
  963. psmid = &g_smidDemonGoodOne;
  964. break;
  965. case 3:
  966. psmid = &g_smidDemonHa;
  967. break;
  968. case 4:
  969. psmid = &g_smidDemonButtSauce;
  970. break;
  971. case 5:
  972. psmid = &g_smidDemonHesOut;
  973. break;
  974. case 6:
  975. psmid = &g_smidDemonInHell;
  976. break;
  977. case 7:
  978. psmid = &g_smidDemonBuckwheat4;
  979. break;
  980. }
  981. #endif
  982. bFoundSample = true;
  983. break;
  984. case typeBurn:
  985. #if 1
  986. ASSERT(m_sSoundBank < NumSoundBanks);
  987. psmid = ms_apsmidBurn[m_sSoundBank][GetRand() % NumBurnComments];
  988. #else
  989. switch (GetRand() % 4)
  990. {
  991. case 0:
  992. psmid = &g_smidDemonSmellChicken;
  993. break;
  994. case 1:
  995. psmid = &g_smidDemonFeelHeat;
  996. break;
  997. case 2:
  998. psmid = &g_smidDemonBurn;
  999. break;
  1000. case 3:
  1001. psmid = &g_smidDemonBurnBaby;
  1002. break;
  1003. }
  1004. #endif
  1005. bFoundSample = true;
  1006. break;
  1007. case typeSuicide:
  1008. #if 1
  1009. ASSERT(m_sSoundBank < NumSoundBanks);
  1010. psmid = ms_apsmidSuicide[m_sSoundBank][GetRand() % NumSuicideComments];
  1011. #else
  1012. psmid = &g_smidDemonNoRegrets;
  1013. #endif
  1014. if (lThisTime > m_lIdleTime + ms_lMinIdleTime)
  1015. {
  1016. PlaySample( // Returns nothing.
  1017. // Does not fail.
  1018. *psmid, // In: Identifier of sample you want played.
  1019. SampleMaster::Demon); // In: Sound Volume Category for user adjustment
  1020. m_lIdleTime = lThisTime;
  1021. }
  1022. break;
  1023. case typeWrithing:
  1024. #if 1
  1025. ASSERT(m_sSoundBank < NumSoundBanks);
  1026. psmid = ms_apsmidWrithing[m_sSoundBank][GetRand() % NumWrithingComments];
  1027. #else
  1028. switch (GetRand() % 5)
  1029. {
  1030. case 0:
  1031. psmid = &g_smidDemonSissy1;
  1032. break;
  1033. case 1:
  1034. psmid = &g_smidDemonSissy2;
  1035. break;
  1036. case 2:
  1037. psmid = &g_smidDemonThatHurt1;
  1038. break;
  1039. case 3:
  1040. psmid = &g_smidDemonThatHurt2;
  1041. break;
  1042. case 4:
  1043. psmid = &g_smidDemonBleed;
  1044. break;
  1045. }
  1046. #endif
  1047. bFoundSample = true;
  1048. break;
  1049. case typeDeath:
  1050. m_sRecentKills++;
  1051. break;
  1052. }
  1053. }
  1054. }
  1055. if (lThisTime > m_lIdleTime + ms_lMinIdleTime)
  1056. {
  1057. // Check to see if a series of kills have been made and use this as the
  1058. // higher priority saying.
  1059. if (m_sRecentKills > 3 && lThisTime < m_lKillTimer)
  1060. {
  1061. #if 1
  1062. ASSERT(m_sSoundBank < NumSoundBanks);
  1063. psmid = ms_apsmidKillSeries[m_sSoundBank][GetRand() % NumKillSeriesComments];
  1064. #else
  1065. switch (GetRand() % 7)
  1066. {
  1067. case 0:
  1068. psmid = &g_smidDemonTheMan;
  1069. break;
  1070. case 1:
  1071. psmid = &g_smidDemonKickAss;
  1072. break;
  1073. case 2:
  1074. psmid = &g_smidDemonOJ;
  1075. break;
  1076. case 3:
  1077. psmid = &g_smidDemonPostal;
  1078. break;
  1079. case 4:
  1080. psmid = &g_smidDemonBuckwheat4;
  1081. break;
  1082. case 5:
  1083. psmid = &g_smidDemonLikeYou;
  1084. break;
  1085. case 6:
  1086. psmid = &g_smidDemonGoPostal4;
  1087. break;
  1088. }
  1089. #endif
  1090. if (lThisTime > m_lIdleTime + ms_lMinIdleTime)
  1091. {
  1092. PlaySample( // Returns nothing.
  1093. // Does not fail.
  1094. *psmid, // In: Identifier of sample you want played.
  1095. SampleMaster::Demon); // In: Sound Volume Category for user adjustment
  1096. m_lIdleTime = lThisTime;
  1097. m_sCommentCount++;
  1098. }
  1099. }
  1100. else
  1101. {
  1102. // See if we got a new sound
  1103. if (bFoundSample)
  1104. {
  1105. m_sCommentCount++;
  1106. if (m_sCommentCount > 4 && psmid)
  1107. {
  1108. PlaySample( // Returns nothing.
  1109. // Does not fail.
  1110. *psmid, // In: Identifier of sample you want played.
  1111. SampleMaster::Demon); // In: Sound Volume Category for user adjustment
  1112. m_lIdleTime = lThisTime;
  1113. m_sCommentCount = 0;
  1114. }
  1115. }
  1116. }
  1117. }
  1118. // Adjust Kill timer
  1119. if (lThisTime > m_lKillTimer)
  1120. {
  1121. m_sRecentKills = 0;
  1122. m_lKillTimer = lThisTime + ms_lBonusKillTime;
  1123. }
  1124. }
  1125. ////////////////////////////////////////////////////////////////////////////////
  1126. // EOF
  1127. ////////////////////////////////////////////////////////////////////////////////