WEAPON.CPP 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872
  1. #include "weapon.h"
  2. #include "globals.h"
  3. #include "qav.h"
  4. #include "debug4g.h"
  5. #include "actor.h"
  6. #include "db.h"
  7. #include "actor.h"
  8. #include "gameutil.h"
  9. #include "trig.h"
  10. #include "view.h"
  11. #include "options.h"
  12. #include "names.h"
  13. #include "triggers.h"
  14. #include "error.h"
  15. #include "misc.h"
  16. #include "screen.h"
  17. #include "tile.h"
  18. #include "ai.h" // lackey support
  19. #include "sound.h"
  20. #include "sfx.h"
  21. #define kShotgunBarrels 2
  22. #define kVectorsPerBarrel 16
  23. #define kMaxShotgunVectors (kShotgunBarrels * kVectorsPerBarrel)
  24. enum {
  25. kVoodooStabChest = 1,
  26. kVoodooStabShoulder,
  27. kVoodooStabEye,
  28. kVoodooStabGroin,
  29. kVoodooStabSelf,
  30. };
  31. // Weapon States
  32. enum {
  33. kFindWeapon = -1, // flag to find a loaded weapon
  34. kForkIdle = 0,
  35. kBicOpen = 0,
  36. kBicIdle,
  37. kBicSwitch,
  38. kBicNext,
  39. kCanIdle = kBicNext,
  40. kCanFire,
  41. kTNTStickIdle = kBicNext,
  42. kTNTStickFuse1,
  43. kTNTStickFuse2,
  44. kTNTStickThrow,
  45. kTNTBundleIdle,
  46. kTNTBundleFuse1,
  47. kTNTBundleFuse2,
  48. kTNTBundleThrow,
  49. kTNTProxIdle,
  50. kTNTProxEmpty,
  51. kTNTProxThrow,
  52. kTNTRemoteIdle1, // bundle and detonator
  53. kTNTRemoteIdle2, // detonator only
  54. kTNTRemoteEmpty,
  55. kTNTRemoteThrow,
  56. kShotInitialize = 0, // indicates first-time reload required
  57. kShotIdle0,
  58. kShotIdle1,
  59. kShotIdle2,
  60. kShotFire1,
  61. kShotFire2,
  62. kShotLower,
  63. kFlareInitialize = 0,
  64. kFlareRaise,
  65. kFlareIdle,
  66. kFlareFire,
  67. kFlareReload,
  68. kFlareLower,
  69. kTommyIdle = 0,
  70. kSpearInitialize = 0,
  71. kSpearRaise,
  72. kSpearIdle1,
  73. kSpearIdle2,
  74. kSpearFire,
  75. kSpearReload,
  76. kSpearLower,
  77. kShadowInitialize = 0,
  78. kShadowRaise,
  79. kShadowIdle,
  80. kShadowFire,
  81. kShadowLower,
  82. kBeastInitialize = 0,
  83. kBeastRaise,
  84. kBeastIdle,
  85. kBeastAttack,
  86. kBeastLower,
  87. kDollInitialize = 0,
  88. kDollRaise,
  89. kDollIdle,
  90. kDollStab1,
  91. kDollStab2,
  92. kDollStab3,
  93. kDollStab4,
  94. kDollStab5,
  95. kDollLower,
  96. kDollSpell,
  97. };
  98. // Weapon Modes
  99. enum {
  100. kForkModeNormal = 0,
  101. kForkModeMax,
  102. kSprayModeNormal = 0,
  103. kSprayModeMax,
  104. kTNTModeStick = 0,
  105. kTNTModeBundle,
  106. kTNTModeProximity,
  107. kTNTModeRemote,
  108. kTNTModeMax,
  109. kShotgunModeNormal = 0,
  110. kShotgunModeMax,
  111. kTommyModeNormal = 0,
  112. kTommyModeAP,
  113. kTommyModeMax,
  114. kFlareModeNormal = 0,
  115. kFlareModeSB,
  116. kFlareModeMax,
  117. kVoodooModeNormal = 0,
  118. kVoodooModeMax,
  119. kSpearModeNormal = 0,
  120. kSpearModeXP,
  121. kSpearModeMax,
  122. kShadowModeNormal = 0,
  123. kShadowModeMax,
  124. kBeastModeNormal = 0,
  125. kBeastModeMax,
  126. };
  127. enum {
  128. kQAVForkUp = 0,
  129. kQAVForkIdle,
  130. kQAVForkStab,
  131. kQAVForkDown,
  132. kQAVBicUp, // raise lighter and open
  133. kQAVBicFlame, // light lighter
  134. kQAVBicIdle, // burning lighter
  135. kQAVBicDown, // lower and close burning lighter
  136. kQAVSprayUp,
  137. kQAVSprayIdle,
  138. kQAVSprayFire,
  139. kQAVSprayDown,
  140. kQAVStickUp, // raise just stick
  141. kQAVStickDown, // lower just stick
  142. kQAVStickUp2, // raise lighter and stick
  143. kQAVStickDown2, // lower lighter and stick
  144. kQAVStickIdle,
  145. kQAVStickFuse,
  146. kQAVStickDrop,
  147. kQAVStickThrow,
  148. kQAVBundleUp, // raise just bundle
  149. kQAVBundleDown, // lower just bundle
  150. kQAVBundleUp2, // raise lighter and bundle
  151. kQAVBundleDown2, // lower lighter and bundle
  152. kQAVBundleIdle,
  153. kQAVBundleFuse,
  154. kQAVBundleDrop,
  155. kQAVBundleThrow,
  156. kQAVTNTExplode,
  157. kQAVProxUp,
  158. kQAVProxDown,
  159. kQAVProxIdle,
  160. kQAVProxDrop,
  161. kQAVProxThrow,
  162. kQAVRemoteUp1, // detonator present, raise bundle
  163. kQAVRemoteUp2, // raise both bundle and detonator
  164. kQAVRemoteUp3, // raise detonator only
  165. kQAVRemoteDown1, // both present, lower bundle
  166. kQAVRemoteDown2, // lower both bundle and detonator
  167. kQAVRemoteDown3, // lower detonator only
  168. kQAVRemoteIdle1, // both bundle and detonator
  169. kQAVRemoteIdle2, // detonator only
  170. kQAVRemoteDrop,
  171. kQAVRemoteThrow,
  172. kQAVRemoteFire,
  173. kQAVFlareUp,
  174. kQAVFlareIdle,
  175. kQAVFlareFire,
  176. // kQAVFlareReload,
  177. kQAVFlareDown,
  178. kQAVShotUp,
  179. kQAVShotIdle0,
  180. kQAVShotIdle1,
  181. kQAVShotIdle2,
  182. kQAVShotFireL,
  183. kQAVShotFireR,
  184. kQAVShotReload,
  185. kQAVShotDown,
  186. kQAVTommyUp,
  187. kQAVTommyIdle,
  188. kQAVTommyFire1,
  189. kQAVTommyDown,
  190. kQAVSpearUp,
  191. kQAVSpearIdle1,
  192. kQAVSpearIdle2,
  193. kQAVSpearFire,
  194. kQAVSpearDown,
  195. kQAVShadowUp,
  196. kQAVShadowIdle,
  197. kQAVShadowFire,
  198. kQAVShadowDown,
  199. kQAVBeastUp,
  200. kQAVBeastIdle,
  201. kQAVBeastAttack1,
  202. kQAVBeastAttack2,
  203. kQAVBeastAttack3,
  204. kQAVBeastAttack4,
  205. kQAVBeastDown,
  206. kQAVDollUp,
  207. kQAVDollIdleStill,
  208. kQAVDollIdleMoving,
  209. kQAVDollStab1,
  210. kQAVDollStab2,
  211. kQAVDollStab3,
  212. kQAVDollStab4,
  213. kQAVDollStab5,
  214. kQAVDollDown,
  215. kQAVDollSpell,
  216. kQAVEnd
  217. };
  218. static char * weaponQAVNames[kQAVEnd] =
  219. {
  220. "FORKUP", //kQAVForkUp = 0,
  221. "FORKIDLE", //kQAVForkIdle,
  222. "PFORK", //kQAVForkStab,
  223. "FORKDOWN", //kQAVForkDown,
  224. "LITEOPEN", //kQAVBicUp,
  225. "LITEFLAM", //kQAVBicFlame,
  226. "LITEIDLE", //kQAVBicIdle,
  227. "LITECLO2", //kQAVBicDown,
  228. "CANPREF", //kQAVSprayUp,
  229. "CANIDLE", //kQAVSprayIdle,
  230. "CANFIRE", //kQAVSprayFire,
  231. "CANDOWN", //kQAVSprayDown,
  232. "DYNUP", //kQAVStickUp,
  233. "DYNDOWN", //kQAVStickDown,
  234. "DYNUP2", //kQAVStickUp2,
  235. "DYNDOWN2", //kQAVStickDown2,
  236. "DYNIDLE", //kQAVStickIdle,
  237. "DYNFUSE", //kQAVStickFuse,
  238. "DYNDROP", //kQAVStickDrop,
  239. "DYNTHRO", //kQAVStickThrow,
  240. "BUNUP", //kQAVBundleUp,
  241. "BUNDOWN", //kQAVBundleDown,
  242. "BUNUP2", //kQAVBundleUp2,
  243. "BUNDOWN2", //kQAVBundleDown2,
  244. "BUNIDLE", //kQAVBundleIdle,
  245. "BUNFUSE", //kQAVBundleFuse,
  246. "BUNDROP", //kQAVBundleDrop,
  247. "BUNTHRO", //kQAVBundleThrow,
  248. "DYNEXPLO", //kQAVExplode,
  249. "PROXUP", //kQAVProxUp,
  250. "PROXDOWN", //kQAVProxDown,
  251. "PROXIDLE", //kQAVProxIdle,
  252. "PROXDROP", //kQAVProxDrop,
  253. "PROXTHRO", //kQAVProxThrow,
  254. "REMUP1", //kQAVRemoteUp1,
  255. "REMUP2", //kQAVRemoteUp2,
  256. "REMUP3", //kQAVRemoteUp3,
  257. "REMDOWN1", //kQAVRemoteDown1,
  258. "REMDOWN2", //kQAVRemoteDown2,
  259. "REMDOWN3", //kQAVRemoteDown3,
  260. "REMIDLE1", //kQAVRemoteIdle1,
  261. "REMIDLE2", //kQAVRemoteIdle2,
  262. "REMDROP", //kQAVRemoteDrop,
  263. "REMTHRO", //kQAVRemoteThrow,
  264. "REMFIRE", //kQAVRemoteFire,
  265. "FLARUP",
  266. "FLARIDLE",
  267. "FLARFIR2",
  268. // "FLARLOAD",
  269. "FLARDOWN",
  270. "SHOTUP", //kQAVShotUp,
  271. "SHOTI3", //kQAVShotIdle0,
  272. "SHOTI2", //kQAVShotIdle1,
  273. "SHOTI1", //kQAVShotIdle2,
  274. "SHOTF1", //kQAVShotFireL,
  275. "SHOTF2", //kQAVShotFireR,
  276. "SHOTL1", //kQAVShotReload,
  277. "SHOTDOWN", //kQAVShotDown,
  278. "TOMUP", //kQAVTommyUp,
  279. "TOMIDLE", //kQAVTommyIdle,
  280. "TOMFIRE", //kQAVTommyFire1,
  281. "TOMDOWN", //kQAVTommyDown,
  282. "SGUNUP", //kQAVSpearUp,
  283. "SGUNIDL1", //kQAVSpearIdle1,
  284. "SGUNIDL2", //kQAVSpearIdle2,
  285. "SGUNFIRE", //kQAVSpearFire,
  286. "SGUNDOWN", //kQAVSpearDown,
  287. "DARKUP", //kQAVShadowUp,
  288. "DARKIDLE", //kQAVShadowIdle,
  289. "DARKFIRE", //kQAVShadowFire,
  290. "DARKDOWN", //kQAVShadowDown,
  291. "BSTUP", //kQAVBeastUp
  292. "BSTIDLE", //kQAVBeastIdle,
  293. "BSTATAK1", //kQAVBeastAttack1,
  294. "BSTATAK2", //kQAVBeastAttack2,
  295. "BSTATAK3", //kQAVBeastAttack3,
  296. "BSTATAK4", //kQAVBeastAttack4,
  297. "BSTDOWN",
  298. "VDUP", //kQAVDollUp
  299. "VDIDLE1", //kQAVDollIdleStill (PLAYER IS STILL)
  300. "VDIDLE2", //kQAVDollIdleMoving (PLAYER IS WALKING/RUNNING)
  301. "VDFIRE1", //kQAVDollStab1
  302. "VDFIRE2", //kQAVDollStab2
  303. "VDFIRE3", //kQAVDollStab3
  304. "VDFIRE4", //kQAVDollStab4
  305. "VDFIRE5", //kQAVDollStab5
  306. "VDDOWN", //kQAVDollDown
  307. "VDSPEL1", //kQAVDollSpell
  308. };
  309. static modeMax[kWeaponMax + 1] =
  310. {
  311. 0,
  312. kForkModeMax,
  313. kSprayModeMax,
  314. kTNTModeMax,
  315. kShotgunModeMax,
  316. kTommyModeMax,
  317. kFlareModeMax,
  318. kVoodooModeMax,
  319. kSpearModeMax,
  320. kShadowModeMax,
  321. kBeastModeMax,
  322. };
  323. static QAV *weaponQAV[kQAVEnd];
  324. /****************************************************************************
  325. ** LOCAL callback prototypes
  326. ****************************************************************************/
  327. static void FireReanimator( int /* nTrigger */, PLAYER *pPlayer );
  328. /****************************************************************************
  329. ** function calls
  330. ****************************************************************************/
  331. static BOOL CheckAmmo( PLAYER *pPlayer, int nAmmo )
  332. {
  333. if ( gInfiniteAmmo )
  334. return TRUE;
  335. if ( nAmmo == kAmmoNone )
  336. return TRUE;
  337. return pPlayer->ammoCount[nAmmo] > 0;
  338. }
  339. static void UseAmmo( PLAYER *pPlayer, int nAmmo, int nCount )
  340. {
  341. if ( gInfiniteAmmo )
  342. return;
  343. if ( nAmmo == kAmmoNone )
  344. return;
  345. pPlayer->ammoCount[nAmmo] = ClipLow(pPlayer->ammoCount[nAmmo] - nCount, 0);
  346. }
  347. void WeaponInit( void )
  348. {
  349. // get pointers to all the QAV resources
  350. for (int i = 0; i < kQAVEnd; i++)
  351. {
  352. RESHANDLE hQAV = gSysRes.Lookup(weaponQAVNames[i], ".QAV");
  353. if (hQAV == NULL)
  354. {
  355. dprintf("Could not load %s.QAV\n", weaponQAVNames[i]);
  356. ThrowError("Missing Weapon QAV file", ES_ERROR);
  357. }
  358. weaponQAV[i] = (QAV *)gSysRes.Lock(hQAV);
  359. }
  360. dprintf("Preload weapon QAV tiles\n");
  361. for (i = 0; i < kQAVEnd; i++)
  362. {
  363. if (weaponQAV[i] != NULL )
  364. weaponQAV[i]->Preload();
  365. }
  366. }
  367. void WeaponDraw( PLAYER *pPlayer, int shade, int x, int y )
  368. {
  369. dassert(pPlayer != NULL);
  370. QAV *pQAV = pPlayer->pWeaponQAV;
  371. ulong t;
  372. if ( pQAV == NULL )
  373. return;
  374. if (pPlayer->weaponTimer == 0) // playing idle QAV?
  375. t = gGameClock % pQAV->duration;
  376. else
  377. t = pQAV->duration - pPlayer->weaponTimer;
  378. pQAV->origin.x = x;
  379. pQAV->origin.y = y;
  380. int nPowerRemaining = powerupCheck( pPlayer, kItemLtdInvisibility - kItemBase );
  381. int nFlags = kQFrameScale;
  382. if ( nPowerRemaining >= (kTimerRate * 8) || nPowerRemaining && ( gGameClock & 32 ) )
  383. {
  384. nFlags |= kQFrameTranslucent;
  385. shade = -128;
  386. }
  387. pQAV->Draw(t, shade, nFlags);
  388. }
  389. void WeaponPlay( PLAYER *pPlayer )
  390. {
  391. dassert(pPlayer != NULL);
  392. QAV *pQAV = pPlayer->pWeaponQAV;
  393. if ( pQAV == NULL )
  394. return;
  395. ulong t = pQAV->duration - pPlayer->weaponTimer;
  396. pQAV->Play(t - kFrameTicks, t, pPlayer->weaponCallback, pPlayer);
  397. }
  398. static void StartQAV( PLAYER *pPlayer, int weaponIndex, QAVCALLBACK callback = NULL, BOOL fLoop = FALSE)
  399. {
  400. pPlayer->pWeaponQAV = weaponQAV[weaponIndex];
  401. pPlayer->weaponTimer = pPlayer->pWeaponQAV->duration;
  402. pPlayer->weaponCallback = callback;
  403. pPlayer->fLoopQAV = fLoop;
  404. }
  405. #define kAimMaxDist M2X(100)
  406. #define kAimMaxAngle kAngle15
  407. #define kAimMaxSlope 9459 // tan(30) << 14
  408. #define kTrackRate 0x2000 // 0x10000 tracks instantly, 0 takes forever
  409. static void UpdateAimVector( PLAYER *pPlayer )
  410. {
  411. dassert(pPlayer != NULL);
  412. SPRITE *pSprite = pPlayer->sprite;
  413. int x = pSprite->x;
  414. int y = pSprite->y;
  415. int z = pSprite->z - pPlayer->weaponAboveZ;
  416. VECTOR3D aim;
  417. aim.dx = Cos(pSprite->ang) >> 16;
  418. aim.dy = Sin(pSprite->ang) >> 16;
  419. aim.dz = pPlayer->slope;
  420. int nAimSprite = -1;
  421. if ( gAutoAim )
  422. {
  423. int closest = 0x7FFFFFFF;
  424. for (short nTarget = headspritestat[kStatDude]; nTarget >= 0; nTarget = nextspritestat[nTarget] )
  425. {
  426. SPRITE *pTarget = &sprite[nTarget];
  427. // don't target yourself!
  428. if ( pTarget == pSprite )
  429. continue;
  430. int dx, dy, dz;
  431. dx = pTarget->x - x;
  432. dy = pTarget->y - y;
  433. dz = pTarget->z - z;
  434. int dist = qdist(dx, dy);
  435. if ( dist > closest || dist > kAimMaxDist )
  436. continue;
  437. int ang = getangle(dx, dy);
  438. if ( qabs(((ang - pSprite->ang + kAngle180) & kAngleMask) - kAngle180) > kAimMaxAngle )
  439. continue;
  440. int z1 = z + mulscale(pPlayer->slope, dist, 10);
  441. int z2 = mulscale(kAimMaxSlope, dist, 10);
  442. if ( (pTarget->z < z1 - z2) || (pTarget->z > z1 + z2) )
  443. continue;
  444. if ( cansee(x, y, z, pSprite->sectnum, pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum) )
  445. {
  446. closest = dist;
  447. aim.dx = Cos(ang) >> 16;
  448. aim.dy = Sin(ang) >> 16;
  449. aim.dz = divscale(dz, dist, 10);
  450. nAimSprite = nTarget;
  451. }
  452. }
  453. // barrels
  454. for (nTarget = headspritestat[kStatThing]; nTarget >= 0; nTarget = nextspritestat[nTarget] )
  455. {
  456. SPRITE *pTarget = &sprite[nTarget];
  457. if (pTarget->type != kThingTNTBarrel )
  458. continue;
  459. int dx, dy, dz;
  460. dx = pTarget->x - x;
  461. dy = pTarget->y - y;
  462. dz = pTarget->z - z;
  463. int dist = qdist(dx, dy);
  464. if ( dist > closest || dist > kAimMaxDist )
  465. continue;
  466. int ang = getangle(dx, dy);
  467. if ( qabs(((ang - pSprite->ang + kAngle180) & kAngleMask) - kAngle180) > kAimMaxAngle )
  468. continue;
  469. int z1 = z + mulscale(pPlayer->slope, dist, 10);
  470. int z2 = mulscale(kAimMaxSlope, dist, 10);
  471. if ( (pTarget->z < z1 - z2) || (pTarget->z > z1 + z2) )
  472. continue;
  473. if ( cansee(x, y, z, pSprite->sectnum, pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum) )
  474. {
  475. closest = dist;
  476. aim.dx = Cos(ang) >> 16;
  477. aim.dy = Sin(ang) >> 16;
  478. aim.dz = divscale(dz, dist, 10);
  479. nAimSprite = nTarget;
  480. }
  481. }
  482. }
  483. VECTOR3D relAim = aim;
  484. RotateVector(&relAim.dx, &relAim.dy, -pSprite->ang);
  485. pPlayer->relAim.dx = dmulscale16r(pPlayer->relAim.dx, 0x10000 - kTrackRate, relAim.dx, kTrackRate);
  486. pPlayer->relAim.dy = dmulscale16r(pPlayer->relAim.dy, 0x10000 - kTrackRate, relAim.dy, kTrackRate);
  487. pPlayer->relAim.dz = dmulscale16r(pPlayer->relAim.dz, 0x10000 -kTrackRate, relAim.dz, kTrackRate);
  488. pPlayer->aim = pPlayer->relAim;
  489. RotateVector(&pPlayer->aim.dx, &pPlayer->aim.dy, pSprite->ang);
  490. pPlayer->aimSprite = nAimSprite;
  491. }
  492. void WeaponRaise( PLAYER *pPlayer, INPUT *pInput )
  493. {
  494. dassert( pPlayer != 0 );
  495. pPlayer->weapon = pInput->newWeapon;
  496. pInput->newWeapon = 0;
  497. dprintf("WeaponRaise: weapon = %d, mode = %d\n",
  498. pPlayer->weapon, pPlayer->weaponMode[pPlayer->weapon]);
  499. switch( pPlayer->weapon )
  500. {
  501. case kWeaponPitchfork:
  502. StartQAV(pPlayer, kQAVForkUp);
  503. pPlayer->weaponState = kForkIdle;
  504. pPlayer->weaponAmmo = kAmmoNone;
  505. break;
  506. case kWeaponSprayCan:
  507. StartQAV(pPlayer, kQAVBicUp);
  508. pPlayer->weaponState = kBicOpen;
  509. pPlayer->weaponAmmo = kAmmoSprayCan;
  510. break;
  511. case kWeaponTNT:
  512. switch ( pPlayer->weaponMode[kWeaponTNT] )
  513. {
  514. case kTNTModeStick:
  515. StartQAV(pPlayer, kQAVStickUp2);
  516. pPlayer->weaponState = kTNTStickIdle;
  517. pPlayer->weaponAmmo = kAmmoTNTStick;
  518. break;
  519. case kTNTModeBundle:
  520. StartQAV(pPlayer, kQAVBundleUp2);
  521. pPlayer->weaponState = kTNTBundleIdle;
  522. pPlayer->weaponAmmo = kAmmoTNTStick;
  523. break;
  524. case kTNTModeProximity:
  525. StartQAV(pPlayer, kQAVProxUp);
  526. pPlayer->weaponState = kTNTProxIdle;
  527. pPlayer->weaponAmmo = kAmmoTNTProximity;
  528. break;
  529. case kTNTModeRemote:
  530. StartQAV(pPlayer, kQAVRemoteUp2);
  531. pPlayer->weaponState = kTNTRemoteIdle1;
  532. pPlayer->weaponAmmo = kAmmoTNTRemote;
  533. break;
  534. }
  535. break;
  536. case kWeaponShotgun:
  537. StartQAV(pPlayer, kQAVShotUp);
  538. if ( gInfiniteAmmo || pPlayer->ammoCount[kAmmoShell] > 1 )
  539. pPlayer->weaponState = kShotIdle2;
  540. else if ( pPlayer->ammoCount[kAmmoShell] > 0 )
  541. pPlayer->weaponState = kShotIdle1;
  542. else
  543. pPlayer->weaponState = kShotIdle0;
  544. pPlayer->weaponAmmo = kAmmoShell;
  545. break;
  546. case kWeaponTommy:
  547. StartQAV(pPlayer, kQAVTommyUp);
  548. pPlayer->weaponState = kTommyIdle;
  549. pPlayer->weaponAmmo = kAmmoBullet;
  550. break;
  551. case kWeaponVoodoo:
  552. StartQAV(pPlayer, kQAVDollUp);
  553. pPlayer->weaponState = kDollIdle;
  554. pPlayer->weaponAmmo = kAmmoVoodoo;
  555. break;
  556. case kWeaponFlare:
  557. StartQAV(pPlayer, kQAVFlareUp);
  558. pPlayer->weaponState = kFlareIdle;
  559. pPlayer->weaponAmmo = kAmmoFlare;
  560. break;
  561. case kWeaponSpear:
  562. StartQAV(pPlayer, kQAVSpearUp);
  563. if ( pPlayer->ammoCount[kAmmoSpear] > 0 || pPlayer->ammoCount[kAmmoSpearXP] > 0 )
  564. pPlayer->weaponState = kSpearIdle1;
  565. else
  566. pPlayer->weaponState = kSpearIdle2;
  567. pPlayer->weaponAmmo = kAmmoSpear;
  568. break;
  569. case kWeaponShadow:
  570. StartQAV(pPlayer, kQAVShadowUp);
  571. pPlayer->weaponState = kShadowIdle;
  572. pPlayer->weaponAmmo = kAmmoNone;
  573. break;
  574. case kWeaponBeast:
  575. StartQAV(pPlayer, kQAVBeastUp);
  576. pPlayer->weaponState = kBeastIdle;
  577. pPlayer->weaponAmmo = kAmmoNone;
  578. break;
  579. }
  580. }
  581. void WeaponLower( PLAYER *pPlayer, INPUT *pInput )
  582. {
  583. dprintf("WeaponLower()\n");
  584. dassert( pPlayer != 0 );
  585. int nWeapon = pPlayer->weapon;
  586. int nState = pPlayer->weaponState;
  587. switch( nWeapon )
  588. {
  589. case kWeaponPitchfork:
  590. StartQAV(pPlayer, kQAVForkDown);
  591. break;
  592. case kWeaponSprayCan:
  593. switch( nState )
  594. {
  595. case kBicIdle:
  596. StartQAV(pPlayer, kQAVBicDown);
  597. break;
  598. case kBicSwitch:
  599. pPlayer->weapon = pInput->newWeapon;
  600. pPlayer->weaponState = kBicIdle;
  601. pInput->newWeapon = 0;
  602. return;
  603. default:
  604. StartQAV(pPlayer, kQAVSprayDown);
  605. if ( pInput->newWeapon == kWeaponTNT )
  606. pPlayer->weaponState = kBicSwitch;
  607. else
  608. pPlayer->weaponState = kBicIdle;
  609. return;
  610. }
  611. break;
  612. case kWeaponTNT:
  613. {
  614. switch( nState )
  615. {
  616. case kBicSwitch:
  617. pPlayer->weapon = pInput->newWeapon;
  618. pInput->newWeapon = 0;
  619. return;
  620. case kBicIdle:
  621. StartQAV(pPlayer, kQAVBicDown);
  622. break;
  623. case kTNTStickIdle:
  624. if ( pInput->newWeapon == kWeaponSprayCan )
  625. {
  626. StartQAV(pPlayer, kQAVStickDown);
  627. pPlayer->weaponState = kBicSwitch;
  628. return;
  629. }
  630. StartQAV(pPlayer, kQAVStickDown2);
  631. break;
  632. case kTNTBundleIdle:
  633. if ( pInput->newWeapon == kWeaponSprayCan )
  634. {
  635. StartQAV(pPlayer, kQAVBundleDown);
  636. pPlayer->weaponState = kBicSwitch;
  637. return;
  638. }
  639. StartQAV(pPlayer, kQAVBundleDown2);
  640. break;
  641. case kTNTProxIdle:
  642. StartQAV(pPlayer, kQAVProxDown);
  643. break;
  644. case kTNTRemoteIdle1:
  645. StartQAV(pPlayer, kQAVRemoteDown2);
  646. break;
  647. case kTNTRemoteIdle2:
  648. StartQAV(pPlayer, kQAVRemoteDown3);
  649. break;
  650. }
  651. break;
  652. }
  653. case kWeaponShotgun:
  654. StartQAV(pPlayer, kQAVShotDown);
  655. break;
  656. case kWeaponTommy:
  657. StartQAV(pPlayer, kQAVTommyDown);
  658. break;
  659. case kWeaponFlare:
  660. StartQAV(pPlayer, kQAVFlareDown);
  661. break;
  662. case kWeaponVoodoo:
  663. StartQAV(pPlayer, kQAVDollDown);
  664. break;
  665. case kWeaponSpear:
  666. StartQAV(pPlayer, kQAVSpearDown);
  667. break;
  668. case kWeaponShadow:
  669. StartQAV(pPlayer, kQAVShadowDown);
  670. break;
  671. case kWeaponBeast:
  672. StartQAV(pPlayer, kQAVBeastDown);
  673. break;
  674. }
  675. if (pInput->newWeapon == pPlayer->weapon)
  676. {
  677. if ( ++pPlayer->weaponMode[pPlayer->weapon] == modeMax[pPlayer->weapon] )
  678. {
  679. pPlayer->weaponMode[pPlayer->weapon] = 0;
  680. pInput->newWeapon = 0;
  681. }
  682. }
  683. pPlayer->weapon = 0;
  684. }
  685. void WeaponUpdateState( PLAYER *pPlayer)
  686. {
  687. SPRITE *pSprite = pPlayer->sprite;
  688. XSPRITE *pXSprite = pPlayer->xsprite;
  689. int nWeapon = pPlayer->weapon;
  690. int nState = pPlayer->weaponState;
  691. switch( nWeapon )
  692. {
  693. case kWeaponPitchfork:
  694. pPlayer->pWeaponQAV = weaponQAV[kQAVForkIdle];
  695. break;
  696. case kWeaponSprayCan:
  697. switch( nState )
  698. {
  699. case kBicOpen:
  700. StartQAV(pPlayer, kQAVBicFlame);
  701. pPlayer->weaponState = kBicIdle;
  702. break;
  703. case kBicIdle:
  704. if ( CheckAmmo(pPlayer, kAmmoSprayCan) )
  705. {
  706. StartQAV(pPlayer, kQAVSprayUp);
  707. pPlayer->weaponState = kCanIdle;
  708. }
  709. else
  710. pPlayer->pWeaponQAV = weaponQAV[kQAVBicIdle];
  711. break;
  712. case kCanIdle:
  713. pPlayer->pWeaponQAV = weaponQAV[kQAVSprayIdle];
  714. break;
  715. case kCanFire:
  716. if ( CheckAmmo(pPlayer, kAmmoSprayCan) )
  717. {
  718. pPlayer->pWeaponQAV = weaponQAV[kQAVSprayIdle];
  719. pPlayer->weaponState = kCanIdle;
  720. }
  721. else
  722. {
  723. StartQAV(pPlayer, kQAVSprayDown);
  724. pPlayer->weaponState = kBicIdle;
  725. }
  726. break;
  727. }
  728. break;
  729. case kWeaponTNT:
  730. switch( nState )
  731. {
  732. case kBicIdle:
  733. switch ( pPlayer->weaponMode[kWeaponTNT] )
  734. {
  735. case kTNTModeStick:
  736. StartQAV(pPlayer, kQAVStickUp);
  737. pPlayer->weaponState = kTNTStickIdle;
  738. break;
  739. case kTNTModeBundle:
  740. StartQAV(pPlayer, kQAVBundleUp);
  741. pPlayer->weaponState = kTNTBundleIdle;
  742. break;
  743. }
  744. break;
  745. case kBicOpen:
  746. StartQAV(pPlayer, kQAVBicFlame);
  747. pPlayer->weaponState = kBicIdle;
  748. break;
  749. case kBicSwitch:
  750. if ( pPlayer->ammoCount[kAmmoTNTStick] > 0)
  751. {
  752. StartQAV(pPlayer, kQAVStickUp);
  753. pPlayer->weaponState = kTNTStickIdle;
  754. }
  755. else
  756. pPlayer->pWeaponQAV = weaponQAV[kQAVBicIdle];
  757. break;
  758. case kTNTStickIdle:
  759. pPlayer->pWeaponQAV = weaponQAV[kQAVStickIdle];
  760. break;
  761. case kTNTBundleIdle:
  762. pPlayer->pWeaponQAV = weaponQAV[kQAVBundleIdle];
  763. break;
  764. case kTNTProxIdle:
  765. pPlayer->pWeaponQAV = weaponQAV[kQAVProxIdle];
  766. break;
  767. case kTNTProxEmpty:
  768. StartQAV(pPlayer, kQAVProxUp);
  769. pPlayer->weaponState = kTNTProxIdle;
  770. break;
  771. case kTNTRemoteIdle1:
  772. pPlayer->pWeaponQAV = weaponQAV[kQAVRemoteIdle1];
  773. break;
  774. case kTNTRemoteIdle2:
  775. pPlayer->pWeaponQAV = weaponQAV[kQAVRemoteIdle2];
  776. break;
  777. case kTNTRemoteEmpty:
  778. StartQAV(pPlayer, kQAVRemoteUp2);
  779. pPlayer->weaponState = kTNTRemoteIdle1;
  780. break;
  781. }
  782. break;
  783. case kWeaponShotgun:
  784. switch ( nState )
  785. {
  786. case kShotIdle0:
  787. if ( CheckAmmo(pPlayer, kAmmoShell) )
  788. {
  789. StartQAV(pPlayer, kQAVShotReload);
  790. if ( gInfiniteAmmo || pPlayer->ammoCount[kAmmoShell] > 1 )
  791. pPlayer->weaponState = kShotIdle2;
  792. else
  793. pPlayer->weaponState = kShotIdle1;
  794. }
  795. else
  796. pPlayer->pWeaponQAV = weaponQAV[kQAVShotIdle0];
  797. break;
  798. case kShotIdle1:
  799. pPlayer->pWeaponQAV = weaponQAV[kQAVShotIdle1];
  800. break;
  801. case kShotIdle2:
  802. pPlayer->pWeaponQAV = weaponQAV[kQAVShotIdle2];
  803. break;
  804. }
  805. break;
  806. case kWeaponTommy:
  807. pPlayer->pWeaponQAV = weaponQAV[kQAVTommyIdle];
  808. break;
  809. case kWeaponFlare:
  810. if (nState == kFlareIdle)
  811. pPlayer->pWeaponQAV = weaponQAV[kQAVFlareIdle];
  812. break;
  813. case kWeaponVoodoo:
  814. switch ( pXSprite->moveState )
  815. {
  816. case kMoveWalk:
  817. if ( qabs(pPlayer->swayHeight) > (3 << 8) )
  818. pPlayer->pWeaponQAV = weaponQAV[kQAVDollIdleMoving];
  819. else
  820. pPlayer->pWeaponQAV = weaponQAV[kQAVDollIdleStill];
  821. break;
  822. case kMoveLand:
  823. pPlayer->pWeaponQAV = weaponQAV[kQAVDollIdleMoving];
  824. break;
  825. default:
  826. pPlayer->pWeaponQAV = weaponQAV[kQAVDollIdleStill];
  827. break;
  828. }
  829. break;
  830. case kWeaponSpear:
  831. switch ( nState )
  832. {
  833. case kSpearIdle1:
  834. pPlayer->pWeaponQAV = weaponQAV[kQAVSpearIdle1];
  835. break;
  836. case kSpearIdle2:
  837. pPlayer->pWeaponQAV = weaponQAV[kQAVSpearIdle2];
  838. break;
  839. }
  840. break;
  841. case kWeaponShadow:
  842. pPlayer->pWeaponQAV = weaponQAV[kQAVShadowIdle];
  843. break;
  844. case kWeaponBeast:
  845. pPlayer->pWeaponQAV = weaponQAV[kQAVBeastIdle];
  846. break;
  847. }
  848. }
  849. static void FirePitchfork( int /* nTrigger */, PLAYER *pPlayer )
  850. {
  851. SPRITE *pSprite = pPlayer->sprite;
  852. int z = pSprite->z - pPlayer->weaponAboveZ;
  853. for ( int i = 0; i < 4; i++ )
  854. {
  855. // dispersal modifiers
  856. int ddx = BiRandom(2000);
  857. int ddy = BiRandom(2000);
  858. int ddz = BiRandom(2000);
  859. actFireVector(pPlayer->nSprite, z,
  860. pPlayer->aim.dx + ddx, pPlayer->aim.dy + ddy, pPlayer->aim.dz + ddz,
  861. kVectorTine);
  862. }
  863. }
  864. static void FireSpray( int /* nTrigger */, PLAYER *pPlayer )
  865. {
  866. playerFireMissile(pPlayer, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz,
  867. kMissileSprayFlame);
  868. UseAmmo(pPlayer, kAmmoSprayCan, kFrameTicks);
  869. }
  870. #define kMaxThrowTime (3 * kTimerRate) // how long to hold fire to get farthest throw
  871. #define kMinThrowVel ((M2X(8.0) << 4) / kTimerRate)
  872. #define kMaxThrowVel ((M2X(30.0) << 4) / kTimerRate)
  873. #define kSlopeThrow -8192 // tan(26)
  874. static void ThrowStick( int /* nTrigger */, PLAYER *pPlayer )
  875. {
  876. pPlayer->throwTime = ClipHigh(pPlayer->throwTime, kMaxThrowTime);
  877. int velocity = muldiv(pPlayer->throwTime, kMaxThrowVel - kMinThrowVel, kMaxThrowTime) + kMinThrowVel;
  878. int nThing = playerFireThing(pPlayer, kSlopeThrow, kThingTNTStick, velocity);
  879. XSPRITE *pXSprite = &xsprite[sprite[nThing].extra];
  880. if ( pPlayer->fuseTime < 0 )
  881. pXSprite->triggerProximity = 1;
  882. else
  883. evPost(nThing, SS_SPRITE, pPlayer->fuseTime);
  884. UseAmmo(pPlayer, kAmmoTNTStick, 1);
  885. }
  886. static void DropStick( int /* nTrigger */, PLAYER *pPlayer )
  887. {
  888. int nThing = playerFireThing(pPlayer, 0, kThingTNTStick, 0);
  889. evPost(nThing, SS_SPRITE, pPlayer->fuseTime);
  890. UseAmmo(pPlayer, kAmmoTNTStick, 1);
  891. }
  892. static void ExplodeStick( int /* nTrigger */, PLAYER *pPlayer )
  893. {
  894. int nThing = playerFireThing(pPlayer, 0, kThingTNTStick, 0);
  895. evPost(nThing, SS_SPRITE, 0); // trigger it immediately
  896. UseAmmo(pPlayer, kAmmoTNTStick, 1);
  897. StartQAV(pPlayer, kQAVTNTExplode);
  898. pPlayer->weapon = 0; // drop the hands
  899. }
  900. static void ThrowBundle( int /* nTrigger */, PLAYER *pPlayer )
  901. {
  902. pPlayer->throwTime = ClipHigh(pPlayer->throwTime, kMaxThrowTime);
  903. int velocity = muldiv(pPlayer->throwTime, kMaxThrowVel - kMinThrowVel, kMaxThrowTime) + kMinThrowVel;
  904. int nThing = playerFireThing(pPlayer, kSlopeThrow, kThingTNTBundle, velocity);
  905. XSPRITE *pXSprite = &xsprite[sprite[nThing].extra];
  906. if ( pPlayer->fuseTime < 0 )
  907. pXSprite->triggerProximity = 1;
  908. else
  909. evPost(nThing, SS_SPRITE, pPlayer->fuseTime);
  910. UseAmmo(pPlayer, kAmmoTNTStick, 7);
  911. }
  912. static void DropBundle( int /* nTrigger */, PLAYER *pPlayer )
  913. {
  914. int nThing = playerFireThing(pPlayer, 0, kThingTNTBundle, 0);
  915. evPost(nThing, SS_SPRITE, pPlayer->fuseTime);
  916. UseAmmo(pPlayer, kAmmoTNTStick, 7);
  917. }
  918. static void ExplodeBundle( int /* nTrigger */, PLAYER *pPlayer )
  919. {
  920. int nThing = playerFireThing(pPlayer, 0, kThingTNTBundle, 0);
  921. evPost(nThing, SS_SPRITE, 0); // trigger it immediately
  922. UseAmmo(pPlayer, kAmmoTNTStick, 7);
  923. StartQAV(pPlayer, kQAVTNTExplode);
  924. pPlayer->weapon = 0; // drop the hands
  925. }
  926. static void ThrowProx( int /* nTrigger */, PLAYER *pPlayer )
  927. {
  928. pPlayer->throwTime = ClipHigh(pPlayer->throwTime, kMaxThrowTime);
  929. int velocity = muldiv(pPlayer->throwTime, kMaxThrowVel - kMinThrowVel, kMaxThrowTime) + kMinThrowVel;
  930. int nThing = playerFireThing(pPlayer, kSlopeThrow, kThingTNTBundle, velocity);
  931. XSPRITE *pXSprite = &xsprite[sprite[nThing].extra];
  932. pXSprite->triggerProximity = 1;
  933. UseAmmo(pPlayer, kAmmoTNTProximity, 1);
  934. }
  935. static void DropProx( int /* nTrigger */, PLAYER *pPlayer )
  936. {
  937. int nThing = playerFireThing(pPlayer, 0, kThingTNTProxArmed, 0);
  938. XSPRITE *pXSprite = &xsprite[sprite[nThing].extra];
  939. evPost(nThing, SS_SPRITE, 2 * kTimerRate); // arm it after 2 seconds
  940. UseAmmo(pPlayer, kAmmoTNTProximity, 1);
  941. }
  942. static void ThrowRemote( int /* nTrigger */, PLAYER *pPlayer )
  943. {
  944. pPlayer->throwTime = ClipHigh(pPlayer->throwTime, kMaxThrowTime);
  945. int velocity = muldiv(pPlayer->throwTime, kMaxThrowVel - kMinThrowVel, kMaxThrowTime) + kMinThrowVel;
  946. int nThing = playerFireThing(pPlayer, kSlopeThrow, kThingTNTBundle, velocity);
  947. XSPRITE *pXSprite = &xsprite[sprite[nThing].extra];
  948. pXSprite->triggerProximity = 1;
  949. UseAmmo(pPlayer, kAmmoTNTRemote, 1);
  950. }
  951. static void DropRemote( int /* nTrigger */, PLAYER *pPlayer )
  952. {
  953. int nThing = playerFireThing(pPlayer, 0, kThingTNTRemArmed, 0);
  954. XSPRITE *pXSprite = &xsprite[sprite[nThing].extra];
  955. pXSprite->rxID = kChannelRemoteFire1 + pPlayer->sprite->type - kDudePlayer1;
  956. UseAmmo(pPlayer, kAmmoTNTRemote, 1);
  957. //sndStartSample( "tnt_prox", 64 );
  958. }
  959. static void FireRemote( int /* nTrigger */, PLAYER *pPlayer )
  960. {
  961. evSend(0, 0, kChannelRemoteFire1 + pPlayer->sprite->type - kDudePlayer1, kCommandOn);
  962. }
  963. static void FireShotgun( PLAYER *pPlayer, int nBarrels )
  964. {
  965. dassert(nBarrels > 0 && nBarrels <= kShotgunBarrels);
  966. int nVectors = nBarrels * kVectorsPerBarrel;
  967. SPRITE *pSprite = pPlayer->sprite;
  968. int z = pSprite->z - pPlayer->weaponAboveZ;
  969. for ( int i = 0; i < nVectors; i++ )
  970. {
  971. // dispersal modifiers
  972. int ddx = BiRandom2(2000);
  973. int ddy = BiRandom2(2000);
  974. int ddz = BiRandom2(2000);
  975. actFireVector(pPlayer->nSprite, z,
  976. pPlayer->aim.dx + ddx, pPlayer->aim.dy + ddy, pPlayer->aim.dz + ddz,
  977. kVectorShell);
  978. }
  979. if (nBarrels == 1)
  980. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxShotFire);
  981. else
  982. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxShotFire2);
  983. }
  984. static void FireTommy( int /* nTrigger */, PLAYER *pPlayer )
  985. {
  986. SPRITE *pSprite = pPlayer->sprite;
  987. int z = pSprite->z - pPlayer->weaponAboveZ;
  988. UseAmmo(pPlayer, pPlayer->weaponAmmo, 1);
  989. // dispersal modifiers
  990. int ddx = BiRandom(1000);
  991. int ddy = BiRandom(1000);
  992. int ddz = BiRandom(1000);
  993. actFireVector(pPlayer->nSprite, z,
  994. pPlayer->aim.dx + ddx, pPlayer->aim.dy + ddy, pPlayer->aim.dz + ddz,
  995. kVectorBullet);
  996. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxTomFire);
  997. }
  998. static void FireFlare( int /* nTrigger */, PLAYER *pPlayer )
  999. {
  1000. SPRITE *pSprite = pPlayer->sprite;
  1001. playerFireMissile(pPlayer, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz,
  1002. kMissileFlare);
  1003. UseAmmo(pPlayer, pPlayer->weaponAmmo, 1);
  1004. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxFlareFire);
  1005. }
  1006. // this is a hack to fire a starburst flare
  1007. static void FireFlare2( int /* nTrigger */, PLAYER *pPlayer )
  1008. {
  1009. SPRITE *pSprite = pPlayer->sprite;
  1010. playerFireMissile(pPlayer, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz,
  1011. kMissileStarburstFlare);
  1012. UseAmmo(pPlayer, pPlayer->weaponAmmo, 1);
  1013. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxFlareFire);
  1014. }
  1015. static void FireVoodoo( int nStabType, PLAYER *pPlayer )
  1016. {
  1017. SPRITE *pSprite = pPlayer->sprite;
  1018. SPRITE *pTarget = NULL;
  1019. int nSelfSprite = pPlayer->nSprite;
  1020. int z = pSprite->z - pPlayer->weaponAboveZ;
  1021. if ( nStabType == kVoodooStabSelf )
  1022. {
  1023. actDamageSprite(nSelfSprite, pPlayer->nSprite, kDamageStab, 2 << 4);
  1024. if (pPlayer == gMe)
  1025. viewSetMessage("Ouch!");
  1026. return;
  1027. }
  1028. dassert(pPlayer->aimSprite >= 0);
  1029. pTarget = &sprite[pPlayer->aimSprite];
  1030. switch( nStabType )
  1031. {
  1032. case kVoodooStabChest:
  1033. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxVoodooHit);
  1034. actSpawnEffect(pTarget->sectnum, pTarget->x, pTarget->y, pTarget->z,
  1035. ET_Squib1);
  1036. actDamageSprite(nSelfSprite, pPlayer->aimSprite, kDamageVoodoo, 10 << 4);
  1037. break;
  1038. case kVoodooStabShoulder:
  1039. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxVoodooHit2);
  1040. actSpawnEffect(pTarget->sectnum, pTarget->x, pTarget->y, pTarget->z,
  1041. ET_Squib1);
  1042. actDamageSprite(nSelfSprite, pPlayer->aimSprite, kDamageVoodoo, 20 << 4);
  1043. if ( pTarget->type >= kDudePlayer1 && pTarget->type <= kDudePlayer8 )
  1044. {
  1045. int nPlayerHit = pTarget->type - kDudePlayer1;
  1046. WeaponLower(&gPlayer[nPlayerHit], &gPlayerInput[nPlayerHit]);
  1047. }
  1048. break;
  1049. case kVoodooStabGroin:
  1050. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxPlayLaugh);
  1051. actSpawnEffect(pTarget->sectnum, pTarget->x, pTarget->y, pTarget->z,
  1052. ET_Squib1);
  1053. actDamageSprite(nSelfSprite, pPlayer->aimSprite, kDamageVoodoo, 50 << 4);
  1054. break;
  1055. case kVoodooStabEye:
  1056. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxVoodooHit4);
  1057. actSpawnEffect(pTarget->sectnum, pTarget->x, pTarget->y, pTarget->z,
  1058. ET_Squib1);
  1059. actDamageSprite(nSelfSprite, pPlayer->aimSprite, kDamageVoodoo, 25 << 4);
  1060. if ( pTarget->type >= kDudePlayer1 && pTarget->type <= kDudePlayer8 )
  1061. {
  1062. PLAYER *pPlayerHit = &gPlayer[pTarget->type - kDudePlayer1];
  1063. if (pPlayerHit == gView) // change to gMe later!
  1064. scrDacRelEffect(-96, -96, -96);
  1065. }
  1066. break;
  1067. }
  1068. }
  1069. static void FireSpear( int /* nTrigger */, PLAYER *pPlayer )
  1070. {
  1071. playerFireMissile(pPlayer, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz,
  1072. kMissileSpear);
  1073. UseAmmo(pPlayer, pPlayer->weaponAmmo, 1);
  1074. }
  1075. static void FireShadow( int /* nTrigger */, PLAYER *pPlayer )
  1076. {
  1077. playerFireMissile(pPlayer, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz,
  1078. kMissileEctoSkull);
  1079. if ( !gInfiniteAmmo )
  1080. actDamageSprite(pPlayer->nSprite, pPlayer->nSprite, kDamageSpirit, 10 << 4);
  1081. }
  1082. static void FireReanimator( int /* nTrigger */, PLAYER *pPlayer )
  1083. {
  1084. SPRITE *pSprite = pPlayer->sprite;
  1085. int z = pSprite->z - pPlayer->weaponAboveZ;
  1086. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxVoodooChant);
  1087. for ( int i = 0; i < 4; i++ )
  1088. {
  1089. // dispersal modifiers
  1090. int ddx = BiRandom(2000);
  1091. int ddy = BiRandom(2000);
  1092. int ddz = BiRandom(2000);
  1093. HITINFO hitInfo;
  1094. int hitCode = HitScan( pPlayer->sprite, z,
  1095. pPlayer->aim.dx + ddx, pPlayer->aim.dy + ddy, pPlayer->aim.dz + ddz, &hitInfo );
  1096. // ADD: limit distance of reanimator voodoo
  1097. switch ( hitCode )
  1098. {
  1099. case SS_SPRITE:
  1100. {
  1101. SPRITE *pSprite = &sprite[hitInfo.hitsprite];
  1102. if (pSprite->type == kDudeAxeZombie && pSprite->owner == -1)
  1103. {
  1104. //dprintf("calling playerAddLackey\n");
  1105. if (playerAddLackey(pPlayer, hitInfo.hitsprite))
  1106. aiSetTarget( &xsprite[pSprite->extra], pPlayer->sprite->x, pPlayer->sprite->y, pPlayer->sprite->z );
  1107. }
  1108. break;
  1109. }
  1110. }
  1111. }
  1112. }
  1113. uchar WeaponFindLoaded( PLAYER *pPlayer )
  1114. {
  1115. dprintf("WeaponFindLoaded\n");
  1116. // see if it just needs to switch to a different type of ammo
  1117. switch ( pPlayer->weapon )
  1118. {
  1119. case kWeaponTNT:
  1120. if ( pPlayer->ammoCount[kAmmoTNTStick] || pPlayer->ammoCount[kAmmoTNTProximity] ||
  1121. pPlayer->ammoCount[kAmmoTNTRemote] )
  1122. return kWeaponTNT;
  1123. break;
  1124. case kWeaponTommy:
  1125. if ( pPlayer->ammoCount[kAmmoBullet] || pPlayer->ammoCount[kAmmoBulletAP] )
  1126. return kWeaponTommy;
  1127. break;
  1128. case kWeaponFlare:
  1129. if ( pPlayer->ammoCount[kAmmoFlare] || pPlayer->ammoCount[kAmmoFlareSB] )
  1130. return kWeaponFlare;
  1131. break;
  1132. case kWeaponSpear:
  1133. if ( pPlayer->ammoCount[kAmmoSpear] || pPlayer->ammoCount[kAmmoSpearXP] )
  1134. return kWeaponSpear;
  1135. break;
  1136. }
  1137. // switch to a new weapon based on available ammo
  1138. if ( pPlayer->hasWeapon[ kWeaponShadow ] && powerupCheck(pPlayer, kItemInvulnerability - kItemBase) )
  1139. return kWeaponShadow;
  1140. else if ( pPlayer->hasWeapon[kWeaponTommy] && CheckAmmo(pPlayer, kAmmoBullet) )
  1141. return kWeaponTommy;
  1142. else if ( pPlayer->hasWeapon[kWeaponTommy] && CheckAmmo(pPlayer, kAmmoBulletAP) )
  1143. return kWeaponTommy;
  1144. else if ( pPlayer->hasWeapon[kWeaponShotgun] && CheckAmmo( pPlayer, kAmmoShell) )
  1145. return kWeaponShotgun;
  1146. else if ( pPlayer->hasWeapon[kWeaponFlare] && CheckAmmo(pPlayer, kAmmoFlareSB) )
  1147. return kWeaponFlare;
  1148. else if ( pPlayer->hasWeapon[kWeaponFlare] && CheckAmmo(pPlayer, kAmmoFlare) )
  1149. return kWeaponFlare;
  1150. else if ( pPlayer->hasWeapon[kWeaponSpear] && CheckAmmo(pPlayer, kAmmoSpearXP) )
  1151. return kWeaponSpear;
  1152. else if ( pPlayer->hasWeapon[kWeaponSpear] && CheckAmmo(pPlayer, kAmmoSpear) )
  1153. return kWeaponSpear;
  1154. else if ( pPlayer->hasWeapon[kWeaponSprayCan] && CheckAmmo(pPlayer, kAmmoSprayCan) )
  1155. return kWeaponSprayCan;
  1156. else if ( pPlayer->hasWeapon[kWeaponTNT] && CheckAmmo(pPlayer, kAmmoTNTStick) )
  1157. return kWeaponTNT;
  1158. else if ( pPlayer->hasWeapon[kWeaponTNT] && CheckAmmo(pPlayer, kAmmoTNTProximity) )
  1159. return kWeaponTNT;
  1160. else if ( pPlayer->hasWeapon[kWeaponTNT] && CheckAmmo(pPlayer, kAmmoTNTRemote) )
  1161. return kWeaponTNT;
  1162. else if ( pPlayer->hasWeapon[kWeaponVoodoo] && CheckAmmo(pPlayer, kAmmoVoodoo) )
  1163. return kWeaponVoodoo;
  1164. else if ( pPlayer->hasWeapon[kWeaponShadow] && pPlayer->xsprite->health > 75 )
  1165. return kWeaponShadow;
  1166. return kWeaponPitchfork;
  1167. }
  1168. /*
  1169. ;[Weapon#]
  1170. ;Name = "WeaponNameMax24"
  1171. ;SelectKey = [ None | scancode ]
  1172. ;UseByDefault = [ TRUE | FALSE ]
  1173. ;HasByDefault = [ TRUE | FALSE ]
  1174. ;RequiresWeapon = [ None | 0..9 ]
  1175. ;
  1176. ;Type = [ NonWeapon | Melee | Thrown | Projectile | Vector ]
  1177. ;Type = NonWeapon
  1178. ;
  1179. ;Type = Melee
  1180. ;MaxDistance = [ Infinite | 0..max ]
  1181. ;
  1182. ;Type = Thrown
  1183. ;MaxDistance = [ Infinite | 0..max ]
  1184. ;
  1185. ;Type = Projectile
  1186. ;MaxDistance = [ Infinite | 0..max ]
  1187. ;
  1188. ;Type = Vector (uses hitscan)
  1189. ;MaxDistance = [ Infinite | 0..max ]
  1190. ;Richochet = [ TRUE | FALSE ]
  1191. ;UsesNightScope = [ TRUE | FALSE ]
  1192. ;
  1193. ;Shots = [ 0..max shots or projectiles ]
  1194. ;Dispersion = [ 0..100% ]
  1195. ;Accuracy = [ 0..100% ]
  1196. ;
  1197. ;AmmoStyle = [ Infinite, Rechargable, Expendable, Health ]
  1198. ;AmmoStyle = Infinite
  1199. ;
  1200. ;AmmoStyle = Rechargable
  1201. ;RechargeRate = [ 0 | ammo/second (?) ]
  1202. ;MaxAmmo = [ 0..max ]
  1203. ;
  1204. ;AmmoStyle = Expendable
  1205. ;MaxAmmo = [ 0..max ]
  1206. ;AmmoType = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
  1207. ;
  1208. ;AmmoStyle = Health
  1209. ;HealthPerShot = [ 0..usedpershot ]
  1210. ;
  1211. ;JamFrequency = [ 0..100% ]
  1212. ;JamSingleFire = [ TRUE | FALSE ]
  1213. ;JamRapidFire = [ TRUE | FALSE ]
  1214. ;
  1215. ;[Ammo#]
  1216. ;Name = "AmmoNameMax24"
  1217. ;Velocity = [ ? ]
  1218. ;DamageTypes = [ Explosion, Burn, Bullet, Stab, Pummel, Cleave, Ecto]
  1219. ;DamageRates = [ 0, 0, 0, 0, 0, 0, 0 ]
  1220. */
  1221. void WeaponProcess( PLAYER *pPlayer, INPUT *pInput )
  1222. {
  1223. WeaponPlay(pPlayer);
  1224. // decrement weapon ready timer
  1225. pPlayer->weaponTimer -= kFrameTicks;
  1226. if ( pPlayer->fLoopQAV )
  1227. {
  1228. if ( pInput->buttonFlags.shoot && pPlayer->ammoCount[pPlayer->weaponAmmo] )
  1229. {
  1230. while ( pPlayer->weaponTimer <= 0 )
  1231. pPlayer->weaponTimer += pPlayer->pWeaponQAV->duration;
  1232. UpdateAimVector(pPlayer);
  1233. return;
  1234. }
  1235. pPlayer->weaponTimer = 0;
  1236. pPlayer->fLoopQAV = FALSE;
  1237. }
  1238. else
  1239. pPlayer->weaponTimer = ClipLow(pPlayer->weaponTimer, 0);
  1240. // special processing for TNT
  1241. if ( pPlayer->weapon == kWeaponTNT )
  1242. {
  1243. switch ( pPlayer->weaponState )
  1244. {
  1245. case kTNTStickFuse1:
  1246. // player released alt fire key?
  1247. if ( !pInput->buttonFlags.shoot2 )
  1248. pPlayer->weaponState = kTNTStickFuse2;
  1249. return;
  1250. case kTNTStickFuse2:
  1251. // dropping?
  1252. if ( pInput->buttonFlags.shoot2 )
  1253. {
  1254. pPlayer->fuseTime = pPlayer->weaponTimer;
  1255. StartQAV(pPlayer, kQAVStickDrop, (QAVCALLBACK)DropStick);
  1256. pPlayer->weaponState = kBicIdle;
  1257. return;
  1258. }
  1259. // throwing?
  1260. if ( pInput->buttonFlags.shoot )
  1261. {
  1262. pPlayer->weaponState = kTNTStickThrow;
  1263. pPlayer->fuseTime = 0;
  1264. pPlayer->throwTime = gFrameClock;
  1265. }
  1266. return;
  1267. case kTNTStickThrow:
  1268. // releasing?
  1269. if ( !pInput->buttonFlags.shoot )
  1270. {
  1271. if ( pPlayer->fuseTime == 0 )
  1272. pPlayer->fuseTime = pPlayer->weaponTimer;
  1273. pPlayer->throwTime = gFrameClock - pPlayer->throwTime;
  1274. sfxCreate3DSound(pPlayer->sprite->x, pPlayer->sprite->y, pPlayer->sprite->z,
  1275. kSfxTNTToss);
  1276. StartQAV(pPlayer, kQAVStickThrow, (QAVCALLBACK)ThrowStick);
  1277. pPlayer->weaponState = kBicIdle;
  1278. }
  1279. return;
  1280. case kTNTBundleFuse1:
  1281. // player released alt fire key?
  1282. if ( !pInput->buttonFlags.shoot2 )
  1283. pPlayer->weaponState = kTNTBundleFuse2;
  1284. return;
  1285. case kTNTBundleFuse2:
  1286. // dropping?
  1287. if ( pInput->buttonFlags.shoot2 )
  1288. {
  1289. pPlayer->fuseTime = pPlayer->weaponTimer;
  1290. StartQAV(pPlayer, kQAVBundleDrop, (QAVCALLBACK)DropBundle);
  1291. pPlayer->weaponState = kBicIdle;
  1292. return;
  1293. }
  1294. // throwing?
  1295. if ( pInput->buttonFlags.shoot )
  1296. {
  1297. pPlayer->weaponState = kTNTBundleThrow;
  1298. pPlayer->fuseTime = 0;
  1299. pPlayer->throwTime = gFrameClock;
  1300. }
  1301. return;
  1302. case kTNTBundleThrow:
  1303. // releasing?
  1304. if ( !pInput->buttonFlags.shoot )
  1305. {
  1306. if ( pPlayer->fuseTime == 0 )
  1307. pPlayer->fuseTime = pPlayer->weaponTimer;
  1308. pPlayer->throwTime = gFrameClock - pPlayer->throwTime;
  1309. StartQAV(pPlayer, kQAVBundleThrow, (QAVCALLBACK)ThrowBundle);
  1310. pPlayer->weaponState = kBicIdle;
  1311. }
  1312. return;
  1313. case kTNTProxThrow:
  1314. // releasing?
  1315. if ( !pInput->buttonFlags.shoot )
  1316. {
  1317. pPlayer->throwTime = gFrameClock - pPlayer->throwTime;
  1318. StartQAV(pPlayer, kQAVBundleThrow, (QAVCALLBACK)ThrowProx);
  1319. pPlayer->weaponState = kTNTProxEmpty;
  1320. }
  1321. return;
  1322. case kTNTRemoteThrow:
  1323. // releasing?
  1324. if ( !pInput->buttonFlags.shoot )
  1325. {
  1326. pPlayer->throwTime = gFrameClock - pPlayer->throwTime;
  1327. StartQAV(pPlayer, kQAVBundleThrow, (QAVCALLBACK)ThrowRemote);
  1328. pPlayer->weaponState = kTNTRemoteEmpty;
  1329. }
  1330. return;
  1331. }
  1332. }
  1333. // return if weapon is busy
  1334. if (pPlayer->weaponTimer > 0)
  1335. return;
  1336. pPlayer->pWeaponQAV = NULL;
  1337. // pPlayer->weapon is set to kMaxWeapons in the fire processing below
  1338. if ( pPlayer->weaponState == kFindWeapon )
  1339. {
  1340. dprintf("Out of ammo: looking for a new weapon\n");
  1341. pPlayer->weaponState = 0;
  1342. pInput->newWeapon = WeaponFindLoaded( pPlayer );
  1343. }
  1344. // weapon select
  1345. if ( pInput->newWeapon )
  1346. {
  1347. if ( pPlayer->xsprite->health == 0 || !pPlayer->hasWeapon[ pInput->newWeapon ] )
  1348. {
  1349. pInput->newWeapon = 0;
  1350. return;
  1351. }
  1352. if (pPlayer->weapon != 0)
  1353. WeaponLower(pPlayer, pInput); // lower the old weapon
  1354. else
  1355. WeaponRaise(pPlayer, pInput); // raise new weapon
  1356. return;
  1357. }
  1358. if ( pPlayer->weapon == 0 )
  1359. return; // no weapon drawn, do nothing
  1360. UpdateAimVector(pPlayer);
  1361. // fire key
  1362. if ( pInput->buttonFlags.shoot )
  1363. {
  1364. if ( CheckAmmo(pPlayer, pPlayer->weaponAmmo) )
  1365. {
  1366. // firing weapon (primary)
  1367. switch ( pPlayer->weapon )
  1368. {
  1369. case kWeaponPitchfork:
  1370. StartQAV(pPlayer, kQAVForkStab, (QAVCALLBACK)FirePitchfork, FALSE);
  1371. return;
  1372. case kWeaponSprayCan:
  1373. if ( pPlayer->weaponState == kCanIdle )
  1374. {
  1375. StartQAV(pPlayer, kQAVSprayFire, (QAVCALLBACK)FireSpray, TRUE);
  1376. pPlayer->weaponState = kCanFire;
  1377. return;
  1378. }
  1379. break;
  1380. case kWeaponTNT:
  1381. switch ( pPlayer->weaponState )
  1382. {
  1383. case kTNTStickIdle:
  1384. StartQAV(pPlayer, kQAVStickFuse, (QAVCALLBACK)ExplodeStick);
  1385. pPlayer->weaponState = kTNTStickThrow;
  1386. pPlayer->throwTime = gFrameClock;
  1387. pPlayer->fuseTime = -1;
  1388. return;
  1389. case kTNTBundleIdle:
  1390. StartQAV(pPlayer, kQAVBundleFuse, (QAVCALLBACK)ExplodeBundle);
  1391. pPlayer->weaponState = kTNTBundleThrow;
  1392. pPlayer->throwTime = gFrameClock;
  1393. pPlayer->fuseTime = -1;
  1394. return;
  1395. case kTNTProxIdle:
  1396. pPlayer->weaponState = kTNTProxThrow;
  1397. pPlayer->throwTime = gFrameClock;
  1398. return;
  1399. case kTNTRemoteIdle1:
  1400. pPlayer->weaponState = kTNTRemoteThrow;
  1401. pPlayer->throwTime = gFrameClock;
  1402. return;
  1403. case kTNTRemoteIdle2:
  1404. StartQAV(pPlayer, kQAVRemoteFire, (QAVCALLBACK)FireRemote);
  1405. pPlayer->weaponState = kTNTRemoteEmpty;
  1406. return;
  1407. }
  1408. break;
  1409. case kWeaponShotgun:
  1410. switch ( pPlayer->weaponState )
  1411. {
  1412. case kShotIdle2:
  1413. StartQAV(pPlayer, kQAVShotFireL);
  1414. pPlayer->weaponState = kShotIdle1;
  1415. UseAmmo(pPlayer, kAmmoShell, 1);
  1416. FireShotgun(pPlayer, 1);
  1417. return;
  1418. case kShotIdle1:
  1419. StartQAV(pPlayer, kQAVShotFireR);
  1420. pPlayer->weaponState = kShotIdle0;
  1421. UseAmmo(pPlayer, kAmmoShell, 1);
  1422. FireShotgun(pPlayer, 1);
  1423. return;
  1424. }
  1425. break;
  1426. case kWeaponTommy:
  1427. StartQAV(pPlayer, kQAVTommyFire1, (QAVCALLBACK)FireTommy, TRUE);
  1428. return;
  1429. case kWeaponFlare:
  1430. StartQAV(pPlayer, kQAVFlareFire, (QAVCALLBACK)FireFlare);
  1431. return;
  1432. case kWeaponVoodoo:
  1433. {
  1434. int nStabType = Random(4);
  1435. if ( pPlayer->aimSprite == -1 )
  1436. nStabType = 4;
  1437. StartQAV(pPlayer, kQAVDollStab1 + nStabType, (QAVCALLBACK)FireVoodoo);
  1438. return;
  1439. }
  1440. case kWeaponSpear:
  1441. StartQAV(pPlayer, kQAVSpearFire, (QAVCALLBACK)FireSpear);
  1442. return;
  1443. case kWeaponShadow:
  1444. StartQAV(pPlayer, kQAVShadowFire, (QAVCALLBACK)FireShadow);
  1445. return;
  1446. case kWeaponBeast:
  1447. StartQAV(pPlayer, kQAVBeastAttack1 + Random(4));
  1448. pPlayer->weaponState = kBeastIdle;
  1449. return;
  1450. }
  1451. }
  1452. else
  1453. {
  1454. dprintf("Primary out of ammo: setting weapon state to kFindWeapon\n");
  1455. pPlayer->weaponState = kFindWeapon;
  1456. return;
  1457. }
  1458. }
  1459. // alternate fire key
  1460. if ( pInput->buttonFlags.shoot2 )
  1461. {
  1462. if ( CheckAmmo(pPlayer, pPlayer->weaponAmmo) )
  1463. {
  1464. // firing weapon (alternate)
  1465. switch ( pPlayer->weapon )
  1466. {
  1467. case kWeaponPitchfork:
  1468. playerFireMissile(pPlayer,
  1469. pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz,
  1470. kMissileFireball);
  1471. pPlayer->weaponTimer = 20;
  1472. return;
  1473. case kWeaponSprayCan:
  1474. if ( pPlayer->weaponState == kCanIdle )
  1475. {
  1476. StartQAV(pPlayer, kQAVSprayFire, (QAVCALLBACK)FireSpray, TRUE);
  1477. pPlayer->weaponState = kCanFire;
  1478. return;
  1479. }
  1480. break;
  1481. case kWeaponTNT:
  1482. switch ( pPlayer->weaponState )
  1483. {
  1484. case kTNTStickIdle:
  1485. StartQAV(pPlayer, kQAVStickFuse, (QAVCALLBACK)ExplodeStick);
  1486. pPlayer->weaponState = kTNTStickFuse1;
  1487. return;
  1488. case kTNTBundleIdle:
  1489. StartQAV(pPlayer, kQAVBundleFuse, (QAVCALLBACK)ExplodeBundle);
  1490. pPlayer->weaponState = kTNTBundleFuse1;
  1491. return;
  1492. case kTNTProxIdle:
  1493. StartQAV(pPlayer, kQAVProxDrop, (QAVCALLBACK)DropProx);
  1494. pPlayer->weaponState = kTNTProxEmpty;
  1495. return;
  1496. case kTNTRemoteIdle1:
  1497. StartQAV(pPlayer, kQAVRemoteDrop, (QAVCALLBACK)DropRemote);
  1498. pPlayer->weaponState = kTNTRemoteIdle2;
  1499. return;
  1500. case kTNTRemoteIdle2:
  1501. // raise another bundle
  1502. StartQAV(pPlayer, kQAVRemoteUp1);
  1503. pPlayer->weaponState = kTNTRemoteIdle1;
  1504. return;
  1505. }
  1506. break;
  1507. case kWeaponShotgun:
  1508. switch ( pPlayer->weaponState )
  1509. {
  1510. case kShotIdle2:
  1511. StartQAV(pPlayer, kQAVShotFireR);
  1512. pPlayer->weaponState = kShotIdle0;
  1513. UseAmmo(pPlayer, kAmmoShell, 2);
  1514. FireShotgun(pPlayer, 2);
  1515. return;
  1516. case kShotIdle1:
  1517. StartQAV(pPlayer, kQAVShotFireR);
  1518. pPlayer->weaponState = kShotIdle0;
  1519. UseAmmo(pPlayer, kAmmoShell, 1);
  1520. FireShotgun(pPlayer, 1);
  1521. return;
  1522. }
  1523. break;
  1524. case kWeaponTommy:
  1525. StartQAV(pPlayer, kQAVTommyFire1, (QAVCALLBACK)FireTommy, TRUE);
  1526. return;
  1527. case kWeaponFlare:
  1528. StartQAV(pPlayer, kQAVFlareFire, (QAVCALLBACK)FireFlare2);
  1529. return;
  1530. case kWeaponVoodoo:
  1531. StartQAV(pPlayer, kQAVDollSpell, (QAVCALLBACK)FireReanimator, FALSE);
  1532. return;
  1533. case kWeaponSpear:
  1534. StartQAV(pPlayer, kQAVSpearFire, (QAVCALLBACK)FireSpear);
  1535. return;
  1536. case kWeaponShadow:
  1537. StartQAV(pPlayer, kQAVShadowFire, (QAVCALLBACK)FireShadow);
  1538. return;
  1539. }
  1540. }
  1541. else
  1542. {
  1543. dprintf("Alternate out of ammo: setting weapon state to kFindWeapon\n");
  1544. pPlayer->weaponState = kFindWeapon;
  1545. return;
  1546. }
  1547. }
  1548. WeaponUpdateState(pPlayer);
  1549. }