p_pspr.c (10763B)
1 #include "doomdef.h" 2 #include "d_event.h" 3 #include "m_random.h" 4 #include "p_local.h" 5 #include "s_sound.h" 6 #include "doomstat.h" 7 #include "sounds.h" 8 #include "p_pspr.h" 9 10 #define LOWERSPEED FRACUNIT*6 11 #define RAISESPEED FRACUNIT*6 12 #define WEAPONBOTTOM 128*FRACUNIT 13 #define WEAPONTOP 32*FRACUNIT 14 #define BFGCELLS 40 15 16 fixed_t swingx; 17 fixed_t swingy; 18 fixed_t bulletslope; 19 20 void 21 P_SetPsprite(player_t* player, int position, statenum_t stnum) 22 { 23 pspdef_t* psp; 24 state_t* state; 25 26 psp = &player->psprites[position]; 27 do { 28 if (!stnum) { 29 psp->state = NULL; 30 break; 31 } 32 state = &states[stnum]; 33 psp->state = state; 34 psp->tics = state->tics; 35 if (state->misc1) { 36 psp->sx = state->misc1 << FRACBITS; 37 psp->sy = state->misc2 << FRACBITS; 38 } 39 if (state->action.acp2) { 40 state->action.acp2(player, psp); 41 if (!psp->state) 42 break; 43 } 44 stnum = psp->state->nextstate; 45 } while (!psp->tics); 46 } 47 48 void 49 P_CalcSwing(player_t* player) 50 { 51 fixed_t swing; 52 int angle; 53 54 swing = player->bob; 55 angle = (FINEANGLES/70*leveltime)&FINEMASK; 56 swingx = FixedMul ( swing, finesine[angle]); 57 angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK; 58 swingy = -FixedMul ( swingx, finesine[angle]); 59 } 60 61 void 62 P_BringUpWeapon(player_t* player) 63 { 64 statenum_t newstate; 65 66 if (player->pendingweapon == wp_nochange) player->pendingweapon = player->readyweapon; 67 if (player->pendingweapon == wp_chainsaw) S_StartSound (player->mo, sfx_sawup); 68 newstate = weaponinfo[player->pendingweapon].upstate; 69 player->pendingweapon = wp_nochange; 70 player->psprites[ps_weapon].sy = WEAPONBOTTOM; 71 P_SetPsprite (player, ps_weapon, newstate); 72 } 73 74 boolean 75 P_CheckAmmo(player_t* player) 76 { 77 ammotype_t ammo; 78 int count; 79 80 ammo = weaponinfo[player->readyweapon].ammo; 81 if (player->readyweapon == wp_bfg) count = BFGCELLS; 82 else if (player->readyweapon == wp_supershotgun) count = 2; 83 else count = 1; 84 if (ammo == am_noammo || player->ammo[ammo] >= count) return true; 85 do { 86 player->pendingweapon = wp_plasma; 87 if (player->weaponowned[wp_chaingun] && player->ammo[am_clip]) player->pendingweapon = wp_chaingun; 88 else if (player->weaponowned[wp_shotgun] && player->ammo[am_shell]) player->pendingweapon = wp_shotgun; 89 else if (player->ammo[am_clip]) player->pendingweapon = wp_pistol; 90 else if (player->weaponowned[wp_chainsaw]) player->pendingweapon = wp_chainsaw; 91 else if (player->weaponowned[wp_missile] && player->ammo[am_misl]) player->pendingweapon = wp_missile; 92 else player->pendingweapon = wp_fist; 93 } while (player->pendingweapon == wp_nochange); 94 P_SetPsprite (player, ps_weapon, weaponinfo[player->readyweapon].downstate); 95 return false; 96 } 97 98 void 99 P_FireWeapon(player_t* player) 100 { 101 statenum_t newstate; 102 103 if (!P_CheckAmmo(player)) return; 104 P_SetMobjState (player->mo, S_PLAY_ATK1); 105 newstate = weaponinfo[player->readyweapon].atkstate; 106 P_SetPsprite (player, ps_weapon, newstate); 107 P_NoiseAlert (player->mo, player->mo); 108 } 109 110 void 111 P_DropWeapon(player_t* player) 112 { 113 P_SetPsprite (player, ps_weapon, weaponinfo[player->readyweapon].downstate); 114 } 115 116 void 117 A_WeaponReady(player_t* player, pspdef_t* psp) 118 { 119 statenum_t newstate; 120 int angle; 121 122 if (player->mo->state == &states[S_PLAY_ATK1] || player->mo->state == &states[S_PLAY_ATK2]) P_SetMobjState (player->mo, S_PLAY); 123 if (player->readyweapon == wp_chainsaw && psp->state == &states[S_SAW]) S_StartSound (player->mo, sfx_sawidl); 124 if (player->pendingweapon != wp_nochange || !player->health) { 125 newstate = weaponinfo[player->readyweapon].downstate; 126 P_SetPsprite (player, ps_weapon, newstate); 127 return; 128 } 129 if (player->cmd.buttons & BT_ATTACK) { 130 if (!player->attackdown || (player->readyweapon != wp_missile && player->readyweapon != wp_bfg)) { 131 player->attackdown = true; 132 P_FireWeapon (player); 133 return; 134 } 135 } else player->attackdown = false; 136 angle = (128*leveltime)&FINEMASK; 137 psp->sx = FRACUNIT + FixedMul (player->bob, finecosine[angle]); 138 angle &= FINEANGLES/2-1; 139 psp->sy = WEAPONTOP + FixedMul (player->bob, finesine[angle]); 140 } 141 142 void 143 A_ReFire(player_t* player, pspdef_t* psp) 144 { 145 if ((player->cmd.buttons & BT_ATTACK) && player->pendingweapon == wp_nochange && player->health) { 146 player->refire++; 147 P_FireWeapon (player); 148 } else { 149 player->refire = 0; 150 P_CheckAmmo (player); 151 } 152 } 153 154 void 155 A_CheckReload(player_t* player, pspdef_t* psp) 156 { 157 P_CheckAmmo(player); 158 } 159 160 void 161 A_Lower(player_t* player, pspdef_t* psp) 162 { 163 psp->sy += LOWERSPEED; 164 if (psp->sy < WEAPONBOTTOM) return; 165 if (player->playerstate == PST_DEAD) { 166 psp->sy = WEAPONBOTTOM; 167 return; 168 } 169 if (!player->health) { 170 P_SetPsprite(player, ps_weapon, S_NULL); 171 return; 172 } 173 player->readyweapon = player->pendingweapon; 174 P_BringUpWeapon (player); 175 } 176 177 void 178 A_Raise(player_t* player, pspdef_t* psp) 179 { 180 statenum_t newstate; 181 182 psp->sy -= RAISESPEED; 183 if (psp->sy > WEAPONTOP) return; 184 psp->sy = WEAPONTOP; 185 newstate = weaponinfo[player->readyweapon].readystate; 186 P_SetPsprite (player, ps_weapon, newstate); 187 } 188 189 void 190 A_GunFlash(player_t* player, pspdef_t* psp) 191 { 192 P_SetMobjState(player->mo, S_PLAY_ATK2); 193 P_SetPsprite(player,ps_flash,weaponinfo[player->readyweapon].flashstate); 194 } 195 196 void 197 A_Punch(player_t* player, pspdef_t* psp) 198 { 199 angle_t angle; 200 int damage, slope; 201 202 damage = (P_Random() % 10 + 1) << 1; 203 if (player->powers[pw_strength]) damage *= 10; 204 angle = player->mo->angle; 205 angle += (P_Random()-P_Random())<<18; 206 slope = P_AimLineAttack (player->mo, angle, MELEERANGE); 207 P_LineAttack (player->mo, angle, MELEERANGE, slope, damage); 208 if (linetarget) { 209 S_StartSound (player->mo, sfx_punch); 210 player->mo->angle = R_PointToAngle2 (player->mo->x, player->mo->y, linetarget->x, linetarget->y); 211 } 212 } 213 214 void 215 A_Saw(player_t* player, pspdef_t* psp) 216 { 217 angle_t angle; 218 int damage, slope; 219 220 damage = 2 * (P_Random() % 10 + 1); 221 angle = player->mo->angle; 222 angle += (P_Random() - P_Random()) << 18; 223 slope = P_AimLineAttack (player->mo, angle, MELEERANGE+1); 224 P_LineAttack(player->mo, angle, MELEERANGE+1, slope, damage); 225 if (!linetarget) { 226 S_StartSound (player->mo, sfx_sawful); 227 return; 228 } 229 S_StartSound(player->mo, sfx_sawhit); 230 angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); 231 if (angle - player->mo->angle > ANG180) { 232 if (angle - player->mo->angle < -ANG90/20) player->mo->angle = angle + ANG90/21; 233 else player->mo->angle -= ANG90/20; 234 } else { 235 if (angle - player->mo->angle > ANG90/20) player->mo->angle = angle - ANG90/21; 236 else player->mo->angle += ANG90/20; 237 } 238 player->mo->flags |= MF_JUSTATTACKED; 239 } 240 241 void 242 A_FireMissile(player_t* player, pspdef_t* psp) 243 { 244 --player->ammo[weaponinfo[player->readyweapon].ammo]; 245 P_SpawnPlayerMissile (player->mo, MT_ROCKET); 246 } 247 248 void 249 A_FireBFG(player_t* player, pspdef_t* psp) 250 { 251 player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS; 252 P_SpawnPlayerMissile (player->mo, MT_BFG); 253 } 254 255 void 256 A_FirePlasma(player_t* player, pspdef_t* psp) 257 { 258 --player->ammo[weaponinfo[player->readyweapon].ammo]; 259 P_SetPsprite (player, ps_flash, weaponinfo[player->readyweapon].flashstate + (P_Random() & 1)); 260 P_SpawnPlayerMissile (player->mo, MT_PLASMA); 261 } 262 263 264 void 265 P_BulletSlope (mobj_t* mo) 266 { 267 angle_t an; 268 269 an = mo->angle; 270 bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); 271 if (!linetarget) { 272 an += 1<<26; 273 bulletslope = P_AimLineAttack(mo, an, 16*64*FRACUNIT); 274 if (!linetarget) { 275 an -= 2<<26; 276 bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); 277 } 278 } 279 } 280 281 void 282 P_GunShot(mobj_t* mo, boolean accurate) 283 { 284 angle_t angle; 285 int damage; 286 287 damage = 5 * (P_Random() % 3 + 1); 288 angle = mo->angle; 289 if (!accurate) angle += (P_Random()-P_Random())<<18; 290 P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage); 291 } 292 293 void 294 A_FirePistol(player_t* player, pspdef_t* psp) 295 { 296 S_StartSound(player->mo, sfx_pistol); 297 P_SetMobjState (player->mo, S_PLAY_ATK2); 298 --player->ammo[weaponinfo[player->readyweapon].ammo]; 299 P_SetPsprite(player, ps_flash, weaponinfo[player->readyweapon].flashstate); 300 P_BulletSlope (player->mo); 301 P_GunShot (player->mo, !player->refire); 302 } 303 304 void 305 A_FireShotgun(player_t* player, pspdef_t* psp) 306 { 307 int i; 308 309 S_StartSound(player->mo, sfx_shotgn); 310 P_SetMobjState(player->mo, S_PLAY_ATK2); 311 --player->ammo[weaponinfo[player->readyweapon].ammo]; 312 P_SetPsprite (player, ps_flash, weaponinfo[player->readyweapon].flashstate); 313 P_BulletSlope (player->mo); 314 for (i = 0; i < 7; ++i) P_GunShot(player->mo, false); 315 } 316 317 void 318 A_FireShotgun2(player_t* player, pspdef_t* psp) 319 { 320 angle_t angle; 321 int i, damage; 322 323 S_StartSound(player->mo, sfx_dshtgn); 324 P_SetMobjState(player->mo, S_PLAY_ATK2); 325 player->ammo[weaponinfo[player->readyweapon].ammo]-=2; 326 P_SetPsprite(player, ps_flash, weaponinfo[player->readyweapon].flashstate); 327 P_BulletSlope(player->mo); 328 for (i = 0; i < 20; ++i) { 329 damage = 5 * (P_Random() % 3 + 1); 330 angle = player->mo->angle; 331 angle += (P_Random() - P_Random()) << 19; 332 P_LineAttack (player->mo, angle, MISSILERANGE, bulletslope + ((P_Random()-P_Random())<<5), damage); 333 } 334 } 335 336 void 337 A_FireCGun(player_t* player, pspdef_t* psp) 338 { 339 S_StartSound(player->mo, sfx_pistol); 340 if (!player->ammo[weaponinfo[player->readyweapon].ammo]) return; 341 P_SetMobjState(player->mo, S_PLAY_ATK2); 342 --player->ammo[weaponinfo[player->readyweapon].ammo]; 343 P_SetPsprite(player, ps_flash, weaponinfo[player->readyweapon].flashstate + psp->state - &states[S_CHAIN1]); 344 P_BulletSlope(player->mo); 345 P_GunShot(player->mo, !player->refire); 346 } 347 348 void 349 A_Light0(player_t *player, pspdef_t *psp) 350 { 351 player->extralight = 0; 352 } 353 354 void 355 A_Light1(player_t *player, pspdef_t *psp) 356 { 357 player->extralight = 1; 358 } 359 360 void 361 A_Light2(player_t *player, pspdef_t *psp) 362 { 363 player->extralight = 2; 364 } 365 366 void 367 A_BFGSpray(mobj_t* mo) 368 { 369 angle_t an; 370 int i, j, damage; 371 372 for (i = 0; i < 40; ++i) { 373 an = mo->angle - ANG90/2 + ANG90/40 * i; 374 P_AimLineAttack(mo->target, an, 16*64*FRACUNIT); 375 if (!linetarget) continue; 376 P_SpawnMobj(linetarget->x, linetarget->y, linetarget->z + (linetarget->height>>2), MT_EXTRABFG); 377 damage = 0; 378 for (j = 0; j < 15; ++j) damage += (P_Random()&7) + 1; 379 P_DamageMobj(linetarget, mo->target,mo->target, damage); 380 } 381 } 382 383 void 384 A_BFGsound(player_t* player, pspdef_t* psp) 385 { 386 S_StartSound(player->mo, sfx_bfg); 387 } 388 389 void 390 P_SetupPsprites(player_t* player) 391 { 392 int i; 393 394 for (i = 0; i < NUMPSPRITES; ++i) player->psprites[i].state = NULL; 395 player->pendingweapon = player->readyweapon; 396 P_BringUpWeapon(player); 397 } 398 399 void 400 P_MovePsprites(player_t* player) 401 { 402 pspdef_t* psp; 403 state_t* state; 404 int i; 405 406 psp = &player->psprites[0]; 407 for (i = 0; i < NUMPSPRITES; ++i, ++psp) { 408 if ((state = psp->state)) { 409 if (psp->tics != -1) { 410 --psp->tics; 411 if (!psp->tics) P_SetPsprite(player, i, psp->state->nextstate); 412 } 413 } 414 } 415 player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; 416 player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; 417 }