doom

a minimalistic implementation of doom
git clone git://ssnf.xyz/doom
Log | Files | Refs

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 }