PLAYER.CPP 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "actor.h"
  5. #include "ai.h"
  6. #include "db.h"
  7. #include "debug4g.h"
  8. #include "dude.h"
  9. #include "engine.h"
  10. #include "error.h"
  11. #include "eventq.h"
  12. #include "gameutil.h"
  13. #include "globals.h"
  14. #include "misc.h"
  15. #include "multi.h"
  16. #include "names.h"
  17. #include "options.h"
  18. #include "player.h"
  19. #include "screen.h"
  20. #include "sectorfx.h"
  21. #include "seq.h"
  22. #include "tile.h"
  23. #include "trig.h"
  24. #include "triggers.h"
  25. #include "view.h"
  26. #include "warp.h"
  27. #include "weapon.h"
  28. #include "aizomba.h" // currently required for lackeys
  29. #include "sfx.h"
  30. #include "sound.h" // can be removed once sfx complete
  31. #define kLookMax 60
  32. #define kHorizUpMax 120
  33. #define kHorizDownMax 180
  34. // this should probably go into the posture table too
  35. #define kClimbSpeed 160
  36. #define kPowerUpTime (kTimerRate * 30)
  37. #define kMaxPowerUpTime ((kTimerRate * 60) * 60)
  38. PLAYER gPlayer[kMaxPlayers];
  39. PLAYER *gMe = NULL;
  40. PLAYER *gView = NULL;
  41. INPUT gPlayerInput[kMaxPlayers];
  42. /*******************************************************************************
  43. Notes on the posture table:
  44. Acceleration units are units per clock tick. If the timer rate is changed,
  45. these values will need to change as well.
  46. *******************************************************************************/
  47. POSTURE gPosture[] =
  48. {
  49. // player posture
  50. {
  51. 10, // frontAccel 25,
  52. 5, // sideAccel 30,
  53. 5, // backAccel 20,
  54. 350, // frontSpeed[0] 350,
  55. 800, // frontSpeed[1] 700,
  56. 300, // sideSpeed[0] 300,
  57. 500, // sideSpeed[1] 500,
  58. 250, // backSpeed[0] 250,
  59. 500, // backSpeed[1] 500,
  60. 100, // pace[0]
  61. 140, // pace[1]
  62. 3, // bobV
  63. 2, // bobH
  64. 4, // swayV
  65. 10, // swayH
  66. },
  67. // beast posture ******** THESE ALL NEED TO LOOK LIKE ABOVE (TO DO!) **********
  68. {
  69. 20, // frontAccel 20,
  70. 40, // sideAccel 40,
  71. 24, // backAccel 24,
  72. 500, // frontSpeed[0] 500,
  73. 1000, // frontSpeed[1] 1000,
  74. 400, // sideSpeed[0] 400,
  75. 800, // sideSpeed[1] 800,
  76. 300, // backSpeed[0] 300,
  77. 600, // backSpeed[1] 600,
  78. 100, // pace[0]
  79. 80, // pace[1]
  80. 12, // bobV
  81. 4, // bobH
  82. 8, // swayV
  83. 16, // swayH
  84. },
  85. };
  86. AMMOINFO gAmmoInfo[kAmmoMax] =
  87. {
  88. // max, vectorType
  89. { kTimerRate*40, kVectorNone }, // kAmmoSprayCan
  90. { 24, kVectorNone }, // kAmmoTNTStick
  91. { 8, kVectorNone }, // kAmmoTNTProximity
  92. { 8, kVectorNone }, // kAmmoTNTRemote
  93. { 50, kVectorShell }, // kAmmoShell
  94. { 500, kVectorBullet }, // kAmmoBullet
  95. { 500, kVectorBulletAP }, // kAmmoBulletAP
  96. { 24, kVectorNone }, // kAmmoFlare
  97. { 24, kVectorNone }, // kAmmoFlareSB
  98. { 10, kVectorNone }, // kAmmoVoodoo
  99. { 24, kVectorNone }, // kAmmoSpear
  100. { 24, kVectorNone }, // kAmmoSpearXP
  101. };
  102. #if 0
  103. enum POWERUP {
  104. kPupFeatherFall = 0,
  105. kPupJumpBoots,
  106. kPupInvisible,
  107. kPupInvulnerable,
  108. kPupJumpBoots,
  109. kPupRavenFlight,
  110. kPupGunsAkimbo,
  111. kPupDivingSuit,
  112. kPupGasMask,
  113. kPupClone,
  114. kPupCrystalBall,
  115. kPupDecoy,
  116. kPupDoppleganger,
  117. kPupReflectiveShots,
  118. kPupRoseGlasses,
  119. kPupShadowCloak,
  120. kPupShroomRage,
  121. kPupShroomDelirium,
  122. kPupShroomGrow,
  123. kPupShroomShrink,
  124. kPupDeathMask,
  125. kPupAsbestosArmor,
  126. kMaxPowerUps
  127. };
  128. enum POWERUPFLAGS {
  129. kPowerPermanent = 0x0001,
  130. kPowerUnique = 0x0002,
  131. };
  132. #endif
  133. struct POWERUPINFO {
  134. short picnum;
  135. long zoom;
  136. BOOL isUnique;
  137. int addPower;
  138. int maxPower;
  139. };
  140. POWERUPINFO gPowerUpInfo[ kMaxPowerUps ] =
  141. {
  142. {-1, 0, TRUE, 1, 1}, // kItemKey1
  143. {-1, 0, TRUE, 1, 1}, // kItemKey2
  144. {-1, 0, TRUE, 1, 1}, // kItemKey3
  145. {-1, 0, TRUE, 1, 1}, // kItemKey4
  146. {-1, 0, TRUE, 1, 1}, // kItemKey5
  147. {-1, 0, TRUE, 1, 1}, // kItemKey6
  148. {-1, 0, TRUE, 1, 1}, // kItemKey7
  149. {-1, 0, FALSE, 10, 100}, // kItemDoctorBag INVENTORY
  150. {-1, 0, FALSE, 5, 100}, // kItemMedPouch
  151. {-1, 0, FALSE, 20, 100}, // kItemLifeEssence
  152. {-1, 0, FALSE, 100, 200}, // kItemLifeSeed
  153. {-1, 0, FALSE, 2, 200}, // kItemPotion1
  154. {kAnmFeather, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemFeatherFall INVENTORY
  155. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemLtdInvisibility
  156. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemInvulnerability
  157. {kPicJumpBoots, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemJumpBoots INVENTORY
  158. {kPicRavenFlight, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemRavenFlight INVENTORY
  159. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemGunsAkimbo
  160. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemDivingSuit INVENTORY
  161. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemGasMask INVENTORY or CUT
  162. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemClone
  163. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemCrystalBall INVENTORY
  164. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemDecoy INVENTORY
  165. {kAnmDoppleganger, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemDoppleganger
  166. {kAnmReflectShots, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemReflectiveShots
  167. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemRoseGlasses INVENTORY
  168. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemShadowCloak
  169. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemShroomRage
  170. {-1, 0, FALSE, kPowerUpTime/4, kMaxPowerUpTime}, // kItemShroomDelirium
  171. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemShroomGrow
  172. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemShroomShrink
  173. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemDeathMask INVENTORY
  174. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemWineGoblet
  175. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemWineBottle
  176. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemSkullGrail
  177. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemSilverGrail
  178. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemTome
  179. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemBlackChest
  180. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemWoodenChest
  181. {-1, 0, FALSE, kPowerUpTime, kMaxPowerUpTime}, // kItemAsbestosArmor INVENTORY
  182. };
  183. int powerupCheck( PLAYER *pPlayer, int nPowerUp )
  184. {
  185. dassert( pPlayer != NULL );
  186. dassert( nPowerUp >= 0 && nPowerUp < kMaxPowerUps );
  187. return pPlayer->powerUpTimer[nPowerUp];
  188. }
  189. void powerupDraw( PLAYER *pView )
  190. {
  191. for (int nPowerUp = kItemMax - kItemBase - 1; nPowerUp >= 0; nPowerUp--)
  192. {
  193. int nPowerRemaining = powerupCheck( pView, nPowerUp );
  194. if ( nPowerRemaining )
  195. {
  196. POWERUPINFO *pInfo = &gPowerUpInfo[ nPowerUp ];
  197. switch( nPowerUp + kItemBase ) // switch off of actual type
  198. {
  199. case kItemFeatherFall:
  200. case kItemLtdInvisibility:
  201. case kItemInvulnerability:
  202. case kItemJumpBoots:
  203. case kItemRavenFlight:
  204. case kItemGunsAkimbo:
  205. case kItemDivingSuit:
  206. case kItemGasMask:
  207. case kItemClone:
  208. case kItemCrystalBall:
  209. case kItemDecoy:
  210. case kItemDoppleganger:
  211. case kItemReflectiveShots:
  212. case kItemRoseGlasses:
  213. case kItemShadowCloak:
  214. case kItemShroomRage:
  215. case kItemShroomDelirium:
  216. case kItemShroomGrow:
  217. case kItemShroomShrink:
  218. case kItemDeathMask:
  219. case kItemWineGoblet:
  220. case kItemWineBottle:
  221. case kItemSkullGrail:
  222. case kItemSilverGrail:
  223. case kItemTome:
  224. case kItemBlackChest:
  225. case kItemWoodenChest:
  226. case kItemAsbestosArmor:
  227. {
  228. int nFlags = kRotateNormal;
  229. if ( nPowerRemaining < (kTimerRate * 8) && ( gGameClock & 32 ) )
  230. nFlags |= kRotateTranslucent;
  231. short nTile = pInfo->picnum;
  232. if (nTile >= 0)
  233. {
  234. nTile += animateoffs(nTile, 0);
  235. rotatesprite(xdim<<15, ydim<<15, pInfo->zoom, 0, nTile, -128, kPLUNormal,
  236. (char)nFlags, gViewX0, gViewY0, gViewX1, gViewY1);
  237. }
  238. }
  239. break;
  240. default:
  241. break;
  242. }
  243. }
  244. }
  245. }
  246. BOOL powerupActivate( PLAYER *pPlayer, int nPowerUp )
  247. {
  248. // char buffer[80];
  249. // skip the power-up if it is unique and already activated
  250. if ( powerupCheck( pPlayer, nPowerUp ) > 0 && gPowerUpInfo[nPowerUp].isUnique )
  251. return FALSE;
  252. pPlayer->powerUpTimer[nPowerUp] = ClipHigh( pPlayer->powerUpTimer[nPowerUp] +
  253. gPowerUpInfo[nPowerUp].addPower, gPowerUpInfo[nPowerUp].maxPower );
  254. DUDEINFO *pDudeInfo = &dudeInfo[pPlayer->sprite->type - kDudeBase];
  255. switch( nPowerUp + kItemBase ) // switch off of actual type
  256. {
  257. case kItemFeatherFall:
  258. case kItemJumpBoots:
  259. pDudeInfo->damageShift[ kDamageFall ] += kNoDamage;
  260. break;
  261. case kItemInvulnerability:
  262. {
  263. for ( int i = 0; i < kDamageMax; i++ )
  264. pDudeInfo->damageShift[ i ] += kNoDamage;
  265. break;
  266. }
  267. case kItemDivingSuit:
  268. pDudeInfo->damageShift[ kDamageDrown ] += kNoDamage;
  269. break;
  270. case kItemGasMask:
  271. pDudeInfo->damageShift[ kDamageGas ] += kNoDamage;
  272. break;
  273. case kItemAsbestosArmor:
  274. pDudeInfo->damageShift[ kDamageBurn ] += kNoDamage;
  275. break;
  276. default:
  277. break;
  278. }
  279. SPRITE *pSprite = pPlayer->sprite;
  280. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxPlayPowerUp);
  281. // sprintf( buffer, "Activating %s for %i",
  282. // gItemText[ nPowerUp ], pPlayer->powerUpTimer[nPowerUp] );
  283. // viewSetMessage(buffer);
  284. return TRUE;
  285. }
  286. void powerupDeactivate( PLAYER *pPlayer, int nPowerUp )
  287. {
  288. DUDEINFO *pDudeInfo = &dudeInfo[pPlayer->sprite->type - kDudeBase];
  289. switch( nPowerUp + kItemBase ) // switch off of actual type
  290. {
  291. case kItemFeatherFall:
  292. case kItemJumpBoots:
  293. pDudeInfo->damageShift[ kDamageFall ] -= kNoDamage;
  294. break;
  295. case kItemInvulnerability:
  296. {
  297. for ( int i = 0; i < kDamageMax; i++ )
  298. pDudeInfo->damageShift[ i ] -= kNoDamage;
  299. break;
  300. }
  301. case kItemDivingSuit:
  302. pDudeInfo->damageShift[ kDamageDrown ] -= kNoDamage;
  303. break;
  304. case kItemGasMask:
  305. pDudeInfo->damageShift[ kDamageGas ] -= kNoDamage;
  306. break;
  307. case kItemAsbestosArmor:
  308. pDudeInfo->damageShift[ kDamageBurn ] -= kNoDamage;
  309. break;
  310. default:
  311. break;
  312. }
  313. pPlayer->powerUpTimer[ nPowerUp ] = 0;
  314. }
  315. void powerupProcess( PLAYER *pPlayer )
  316. {
  317. for (int nPowerUp = kItemMax - kItemBase - 1; nPowerUp >= 0; nPowerUp--)
  318. {
  319. if ( pPlayer->powerUpTimer[nPowerUp] )
  320. {
  321. pPlayer->powerUpTimer[nPowerUp] = ClipLow(pPlayer->powerUpTimer[nPowerUp] - kFrameTicks, 0);
  322. if ( !powerupCheck( pPlayer, nPowerUp ) )
  323. powerupDeactivate( pPlayer, nPowerUp );
  324. }
  325. }
  326. }
  327. void powerupClear( PLAYER *pPlayer )
  328. {
  329. for (int nPowerUp = kItemMax - kItemBase - 1; nPowerUp >= 0; nPowerUp--)
  330. {
  331. pPlayer->powerUpTimer[nPowerUp] = 0;
  332. }
  333. }
  334. void powerupInit( void )
  335. {
  336. for (int nPowerUp = kItemMax - kItemBase - 1; nPowerUp >= 0; nPowerUp--)
  337. {
  338. POWERUPINFO *pInfo = &gPowerUpInfo[ nPowerUp ];
  339. dassert( pInfo->picnum < kMaxTiles );
  340. if ( pInfo->picnum >= 0 )
  341. {
  342. int maxSize = 0;
  343. PICANM *pAnm = &picanm[ pInfo->picnum ];
  344. int nFrame = (pAnm->type != 0) ? pAnm->frames : 0;
  345. for (; nFrame >= 0; nFrame-- )
  346. {
  347. if (pAnm->type == 3) // special case for backward anims
  348. {
  349. maxSize = tilesizx[ pInfo->picnum - nFrame ];
  350. if ( maxSize < tilesizy[ pInfo->picnum - nFrame ] )
  351. maxSize = tilesizy[ pInfo->picnum - nFrame ];
  352. }
  353. else
  354. {
  355. maxSize = tilesizx[ pInfo->picnum + nFrame ];
  356. if ( maxSize < tilesizy[ pInfo->picnum + nFrame ] )
  357. maxSize = tilesizy[ pInfo->picnum + nFrame ];
  358. }
  359. }
  360. dassert( maxSize > 0 );
  361. pInfo->zoom = ( 24 /*kPowerUpFrameSize*/ << 16 ) / maxSize;
  362. }
  363. }
  364. }
  365. void playerSetRace( PLAYER *pPlayer, int nLifeMode, int nType )
  366. {
  367. dassert( nLifeMode >= kModeHuman && nLifeMode <= kModeBeast );
  368. int dudeIndex = nType - kDudeBase;
  369. pPlayer->lifemode = nLifeMode;
  370. dudeInfo[dudeIndex] = gPlayerTemplate[ nLifeMode ];
  371. }
  372. void playerSetGodMode( PLAYER *pPlayer, BOOL nMode )
  373. {
  374. DUDEINFO *pDudeInfo = &dudeInfo[pPlayer->sprite->type - kDudeBase];
  375. if ( nMode )
  376. {
  377. for ( int i = 0; i < kDamageMax; i++ )
  378. pDudeInfo->damageShift[i] += kNoDamage;
  379. }
  380. else
  381. {
  382. for ( int i = 0; i < kDamageMax; i++ )
  383. pDudeInfo->damageShift[i] -= kNoDamage;
  384. }
  385. pPlayer->godMode = nMode;
  386. pPlayer->xsprite->health = pDudeInfo->startHealth << 4;
  387. }
  388. void playerReset( PLAYER *pPlayer, INPUT *pInput, int type )
  389. {
  390. dprintf("Resetting player %d\n", type - kDudePlayer1);
  391. // get the normal player starting position, else if in bloodbath mode,
  392. // randomly pick one of kMaxPlayers starting positions
  393. ZONE *pZone;
  394. if (gNetMode == kNetModeOff || gNetMode == kNetModeCoop)
  395. pZone = &gStartZone[ type - kDudePlayer1 ];
  396. else
  397. pZone = &gStartZone[ Random(numplayers)];
  398. if ( pPlayer->sprite != NULL )
  399. {
  400. // ADD: make the dead body a non-player type
  401. }
  402. int nSprite = actSpawnSprite( pZone->sector, pZone->x, pZone->y, pZone->z, kStatDude, TRUE );
  403. SPRITE *pSprite = &sprite[nSprite];
  404. dassert(pSprite->extra > 0 && pSprite->extra < kMaxXSprites);
  405. XSPRITE *pXSprite = &xsprite[pSprite->extra];
  406. int dudeIndex = type - kDudeBase;
  407. playerSetRace( pPlayer, kModeHuman, type );
  408. seqSpawn(dudeInfo[dudeIndex].seqStartID + kSeqDudeIdle, SS_SPRITE, pSprite->extra);
  409. // make the player's own sprite visible
  410. if ( pPlayer == gMe )
  411. SetBitString(show2dsprite, nSprite);
  412. // raise the player up off the floor
  413. int zTop, zBot;
  414. GetSpriteExtents(pSprite, &zTop, &zBot);
  415. pSprite->z -= zBot - pSprite->z;
  416. pPlayer->sprite = pSprite;
  417. pPlayer->nSprite = nSprite;
  418. pPlayer->xsprite = pXSprite;
  419. pSprite->ang = pZone->angle;
  420. pSprite->type = (short)type;
  421. pSprite->clipdist = dudeInfo[dudeIndex].clipdist;
  422. pSprite->flags = kAttrMove | kAttrGravity | kAttrFalling;
  423. pXSprite->health = dudeInfo[dudeIndex].startHealth << 4;
  424. pXSprite->moveState = kMoveWalk;
  425. pXSprite->burnTime = 0;
  426. pXSprite->burnSource = -1;
  427. pPlayer->eyeAboveZ = dudeInfo[dudeIndex].eyeHeight * pSprite->yrepeat << 2;
  428. pPlayer->weaponAboveZ = pPlayer->eyeAboveZ / 2;
  429. pPlayer->bloodlust = 0;
  430. pPlayer->impactPE = 0;
  431. pPlayer->impactPhase = 0;
  432. pPlayer->standSpeed = 0;
  433. pPlayer->compression = 0;
  434. pPlayer->viewOffZ = 0;
  435. pPlayer->weapOffZ = 0;
  436. pPlayer->viewOffdZ = 0;
  437. pPlayer->weapOffdZ = 0;
  438. pPlayer->horiz = 0;
  439. pPlayer->look = 0;
  440. pPlayer->slope = 0;
  441. pPlayer->fraggerID = -1;
  442. pPlayer->airTime = 0;
  443. pPlayer->bloodTime = 0;
  444. pPlayer->gooTime = 0;
  445. pPlayer->wetTime = 0;
  446. pPlayer->godMode = FALSE;
  447. pPlayer->relAim.dx = 1 << 14;
  448. pPlayer->relAim.dy = 0;
  449. pPlayer->relAim.dz = 0;
  450. pPlayer->aimSprite = -1;
  451. for (int i = 0; i < 8; i++)
  452. pPlayer->hasKey[i] = 0;
  453. pPlayer->weapon = kWeaponNone;
  454. pPlayer->deathTime = 0;
  455. pSprite->xvel = 0;
  456. pSprite->yvel = 0;
  457. pSprite->zvel = 0;
  458. pInput->forward = 0;
  459. pInput->strafe = 0;
  460. pInput->turn = 0;
  461. pInput->syncFlags.byte = 0;
  462. pInput->buttonFlags.byte = 0;
  463. pInput->keyFlags.byte = 0;
  464. pInput->newWeapon = kWeaponPitchfork;
  465. scrDacAbsEffect(0, 0, 0);
  466. for (i = 0; i < kWeaponMax; i++)
  467. {
  468. pPlayer->hasWeapon[i] = gInfiniteAmmo;
  469. pPlayer->weaponMode[i] = 0;
  470. }
  471. pPlayer->hasWeapon[kWeaponPitchfork] = TRUE;
  472. for (i = 0; i < kAmmoMax; i++)
  473. {
  474. pPlayer->ammoCount[i] = gInfiniteAmmo ? gAmmoInfo[i].max : 0;
  475. }
  476. pPlayer->weaponTimer = 0; // idle
  477. pPlayer->weaponState = 0;
  478. pPlayer->pWeaponQAV = NULL;
  479. for (i = 0; i < kMaxPowerUps; i++)
  480. pPlayer->powerUpTimer[i] = 0;
  481. for (i = 0; i < kMaxLackeys; i++)
  482. pPlayer->nLackeySprites[i] = -1;
  483. }
  484. void playerInit( int nPlayer )
  485. {
  486. PLAYER *pPlayer = &gPlayer[nPlayer];
  487. dprintf("Initializing player %d\n", nPlayer);
  488. pPlayer->sprite = NULL;
  489. pPlayer->teamID = nPlayer;
  490. pPlayer->fragCount = 0;
  491. memset(pPlayer->fragInfo, 0, sizeof(pPlayer->fragInfo));
  492. playerReset(pPlayer, &gPlayerInput[nPlayer], kDudePlayer1 + nPlayer);
  493. }
  494. static int CheckTouchSprite( SPRITE *pSprite )
  495. {
  496. int i, next;
  497. int dx, dy, dz;
  498. for (i = headspritestat[kStatItem]; i >= 0; i = next)
  499. {
  500. next = nextspritestat[i];
  501. dx = qabs(pSprite->x - sprite[i].x) >> 4;
  502. if (dx < kTouchXYDist)
  503. {
  504. dy = qabs(pSprite->y - sprite[i].y) >> 4;
  505. if (dy < kTouchXYDist)
  506. {
  507. int zTop, zBot;
  508. GetSpriteExtents(pSprite, &zTop, &zBot);
  509. dz = 0;
  510. if ( sprite[i].z < zTop )
  511. dz = (zTop - sprite[i].z) >> 8;
  512. else if ( sprite[i].z > zBot )
  513. dz = (sprite[i].z - zBot) >> 8;
  514. if (dz < kTouchZDist)
  515. {
  516. if (qdist(dx, dy) < kTouchXYDist)
  517. {
  518. int zTop, zBot;
  519. GetSpriteExtents(&sprite[i], &zTop, &zBot);
  520. if (
  521. // center
  522. cansee(pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum,
  523. sprite[i].x, sprite[i].y, sprite[i].z, sprite[i].sectnum) ||
  524. // top
  525. cansee(pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum,
  526. sprite[i].x, sprite[i].y, zTop, sprite[i].sectnum) ||
  527. // bottom
  528. cansee(pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum,
  529. sprite[i].x, sprite[i].y, zBot, sprite[i].sectnum)
  530. )
  531. return i;
  532. }
  533. }
  534. }
  535. }
  536. }
  537. return -1;
  538. }
  539. static BOOL PickupItem( PLAYER *pPlayer, int nSprite, int nItemType )
  540. {
  541. SPRITE *pSprite = pPlayer->sprite;
  542. XSPRITE *pXSprite = pPlayer->xsprite;
  543. int nPowerUp = nItemType - kItemBase;
  544. switch( nItemType )
  545. {
  546. case kItemKey1:
  547. case kItemKey2:
  548. case kItemKey3:
  549. case kItemKey4:
  550. case kItemKey5:
  551. case kItemKey6:
  552. case kItemKey7:
  553. if ( pPlayer->hasKey[nItemType - kItemKey1 + 1] )
  554. return FALSE;
  555. pPlayer->hasKey[nItemType - kItemKey1 + 1] = sprite[nSprite].picnum;
  556. break;
  557. case kItemDoctorBag:
  558. case kItemPotion1:
  559. case kItemMedPouch:
  560. case kItemLifeEssence:
  561. case kItemLifeSeed:
  562. if ( !actHealDude(pXSprite, gPowerUpInfo[nPowerUp].addPower, gPowerUpInfo[nPowerUp].maxPower) )
  563. return FALSE;
  564. break;
  565. default:
  566. if ( !powerupActivate( pPlayer, nPowerUp ) )
  567. return FALSE;
  568. break;
  569. }
  570. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxPlayItemUp);
  571. return TRUE;
  572. }
  573. static BOOL PickupAmmo( PLAYER *pPlayer, int /*nSprite*/, int nAmmoItemType )
  574. {
  575. AMMOITEMDATA *pAmmoData = &gAmmoItemData[nAmmoItemType - kAmmoItemBase];
  576. int nAmmoType = pAmmoData->ammoType;
  577. if ( pPlayer->ammoCount[nAmmoType] >= gAmmoInfo[nAmmoType].max )
  578. return FALSE;
  579. pPlayer->ammoCount[nAmmoType] = ClipHigh(
  580. pPlayer->ammoCount[nAmmoType] + pAmmoData->count, gAmmoInfo[nAmmoType].max );
  581. // set the hasWeapon flags for weapons which are ammo
  582. if ( pAmmoData->weaponType != kWeaponNone )
  583. pPlayer->hasWeapon[pAmmoData->weaponType] = TRUE;
  584. SPRITE *pSprite = pPlayer->sprite;
  585. sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxPlayItemUp);
  586. return TRUE;
  587. }
  588. static BOOL PickupWeapon( PLAYER *pPlayer, int nSprite, int nWeaponItem )
  589. {
  590. WEAPONITEMDATA *pWeaponData = &gWeaponItemData[nWeaponItem - kWeaponItemBase];
  591. int nWeapon = pWeaponData->weaponType;
  592. int nAmmo = pWeaponData->ammoType;
  593. // add weapon to player inventory
  594. if ( !pPlayer->hasWeapon[nWeapon] )
  595. {
  596. pPlayer->hasWeapon[nWeapon] = TRUE;
  597. if ( nAmmo != kAmmoNone )
  598. {
  599. // add preloaded ammo
  600. pPlayer->ammoCount[nAmmo] = ClipHigh(
  601. pPlayer->ammoCount[nAmmo] + pWeaponData->count, gAmmoInfo[nAmmo].max );
  602. }
  603. SPRITE *pSprite = pPlayer->sprite;
  604. // sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxWeaponUp);
  605. return TRUE;
  606. }
  607. if ( nAmmo == kAmmoNone )
  608. return FALSE;
  609. if ( pPlayer->ammoCount[nAmmo] >= gAmmoInfo[nAmmo].max )
  610. return FALSE;
  611. BOOL isPermanent = FALSE;
  612. if ( sprite[nSprite].extra > 0)
  613. {
  614. XSPRITE *pXItem = &xsprite[sprite[nSprite].extra];
  615. if ( pXItem->respawn == kRespawnPermanent )
  616. isPermanent = TRUE;
  617. }
  618. if ( !isPermanent )
  619. {
  620. // add preloaded ammo
  621. pPlayer->ammoCount[nAmmo] = ClipHigh(
  622. pPlayer->ammoCount[nAmmo] + pWeaponData->count, gAmmoInfo[nAmmo].max );
  623. SPRITE *pSprite = pPlayer->sprite;
  624. // sfxCreate3DSound(pSprite->x, pSprite->y, pSprite->z, kSfxWeaponUp);
  625. return TRUE;
  626. }
  627. return FALSE;
  628. }
  629. static void PickUp( PLAYER *pPlayer )
  630. {
  631. int x, y, z;
  632. SPRITE *pSprite = pPlayer->sprite;
  633. XSPRITE *pXSprite = pPlayer->xsprite;
  634. char buffer[80];
  635. x = pSprite->x;
  636. y = pSprite->y;
  637. z = pSprite->z;
  638. int nSprite = CheckTouchSprite(pSprite);
  639. if (nSprite >= 0)
  640. {
  641. BOOL bPickedUp = FALSE;
  642. int nType = sprite[nSprite].type;
  643. if (nType >= kItemBase && nType <= kItemMax)
  644. {
  645. bPickedUp = PickupItem( pPlayer, nSprite, nType );
  646. sprintf(buffer, "Picked up %s", gItemText[ nType - kItemBase ] );
  647. }
  648. else if (nType >= kAmmoItemBase && nType < kAmmoItemMax) {
  649. bPickedUp = PickupAmmo( pPlayer, nSprite, nType );
  650. sprintf(buffer, "Picked up %s", gAmmoText[ nType - kAmmoItemBase ] );
  651. }
  652. else if (nType >= kWeaponItemBase && nType < kWeaponItemMax)
  653. {
  654. bPickedUp = PickupWeapon( pPlayer, nSprite, nType );
  655. sprintf(buffer, "Picked up %s", gWeaponText[ nType - kWeaponItemBase ] );
  656. }
  657. if (bPickedUp)
  658. {
  659. if ( sprite[nSprite].extra > 0)
  660. {
  661. XSPRITE *pXItem = &xsprite[sprite[nSprite].extra];
  662. if ( pXItem->triggerPickup )
  663. trTriggerSprite(nSprite, pXItem, kCommandSpritePickup);
  664. }
  665. if ( !actCheckRespawn( nSprite ) )
  666. actPostSprite( nSprite, kStatFree );
  667. if (pPlayer == gMe)
  668. {
  669. viewSetMessage(buffer);
  670. scrDacRelEffect(16, 16, -16);
  671. }
  672. }
  673. }
  674. }
  675. static int ActionScan( PLAYER *pPlayer, int *nIndex, int *nXIndex)
  676. {
  677. SPRITE *pSprite = pPlayer->sprite;
  678. HITINFO hitInfo;
  679. *nIndex = 0;
  680. *nXIndex = 0;
  681. int dx = Cos(pSprite->ang) >> 16;
  682. int dy = Sin(pSprite->ang) >> 16;
  683. int dz = pPlayer->slope;
  684. int hitType = HitScan(pSprite, pSprite->z - pPlayer->eyeAboveZ, dx, dy, dz, &hitInfo);
  685. int hitDist = qdist(pSprite->x - hitInfo.hitx, pSprite->y - hitInfo.hity) >> 4;
  686. if ( hitDist < kPushXYDist )
  687. {
  688. switch ( hitType )
  689. {
  690. case SS_SPRITE:
  691. *nIndex = hitInfo.hitsprite;
  692. *nXIndex = sprite[*nIndex].extra;
  693. if (*nXIndex > 0 && xsprite[*nXIndex].triggerPush )
  694. return SS_SPRITE;
  695. if ( sprite[*nIndex].statnum == kStatDude )
  696. {
  697. SPRITE *pDude = &sprite[*nIndex];
  698. XSPRITE *pXDude = &xsprite[*nXIndex];
  699. dprintf("DUDE %d: ang=%d, goalAng=%d\n", *nIndex, pDude->ang, pXDude->goalAng);
  700. }
  701. break;
  702. case SS_MASKED:
  703. case SS_WALL:
  704. *nIndex = hitInfo.hitwall;
  705. *nXIndex = wall[*nIndex].extra;
  706. if (*nXIndex > 0 && xwall[*nXIndex].triggerPush )
  707. return SS_WALL;
  708. if ( wall[*nIndex].nextsector >= 0)
  709. {
  710. *nIndex = wall[*nIndex].nextsector;
  711. *nXIndex = sector[*nIndex].extra;
  712. if (*nXIndex > 0 && xsector[*nXIndex].triggerWPush )
  713. return SS_SECTOR;
  714. }
  715. break;
  716. case SS_FLOOR:
  717. case SS_CEILING:
  718. *nIndex = hitInfo.hitsect;
  719. *nXIndex = sector[*nIndex].extra;
  720. if (*nXIndex > 0 && xsector[*nXIndex].triggerPush )
  721. return SS_SECTOR;
  722. break;
  723. }
  724. if ( pPlayer == gMe )
  725. sfxStart3DSound(pPlayer->sprite->extra, kSfxPlayHunt, 0x1000); // push grunt
  726. }
  727. *nIndex = pSprite->sectnum;
  728. *nXIndex = sector[*nIndex].extra;
  729. if (*nXIndex > 0 && xsector[*nXIndex].triggerPush )
  730. return SS_SECTOR;
  731. return -1;
  732. }
  733. static void ProcessInput( PLAYER *pPlayer, INPUT *pInput )
  734. {
  735. long vel, svel, sin, cos;
  736. POSTURE *cp = &gPosture[pPlayer->lifemode];
  737. SPRITE *pSprite = pPlayer->sprite;
  738. XSPRITE *pXSprite = pPlayer->xsprite;
  739. pPlayer->run = FALSE;
  740. BOOL run;
  741. WeaponProcess(pPlayer, pInput);
  742. // quick hack for death
  743. if (pXSprite->health == 0)
  744. {
  745. if ( pPlayer->deathTime == 0 )
  746. {
  747. // pXSprite->avel = (pXSprite->avel + BiRandom(40)) & kAngleMask;
  748. }
  749. pPlayer->deathTime += kFrameTicks;
  750. pPlayer->horiz = mulscale16((1 << 15) - (Cos(ClipHigh(pPlayer->deathTime << 3, kAngle180)) >> 15), kHorizUpMax);
  751. pXSprite->moveState = kMoveDead;
  752. pPlayer->compression = mulscale16((1 << 15) - (Cos(ClipHigh(pPlayer->deathTime << 3, kAngle90)) >> 15), pPlayer->eyeAboveZ);
  753. if (pPlayer->weapon)
  754. pInput->newWeapon = pPlayer->weapon; // force weapon down
  755. if (pInput->keyFlags.action)
  756. {
  757. playerReset(pPlayer, pInput, pPlayer->sprite->type);
  758. pInput->keyFlags.action = 0;
  759. }
  760. return; // Don't allow the player to do anything else if dead
  761. }
  762. sin = Sin(pSprite->ang);
  763. cos = Cos(pSprite->ang);
  764. // find vel and svel relative to current angle
  765. vel = dmulscale30(pSprite->xvel, cos, pSprite->yvel, sin);
  766. svel = dmulscale30(pSprite->xvel, sin, -pSprite->yvel, cos);
  767. /*
  768. // ground deceleration
  769. switch ( pXSprite->moveState )
  770. {
  771. case kMoveFall:
  772. case kMoveSwim:
  773. break;
  774. default:
  775. if (vel > 0)
  776. vel = ClipLow(vel - pInput->ticks * cp->decel, 0);
  777. else if (vel < 0)
  778. vel = ClipHigh(vel + pInput->ticks * cp->decel, 0);
  779. if (svel > 0)
  780. svel = ClipLow(svel - pInput->ticks * cp->sideDecel, 0);
  781. else if (svel < 0)
  782. svel = ClipHigh(svel + pInput->ticks * cp->sideDecel, 0);
  783. break;
  784. }
  785. */
  786. // acceleration
  787. switch ( pXSprite->moveState )
  788. {
  789. case kMoveWalk:
  790. case kMoveStand:
  791. case kMoveLand:
  792. case kMoveSwim:
  793. if ( pInput->forward > 0 )
  794. {
  795. run = pInput->forward > pInput->ticks;
  796. pPlayer->run |= run;
  797. if ( vel < cp->frontSpeed[run] );
  798. vel = ClipHigh(vel + cp->frontAccel * pInput->forward + kGroundFriction * kFrameTicks, cp->frontSpeed[run]);
  799. }
  800. else if ( pInput->forward < 0 )
  801. {
  802. run = pInput->forward < -pInput->ticks;
  803. pPlayer->run |= run;
  804. if ( vel > -cp->backSpeed[run] );
  805. vel = ClipLow(vel + cp->backAccel * pInput->forward - kGroundFriction * kFrameTicks, -cp->backSpeed[run]);
  806. }
  807. if ( pInput->strafe > 0 )
  808. {
  809. run = pInput->strafe > pInput->ticks;
  810. pPlayer->run |= run;
  811. if ( svel < cp->sideSpeed[run] );
  812. svel = ClipHigh(svel + cp->sideAccel * pInput->strafe + kGroundFriction * kFrameTicks, cp->sideSpeed[run]);
  813. }
  814. else if ( pInput->strafe < 0 )
  815. {
  816. run = pInput->strafe < -pInput->ticks;
  817. pPlayer->run |= run;
  818. if ( svel > -cp->sideSpeed[run] );
  819. svel = ClipLow(svel + cp->sideAccel * pInput->strafe - kGroundFriction * kFrameTicks, -cp->sideSpeed[run]);
  820. }
  821. break;
  822. }
  823. // turn player
  824. if (pInput->turn != 0)
  825. pSprite->ang = (short)((pSprite->ang + (pInput->turn * kFrameTicks >> 4)) & kAngleMask);
  826. // reconstruct x and y velocities
  827. pSprite->xvel = (short)dmulscale30(vel, cos, svel, sin);
  828. pSprite->yvel = (short)dmulscale30(vel, sin, -svel, cos);
  829. // action key
  830. if (pInput->keyFlags.action)
  831. {
  832. int nIndex, nXIndex;
  833. int keyId;
  834. switch ( ActionScan(pPlayer, &nIndex, &nXIndex) )
  835. {
  836. case SS_SECTOR:
  837. {
  838. XSECTOR *pXSector = &xsector[nXIndex];
  839. keyId = pXSector->key;
  840. dprintf("Key %d required\n", keyId);
  841. if ( pXSector->locked && pPlayer == gMe )
  842. viewSetMessage("It's locked");
  843. if ( keyId == 0 || pPlayer->hasKey[keyId] )
  844. trTriggerSector(nIndex, pXSector, kCommandSpritePush);
  845. else
  846. if (pPlayer == gMe)
  847. {
  848. viewSetMessage("That requires a key.");
  849. }
  850. break;
  851. }
  852. case SS_WALL:
  853. {
  854. XWALL *pXWall = &xwall[nXIndex];
  855. keyId = pXWall->key;
  856. dprintf("Key %d required\n", keyId);
  857. if ( pXWall->locked && pPlayer == gMe )
  858. viewSetMessage("It's locked");
  859. if ( keyId == 0 || pPlayer->hasKey[keyId] )
  860. trTriggerWall(nIndex, pXWall, kCommandWallPush);
  861. else
  862. if (pPlayer == gMe)
  863. {
  864. viewSetMessage("That requires a key.");
  865. }
  866. break;
  867. }
  868. case SS_SPRITE:
  869. {
  870. XSPRITE *pXSprite = &xsprite[nXIndex];
  871. keyId = pXSprite->key;
  872. dprintf("Key %d required\n", keyId);
  873. if ( pXSprite->locked && pPlayer == gMe )
  874. viewSetMessage("It's locked");
  875. if ( keyId == 0 || pPlayer->hasKey[keyId] )
  876. trTriggerSprite(nIndex, pXSprite, kCommandSpritePush);
  877. else
  878. if (pPlayer == gMe)
  879. {
  880. viewSetMessage("That requires a key.");
  881. }
  882. break;
  883. }
  884. }
  885. // non-repeating, so clear flag
  886. pInput->keyFlags.action = 0;
  887. }
  888. if ( pInput->keyFlags.lookcenter && !pInput->buttonFlags.lookup && !pInput->buttonFlags.lookdown )
  889. {
  890. if ( pPlayer->look < 0 )
  891. pPlayer->look = ClipHigh(pPlayer->look + kFrameTicks, 0);
  892. if ( pPlayer->look > 0 )
  893. pPlayer->look = ClipLow(pPlayer->look - kFrameTicks, 0);
  894. if ( pPlayer->look == 0 )
  895. pInput->keyFlags.lookcenter = 0;
  896. }
  897. else
  898. {
  899. if ( pInput->buttonFlags.lookup )
  900. pPlayer->look = ClipHigh(pPlayer->look + kFrameTicks, kLookMax);
  901. if ( pInput->buttonFlags.lookdown )
  902. pPlayer->look = ClipLow(pPlayer->look - kFrameTicks, -kLookMax);
  903. }
  904. if ( pPlayer->look > 0 )
  905. pPlayer->horiz = mulscale30(kHorizUpMax, Sin(pPlayer->look * (kAngle90 / kLookMax)));
  906. else if ( pPlayer->look < 0 )
  907. pPlayer->horiz = mulscale30(kHorizDownMax, Sin(pPlayer->look * (kAngle90 / kLookMax)));
  908. else
  909. pPlayer->horiz = 0;
  910. pPlayer->slope = -pPlayer->horiz << 7;
  911. PickUp(pPlayer);
  912. }
  913. void playerMove( PLAYER *pPlayer, INPUT *pInput )
  914. {
  915. int nSprite = pPlayer->nSprite;
  916. SPRITE *pSprite = pPlayer->sprite;
  917. int nXSprite = pSprite->extra;
  918. XSPRITE *pXSprite = pPlayer->xsprite;
  919. short nSector;
  920. int nXSector;
  921. XSECTOR *pXSector = NULL;
  922. POSTURE *cp = &gPosture[pPlayer->lifemode];
  923. nSector = pSprite->sectnum;
  924. if ( (nXSector = sector[nSector].extra) > 0 )
  925. pXSector = &xsector[nXSector];
  926. int moveDist = qdist(pSprite->xvel, pSprite->yvel);
  927. ProcessInput(pPlayer, pInput);
  928. if ( pXSprite->health == 0 )
  929. return;
  930. int dudeIndex = kDudePlayer1 - kDudeBase;
  931. if ( moveDist == 0 )
  932. seqSpawn(dudeInfo[dudeIndex].seqStartID + kSeqDudeIdle, SS_SPRITE, nXSprite);
  933. else
  934. seqSpawn(dudeInfo[dudeIndex].seqStartID + kSeqCultistWalk, SS_SPRITE, nXSprite); // hack to make player walk
  935. if ( gSpriteHit[nXSprite].floorHit == 0 )
  936. pXSprite->moveState = kMoveFall;
  937. else
  938. pXSprite->moveState = kMoveWalk;
  939. /*
  940. switch (pXSprite->moveState)
  941. {
  942. case kMoveFall:
  943. pPlayer->impactPE = pSprite->zvel * gSpring;
  944. pXSprite->moveState = kMoveLand;
  945. pSprite->zvel = 0;
  946. pPlayer->impactPhase = 0;
  947. pPlayer->standSpeed = kAngle90 / ClipLow(fallDamage << 2, 8);
  948. pPlayer->standSpeed = ClipLow(pPlayer->standSpeed, 2);
  949. // fall through to Move Land
  950. case kMoveLand:
  951. pPlayer->impactPhase = ClipHigh(pPlayer->impactPhase + dt * gSpringPhaseInc, kAngle90);
  952. pPlayer->compression = mulscale30(pPlayer->impactPE, Sin(pPlayer->impactPhase));
  953. // pSprite->zvel = mulscale30(pPlayer->impactPE, Cos(pPlayer->impactPhase));
  954. if (pPlayer->impactPhase == kAngle90)
  955. {
  956. pXSprite->moveState = kMoveStand;
  957. pPlayer->impactPhase = 0;
  958. pSprite->zvel = 0;
  959. }
  960. break;
  961. case kMoveStand:
  962. pPlayer->impactPhase = ClipHigh(pPlayer->impactPhase + dt * pPlayer->standSpeed, kAngle90);
  963. pPlayer->compression = mulscale30(pPlayer->impactPE, (1 << 30) - Sin(pPlayer->impactPhase));
  964. if (pPlayer->impactPhase == kAngle90)
  965. {
  966. pXSprite->moveState = kMoveWalk;
  967. pSprite->zvel = 0;
  968. pPlayer->impactPE = 0;
  969. }
  970. // fall through
  971. case kMoveWalk:
  972. if ( zBot > loz )
  973. {
  974. pPlayer->compression += zBot - loz;
  975. pSprite->z += loz - zBot;
  976. pPlayer->impactPhase = 0;
  977. pXSprite->moveState = kMoveStand;
  978. pPlayer->standSpeed = 8;
  979. pPlayer->impactPE = pPlayer->compression;
  980. }
  981. }
  982. */
  983. if ( pInput->buttonFlags.jump && gSpriteHit[nXSprite].floorHit != 0 )
  984. {
  985. sfxStart3DSound(nXSprite, kSfxPlayJump, 0x1000);
  986. pSprite->zvel = -400;
  987. }
  988. if (pSprite->sectnum < 0 || pSprite->sectnum >= numsectors)
  989. {
  990. dprintf("How did you get in the wrong sector (%d)?\n", pSprite->sectnum);
  991. }
  992. if (pXSector && (pXSector->underwater || (pXSector->depth == kDepthSwim && pSprite->z >= sector[nSector].floorz)))
  993. pXSprite->moveState = kMoveSwim;
  994. // bobbing and swaying code
  995. // this controls the decay on bobbing
  996. int xamp, yamp;
  997. pPlayer->bobAmp = ClipLow(pPlayer->bobAmp - 8 * kFrameTicks, 0);
  998. moveDist >>= 2;
  999. if ( gViewBobbing )
  1000. {
  1001. // this bobbing code should be moved somewhere else, VIEW maybe?
  1002. switch ( pPlayer->xsprite->moveState )
  1003. {
  1004. case kMoveWalk:
  1005. pPlayer->bobPhase = (pPlayer->bobPhase + kFrameTicks * cp->pace[pPlayer->run] * kAngle360 / 120 / kTimerRate) & kAngleMask;
  1006. pPlayer->swayPhase = (pPlayer->swayPhase + kFrameTicks * cp->pace[pPlayer->run] / 2 * kAngle360 / 120 / kTimerRate) & kAngleMask;
  1007. if ( pPlayer->run )
  1008. {
  1009. if (pPlayer->bobAmp < 512)
  1010. pPlayer->bobAmp = ClipHigh(pPlayer->bobAmp + moveDist, 512);
  1011. }
  1012. else
  1013. {
  1014. if (pPlayer->bobAmp < 384)
  1015. pPlayer->bobAmp = ClipHigh(pPlayer->bobAmp + moveDist, 384);
  1016. }
  1017. xamp = yamp = pPlayer->bobAmp;
  1018. break;
  1019. case kMoveSwim:
  1020. pPlayer->bobPhase = (pPlayer->bobPhase + kFrameTicks * kAngle360 / kTimerRate / 2) & kAngleMask;
  1021. pPlayer->swayPhase = (pPlayer->swayPhase + kFrameTicks * kAngle360 / kTimerRate / 2) & kAngleMask;
  1022. yamp = 64;
  1023. xamp = 0;
  1024. break;
  1025. default:
  1026. xamp = yamp = pPlayer->bobAmp;
  1027. }
  1028. pPlayer->bobHeight = mulscale30(cp->bobV * yamp, Sin(pPlayer->bobPhase * 2));
  1029. pPlayer->bobWidth = mulscale30(cp->bobH * xamp, Sin(pPlayer->bobPhase - kAngle45));
  1030. pPlayer->swayHeight = mulscale30(cp->swayV * yamp, Sin(pPlayer->swayPhase * 2));
  1031. pPlayer->swayWidth = mulscale30(cp->swayH * xamp, Sin(pPlayer->swayPhase - kAngle60));
  1032. }
  1033. }
  1034. void playerFireMissile( PLAYER *pPlayer, long dx, long dy, long dz, int missileType )
  1035. {
  1036. actFireMissile(pPlayer->nSprite, pPlayer->sprite->z - pPlayer->weaponAboveZ,
  1037. dx, dy, dz, missileType);
  1038. }
  1039. int playerFireThing( PLAYER *pPlayer, int relSlope, int thingType, int velocity )
  1040. {
  1041. dassert( thingType >= kThingBase && thingType < kThingMax );
  1042. SPRITE *pSprite = pPlayer->sprite;
  1043. return actFireThing( pPlayer->nSprite, pSprite->z - pPlayer->weaponAboveZ,
  1044. pPlayer->slope + relSlope, thingType, velocity );
  1045. }
  1046. void playerDamageSprite( PLAYER *pPlayer, int nSource, int nDamage )
  1047. {
  1048. // if (pPlayer == gMe)
  1049. if ( pPlayer == gView )
  1050. scrDacRelEffect((nDamage>>4)*2, (-nDamage>>4)*3, (-nDamage>>4)*3);
  1051. if ( nDamage > 0 )
  1052. sfxStart3DSound(pPlayer->sprite->extra, kSfxPlayPain, 0x1000);
  1053. // source can be targeted by lackeys?
  1054. if (IsDudeSprite( nSource ))
  1055. {
  1056. for (int i=0; i<kMaxLackeys; i++)
  1057. {
  1058. int nLackey = pPlayer->nLackeySprites[i];
  1059. if (nLackey >= 0 && nLackey != nSource)
  1060. aiAlertLackey( pPlayer, nLackey, nSource, nDamage );
  1061. }
  1062. }
  1063. }
  1064. BOOL playerAddLackey( PLAYER *pPlayer, int nLackey )
  1065. {
  1066. for (int i=0; i<kMaxLackeys; i++)
  1067. if (pPlayer->nLackeySprites[i] == nLackey)
  1068. {
  1069. //dprintf("lackey already in list\n");
  1070. return FALSE;
  1071. }
  1072. for (i=0; i<kMaxLackeys; i++)
  1073. if (pPlayer->nLackeySprites[i] == -1)
  1074. {
  1075. //dprintf("adding lackey %i: %i\n",i,nLackey);
  1076. pPlayer->nLackeySprites[i] = nLackey;
  1077. sprite[nLackey].owner = (short)pPlayer->nSprite;
  1078. break;
  1079. }
  1080. return (i < kMaxLackeys) ? TRUE : FALSE;
  1081. }
  1082. void playerDeleteLackey( PLAYER *pPlayer, int nLackey )
  1083. {
  1084. for (int i=0; i<kMaxLackeys; i++)
  1085. if (pPlayer->nLackeySprites[i] == nLackey)
  1086. {
  1087. pPlayer->nLackeySprites[i] = -1;
  1088. sprite[nLackey].owner = -1;
  1089. break;
  1090. }
  1091. }