heretic/Heretic Source/P_PSPR.C

1870 lines
44 KiB
C

// P_pspr.c
#include "DoomDef.h"
#include "P_local.h"
#include "soundst.h"
// Macros
#define LOWERSPEED FRACUNIT*6
#define RAISESPEED FRACUNIT*6
#define WEAPONBOTTOM 128*FRACUNIT
#define WEAPONTOP 32*FRACUNIT
#define FLAME_THROWER_TICS 10*35
#define MAGIC_JUNK 1234
#define MAX_MACE_SPOTS 8
static int MaceSpotCount;
static struct
{
fixed_t x;
fixed_t y;
} MaceSpots[MAX_MACE_SPOTS];
fixed_t bulletslope;
static int WeaponAmmoUsePL1[NUMWEAPONS] = {
0, // staff
USE_GWND_AMMO_1, // gold wand
USE_CBOW_AMMO_1, // crossbow
USE_BLSR_AMMO_1, // blaster
USE_SKRD_AMMO_1, // skull rod
USE_PHRD_AMMO_1, // phoenix rod
USE_MACE_AMMO_1, // mace
0, // gauntlets
0 // beak
};
static int WeaponAmmoUsePL2[NUMWEAPONS] = {
0, // staff
USE_GWND_AMMO_2, // gold wand
USE_CBOW_AMMO_2, // crossbow
USE_BLSR_AMMO_2, // blaster
USE_SKRD_AMMO_2, // skull rod
USE_PHRD_AMMO_2, // phoenix rod
USE_MACE_AMMO_2, // mace
0, // gauntlets
0 // beak
};
weaponinfo_t wpnlev1info[NUMWEAPONS] =
{
{ // Staff
am_noammo, // ammo
S_STAFFUP, // upstate
S_STAFFDOWN, // downstate
S_STAFFREADY, // readystate
S_STAFFATK1_1, // atkstate
S_STAFFATK1_1, // holdatkstate
S_NULL // flashstate
},
{ // Gold wand
am_goldwand, // ammo
S_GOLDWANDUP, // upstate
S_GOLDWANDDOWN, // downstate
S_GOLDWANDREADY, // readystate
S_GOLDWANDATK1_1, // atkstate
S_GOLDWANDATK1_1, // holdatkstate
S_NULL // flashstate
},
{ // Crossbow
am_crossbow, // ammo
S_CRBOWUP, // upstate
S_CRBOWDOWN, // downstate
S_CRBOW1, // readystate
S_CRBOWATK1_1, // atkstate
S_CRBOWATK1_1, // holdatkstate
S_NULL // flashstate
},
{ // Blaster
am_blaster, // ammo
S_BLASTERUP, // upstate
S_BLASTERDOWN, // downstate
S_BLASTERREADY, // readystate
S_BLASTERATK1_1, // atkstate
S_BLASTERATK1_3, // holdatkstate
S_NULL // flashstate
},
{ // Skull rod
am_skullrod, // ammo
S_HORNRODUP, // upstate
S_HORNRODDOWN, // downstate
S_HORNRODREADY, // readystae
S_HORNRODATK1_1, // atkstate
S_HORNRODATK1_1, // holdatkstate
S_NULL // flashstate
},
{ // Phoenix rod
am_phoenixrod, // ammo
S_PHOENIXUP, // upstate
S_PHOENIXDOWN, // downstate
S_PHOENIXREADY, // readystate
S_PHOENIXATK1_1, // atkstate
S_PHOENIXATK1_1, // holdatkstate
S_NULL // flashstate
},
{ // Mace
am_mace, // ammo
S_MACEUP, // upstate
S_MACEDOWN, // downstate
S_MACEREADY, // readystate
S_MACEATK1_1, // atkstate
S_MACEATK1_2, // holdatkstate
S_NULL // flashstate
},
{ // Gauntlets
am_noammo, // ammo
S_GAUNTLETUP, // upstate
S_GAUNTLETDOWN, // downstate
S_GAUNTLETREADY, // readystate
S_GAUNTLETATK1_1, // atkstate
S_GAUNTLETATK1_3, // holdatkstate
S_NULL // flashstate
},
{ // Beak
am_noammo, // ammo
S_BEAKUP, // upstate
S_BEAKDOWN, // downstate
S_BEAKREADY, // readystate
S_BEAKATK1_1, // atkstate
S_BEAKATK1_1, // holdatkstate
S_NULL // flashstate
}
};
weaponinfo_t wpnlev2info[NUMWEAPONS] =
{
{ // Staff
am_noammo, // ammo
S_STAFFUP2, // upstate
S_STAFFDOWN2, // downstate
S_STAFFREADY2_1, // readystate
S_STAFFATK2_1, // atkstate
S_STAFFATK2_1, // holdatkstate
S_NULL // flashstate
},
{ // Gold wand
am_goldwand, // ammo
S_GOLDWANDUP, // upstate
S_GOLDWANDDOWN, // downstate
S_GOLDWANDREADY, // readystate
S_GOLDWANDATK2_1, // atkstate
S_GOLDWANDATK2_1, // holdatkstate
S_NULL // flashstate
},
{ // Crossbow
am_crossbow, // ammo
S_CRBOWUP, // upstate
S_CRBOWDOWN, // downstate
S_CRBOW1, // readystate
S_CRBOWATK2_1, // atkstate
S_CRBOWATK2_1, // holdatkstate
S_NULL // flashstate
},
{ // Blaster
am_blaster, // ammo
S_BLASTERUP, // upstate
S_BLASTERDOWN, // downstate
S_BLASTERREADY, // readystate
S_BLASTERATK2_1, // atkstate
S_BLASTERATK2_3, // holdatkstate
S_NULL // flashstate
},
{ // Skull rod
am_skullrod, // ammo
S_HORNRODUP, // upstate
S_HORNRODDOWN, // downstate
S_HORNRODREADY, // readystae
S_HORNRODATK2_1, // atkstate
S_HORNRODATK2_1, // holdatkstate
S_NULL // flashstate
},
{ // Phoenix rod
am_phoenixrod, // ammo
S_PHOENIXUP, // upstate
S_PHOENIXDOWN, // downstate
S_PHOENIXREADY, // readystate
S_PHOENIXATK2_1, // atkstate
S_PHOENIXATK2_2, // holdatkstate
S_NULL // flashstate
},
{ // Mace
am_mace, // ammo
S_MACEUP, // upstate
S_MACEDOWN, // downstate
S_MACEREADY, // readystate
S_MACEATK2_1, // atkstate
S_MACEATK2_1, // holdatkstate
S_NULL // flashstate
},
{ // Gauntlets
am_noammo, // ammo
S_GAUNTLETUP2, // upstate
S_GAUNTLETDOWN2, // downstate
S_GAUNTLETREADY2_1, // readystate
S_GAUNTLETATK2_1, // atkstate
S_GAUNTLETATK2_3, // holdatkstate
S_NULL // flashstate
},
{ // Beak
am_noammo, // ammo
S_BEAKUP, // upstate
S_BEAKDOWN, // downstate
S_BEAKREADY, // readystate
S_BEAKATK2_1, // atkstate
S_BEAKATK2_1, // holdatkstate
S_NULL // flashstate
}
};
//---------------------------------------------------------------------------
//
// PROC P_OpenWeapons
//
// Called at level load before things are loaded.
//
//---------------------------------------------------------------------------
void P_OpenWeapons(void)
{
MaceSpotCount = 0;
}
//---------------------------------------------------------------------------
//
// PROC P_AddMaceSpot
//
//---------------------------------------------------------------------------
void P_AddMaceSpot(mapthing_t *mthing)
{
if(MaceSpotCount == MAX_MACE_SPOTS)
{
I_Error("Too many mace spots.");
}
MaceSpots[MaceSpotCount].x = mthing->x<<FRACBITS;
MaceSpots[MaceSpotCount].y = mthing->y<<FRACBITS;
MaceSpotCount++;
}
//---------------------------------------------------------------------------
//
// PROC P_RepositionMace
//
// Chooses the next spot to place the mace.
//
//---------------------------------------------------------------------------
void P_RepositionMace(mobj_t *mo)
{
int spot;
subsector_t *ss;
P_UnsetThingPosition(mo);
spot = P_Random()%MaceSpotCount;
mo->x = MaceSpots[spot].x;
mo->y = MaceSpots[spot].y;
ss = R_PointInSubsector(mo->x, mo->y);
mo->z = mo->floorz = ss->sector->floorheight;
mo->ceilingz = ss->sector->ceilingheight;
P_SetThingPosition(mo);
}
//---------------------------------------------------------------------------
//
// PROC P_CloseWeapons
//
// Called at level load after things are loaded.
//
//---------------------------------------------------------------------------
void P_CloseWeapons(void)
{
int spot;
if(!MaceSpotCount)
{ // No maces placed
return;
}
if(!deathmatch && P_Random() < 64)
{ // Sometimes doesn't show up if not in deathmatch
return;
}
spot = P_Random()%MaceSpotCount;
P_SpawnMobj(MaceSpots[spot].x, MaceSpots[spot].y, ONFLOORZ, MT_WMACE);
}
//---------------------------------------------------------------------------
//
// PROC P_SetPsprite
//
//---------------------------------------------------------------------------
void P_SetPsprite(player_t *player, int position, statenum_t stnum)
{
pspdef_t *psp;
state_t *state;
psp = &player->psprites[position];
do
{
if(!stnum)
{ // Object removed itself.
psp->state = NULL;
break;
}
state = &states[stnum];
psp->state = state;
psp->tics = state->tics; // could be 0
if(state->misc1)
{ // Set coordinates.
psp->sx = state->misc1<<FRACBITS;
psp->sy = state->misc2<<FRACBITS;
}
if(state->action)
{ // Call action routine.
state->action(player, psp);
if(!psp->state)
{
break;
}
}
stnum = psp->state->nextstate;
} while(!psp->tics); // An initial state of 0 could cycle through.
}
/*
=================
=
= P_CalcSwing
=
=================
*/
/*
fixed_t swingx, swingy;
void P_CalcSwing (player_t *player)
{
fixed_t swing;
int angle;
// OPTIMIZE: tablify this
swing = player->bob;
angle = (FINEANGLES/70*leveltime)&FINEMASK;
swingx = FixedMul ( swing, finesine[angle]);
angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK;
swingy = -FixedMul ( swingx, finesine[angle]);
}
*/
//---------------------------------------------------------------------------
//
// PROC P_ActivateBeak
//
//---------------------------------------------------------------------------
void P_ActivateBeak(player_t *player)
{
player->pendingweapon = wp_nochange;
player->readyweapon = wp_beak;
player->psprites[ps_weapon].sy = WEAPONTOP;
P_SetPsprite(player, ps_weapon, S_BEAKREADY);
}
//---------------------------------------------------------------------------
//
// PROC P_PostChickenWeapon
//
//---------------------------------------------------------------------------
void P_PostChickenWeapon(player_t *player, weapontype_t weapon)
{
if(weapon == wp_beak)
{ // Should never happen
weapon = wp_staff;
}
player->pendingweapon = wp_nochange;
player->readyweapon = weapon;
player->psprites[ps_weapon].sy = WEAPONBOTTOM;
P_SetPsprite(player, ps_weapon, wpnlev1info[weapon].upstate);
}
//---------------------------------------------------------------------------
//
// PROC P_BringUpWeapon
//
// Starts bringing the pending weapon up from the bottom of the screen.
//
//---------------------------------------------------------------------------
void P_BringUpWeapon(player_t *player)
{
statenum_t new;
if(player->pendingweapon == wp_nochange)
{
player->pendingweapon = player->readyweapon;
}
if(player->pendingweapon == wp_gauntlets)
{
S_StartSound(player->mo, sfx_gntact);
}
if(player->powers[pw_weaponlevel2])
{
new = wpnlev2info[player->pendingweapon].upstate;
}
else
{
new = wpnlev1info[player->pendingweapon].upstate;
}
player->pendingweapon = wp_nochange;
player->psprites[ps_weapon].sy = WEAPONBOTTOM;
P_SetPsprite(player, ps_weapon, new);
}
//---------------------------------------------------------------------------
//
// FUNC P_CheckAmmo
//
// Returns true if there is enough ammo to shoot. If not, selects the
// next weapon to use.
//
//---------------------------------------------------------------------------
boolean P_CheckAmmo(player_t *player)
{
ammotype_t ammo;
int *ammoUse;
int count;
ammo = wpnlev1info[player->readyweapon].ammo;
if(player->powers[pw_weaponlevel2] && !deathmatch)
{
ammoUse = WeaponAmmoUsePL2;
}
else
{
ammoUse = WeaponAmmoUsePL1;
}
count = ammoUse[player->readyweapon];
if(ammo == am_noammo || player->ammo[ammo] >= count)
{
return(true);
}
// out of ammo, pick a weapon to change to
do
{
if(player->weaponowned[wp_skullrod]
&& player->ammo[am_skullrod] > ammoUse[wp_skullrod])
{
player->pendingweapon = wp_skullrod;
}
else if(player->weaponowned[wp_blaster]
&& player->ammo[am_blaster] > ammoUse[wp_blaster])
{
player->pendingweapon = wp_blaster;
}
else if(player->weaponowned[wp_crossbow]
&& player->ammo[am_crossbow] > ammoUse[wp_crossbow])
{
player->pendingweapon = wp_crossbow;
}
else if(player->weaponowned[wp_mace]
&& player->ammo[am_mace] > ammoUse[wp_mace])
{
player->pendingweapon = wp_mace;
}
else if(player->ammo[am_goldwand] > ammoUse[wp_goldwand])
{
player->pendingweapon = wp_goldwand;
}
else if(player->weaponowned[wp_gauntlets])
{
player->pendingweapon = wp_gauntlets;
}
else if(player->weaponowned[wp_phoenixrod]
&& player->ammo[am_phoenixrod] > ammoUse[wp_phoenixrod])
{
player->pendingweapon = wp_phoenixrod;
}
else
{
player->pendingweapon = wp_staff;
}
} while(player->pendingweapon == wp_nochange);
if(player->powers[pw_weaponlevel2])
{
P_SetPsprite(player, ps_weapon,
wpnlev2info[player->readyweapon].downstate);
}
else
{
P_SetPsprite(player, ps_weapon,
wpnlev1info[player->readyweapon].downstate);
}
return(false);
}
//---------------------------------------------------------------------------
//
// PROC P_FireWeapon
//
//---------------------------------------------------------------------------
void P_FireWeapon(player_t *player)
{
weaponinfo_t *wpinfo;
statenum_t attackState;
if(!P_CheckAmmo(player))
{
return;
}
P_SetMobjState(player->mo, S_PLAY_ATK2);
wpinfo = player->powers[pw_weaponlevel2] ? &wpnlev2info[0]
: &wpnlev1info[0];
attackState = player->refire ? wpinfo[player->readyweapon].holdatkstate
: wpinfo[player->readyweapon].atkstate;
P_SetPsprite(player, ps_weapon, attackState);
P_NoiseAlert(player->mo, player->mo);
if(player->readyweapon == wp_gauntlets && !player->refire)
{ // Play the sound for the initial gauntlet attack
S_StartSound(player->mo, sfx_gntuse);
}
}
//---------------------------------------------------------------------------
//
// PROC P_DropWeapon
//
// The player died, so put the weapon away.
//
//---------------------------------------------------------------------------
void P_DropWeapon(player_t *player)
{
if(player->powers[pw_weaponlevel2])
{
P_SetPsprite(player, ps_weapon,
wpnlev2info[player->readyweapon].downstate);
}
else
{
P_SetPsprite(player, ps_weapon,
wpnlev1info[player->readyweapon].downstate);
}
}
//---------------------------------------------------------------------------
//
// PROC A_WeaponReady
//
// The player can fire the weapon or change to another weapon at this time.
//
//---------------------------------------------------------------------------
void A_WeaponReady(player_t *player, pspdef_t *psp)
{
int angle;
if(player->chickenTics)
{ // Change to the chicken beak
P_ActivateBeak(player);
return;
}
// Change player from attack state
if(player->mo->state == &states[S_PLAY_ATK1]
|| player->mo->state == &states[S_PLAY_ATK2])
{
P_SetMobjState(player->mo, S_PLAY);
}
// Check for staff PL2 active sound
if((player->readyweapon == wp_staff)
&& (psp->state == &states[S_STAFFREADY2_1])
&& P_Random() < 128)
{
S_StartSound(player->mo, sfx_stfcrk);
}
// Put the weapon away if the player has a pending weapon or has
// died.
if(player->pendingweapon != wp_nochange || !player->health)
{
if(player->powers[pw_weaponlevel2])
{
P_SetPsprite(player, ps_weapon,
wpnlev2info[player->readyweapon].downstate);
}
else
{
P_SetPsprite(player, ps_weapon,
wpnlev1info[player->readyweapon].downstate);
}
return;
}
// Check for fire. The phoenix rod does not auto fire.
if(player->cmd.buttons&BT_ATTACK)
{
if(!player->attackdown || (player->readyweapon != wp_phoenixrod))
{
player->attackdown = true;
P_FireWeapon(player);
return;
}
}
else
{
player->attackdown = false;
}
// Bob the weapon based on movement speed.
angle = (128*leveltime)&FINEMASK;
psp->sx = FRACUNIT+FixedMul(player->bob, finecosine[angle]);
angle &= FINEANGLES/2-1;
psp->sy = WEAPONTOP+FixedMul(player->bob, finesine[angle]);
}
//---------------------------------------------------------------------------
//
// PROC P_UpdateBeak
//
//---------------------------------------------------------------------------
void P_UpdateBeak(player_t *player, pspdef_t *psp)
{
psp->sy = WEAPONTOP+(player->chickenPeck<<(FRACBITS-1));
}
//---------------------------------------------------------------------------
//
// PROC A_BeakReady
//
//---------------------------------------------------------------------------
void A_BeakReady(player_t *player, pspdef_t *psp)
{
if(player->cmd.buttons&BT_ATTACK)
{ // Chicken beak attack
player->attackdown = true;
P_SetMobjState(player->mo, S_CHICPLAY_ATK1);
if(player->powers[pw_weaponlevel2])
{
P_SetPsprite(player, ps_weapon, S_BEAKATK2_1);
}
else
{
P_SetPsprite(player, ps_weapon, S_BEAKATK1_1);
}
P_NoiseAlert(player->mo, player->mo);
}
else
{
if(player->mo->state == &states[S_CHICPLAY_ATK1])
{ // Take out of attack state
P_SetMobjState(player->mo, S_CHICPLAY);
}
player->attackdown = false;
}
}
//---------------------------------------------------------------------------
//
// PROC A_ReFire
//
// The player can re fire the weapon without lowering it entirely.
//
//---------------------------------------------------------------------------
void A_ReFire(player_t *player, pspdef_t *psp)
{
if((player->cmd.buttons&BT_ATTACK)
&& player->pendingweapon == wp_nochange && player->health)
{
player->refire++;
P_FireWeapon(player);
}
else
{
player->refire = 0;
P_CheckAmmo(player);
}
}
//---------------------------------------------------------------------------
//
// PROC A_Lower
//
//---------------------------------------------------------------------------
void A_Lower(player_t *player, pspdef_t *psp)
{
if(player->chickenTics)
{
psp->sy = WEAPONBOTTOM;
}
else
{
psp->sy += LOWERSPEED;
}
if(psp->sy < WEAPONBOTTOM)
{ // Not lowered all the way yet
return;
}
if(player->playerstate == PST_DEAD)
{ // Player is dead, so don't bring up a pending weapon
psp->sy = WEAPONBOTTOM;
return;
}
if(!player->health)
{ // Player is dead, so keep the weapon off screen
P_SetPsprite(player, ps_weapon, S_NULL);
return;
}
player->readyweapon = player->pendingweapon;
P_BringUpWeapon(player);
}
//---------------------------------------------------------------------------
//
// PROC A_BeakRaise
//
//---------------------------------------------------------------------------
void A_BeakRaise(player_t *player, pspdef_t *psp)
{
psp->sy = WEAPONTOP;
P_SetPsprite(player, ps_weapon,
wpnlev1info[player->readyweapon].readystate);
}
//---------------------------------------------------------------------------
//
// PROC A_Raise
//
//---------------------------------------------------------------------------
void A_Raise(player_t *player, pspdef_t *psp)
{
psp->sy -= RAISESPEED;
if(psp->sy > WEAPONTOP)
{ // Not raised all the way yet
return;
}
psp->sy = WEAPONTOP;
if(player->powers[pw_weaponlevel2])
{
P_SetPsprite(player, ps_weapon,
wpnlev2info[player->readyweapon].readystate);
}
else
{
P_SetPsprite(player, ps_weapon,
wpnlev1info[player->readyweapon].readystate);
}
}
/*
===============
=
= P_BulletSlope
=
= Sets a slope so a near miss is at aproximately the height of the
= intended target
=
===============
*/
void P_BulletSlope (mobj_t *mo)
{
angle_t an;
//
// see which target is to be aimed at
//
an = mo->angle;
bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
if (!linetarget)
{
an += 1<<26;
bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
if (!linetarget)
{
an -= 2<<26;
bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
}
if (!linetarget)
{
an += 2<<26;
bulletslope = (mo->player->lookdir<<FRACBITS)/173;
}
}
}
//****************************************************************************
//
// WEAPON ATTACKS
//
//****************************************************************************
//----------------------------------------------------------------------------
//
// PROC A_BeakAttackPL1
//
//----------------------------------------------------------------------------
void A_BeakAttackPL1(player_t *player, pspdef_t *psp)
{
angle_t angle;
int damage;
int slope;
damage = 1+(P_Random()&3);
angle = player->mo->angle;
slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
PuffType = MT_BEAKPUFF;
P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
if(linetarget)
{
player->mo->angle = R_PointToAngle2(player->mo->x,
player->mo->y, linetarget->x, linetarget->y);
}
S_StartSound(player->mo, sfx_chicpk1+(P_Random()%3));
player->chickenPeck = 12;
psp->tics -= P_Random()&7;
}
//----------------------------------------------------------------------------
//
// PROC A_BeakAttackPL2
//
//----------------------------------------------------------------------------
void A_BeakAttackPL2(player_t *player, pspdef_t *psp)
{
angle_t angle;
int damage;
int slope;
damage = HITDICE(4);
angle = player->mo->angle;
slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
PuffType = MT_BEAKPUFF;
P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
if(linetarget)
{
player->mo->angle = R_PointToAngle2(player->mo->x,
player->mo->y, linetarget->x, linetarget->y);
}
S_StartSound(player->mo, sfx_chicpk1+(P_Random()%3));
player->chickenPeck = 12;
psp->tics -= P_Random()&3;
}
//----------------------------------------------------------------------------
//
// PROC A_StaffAttackPL1
//
//----------------------------------------------------------------------------
void A_StaffAttackPL1(player_t *player, pspdef_t *psp)
{
angle_t angle;
int damage;
int slope;
damage = 5+(P_Random()&15);
angle = player->mo->angle;
angle += (P_Random()-P_Random())<<18;
slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
PuffType = MT_STAFFPUFF;
P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
if(linetarget)
{
//S_StartSound(player->mo, sfx_stfhit);
// turn to face target
player->mo->angle = R_PointToAngle2(player->mo->x,
player->mo->y, linetarget->x, linetarget->y);
}
}
//----------------------------------------------------------------------------
//
// PROC A_StaffAttackPL2
//
//----------------------------------------------------------------------------
void A_StaffAttackPL2(player_t *player, pspdef_t *psp)
{
angle_t angle;
int damage;
int slope;
// P_inter.c:P_DamageMobj() handles target momentums
damage = 18+(P_Random()&63);
angle = player->mo->angle;
angle += (P_Random()-P_Random())<<18;
slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
PuffType = MT_STAFFPUFF2;
P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
if(linetarget)
{
//S_StartSound(player->mo, sfx_stfpow);
// turn to face target
player->mo->angle = R_PointToAngle2(player->mo->x,
player->mo->y, linetarget->x, linetarget->y);
}
}
//----------------------------------------------------------------------------
//
// PROC A_FireBlasterPL1
//
//----------------------------------------------------------------------------
void A_FireBlasterPL1(player_t *player, pspdef_t *psp)
{
mobj_t *mo;
angle_t angle;
int damage;
mo = player->mo;
S_StartSound(mo, sfx_gldhit);
player->ammo[am_blaster] -= USE_BLSR_AMMO_1;
P_BulletSlope(mo);
damage = HITDICE(4);
angle = mo->angle;
if(player->refire)
{
angle += (P_Random()-P_Random())<<18;
}
PuffType = MT_BLASTERPUFF1;
P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
S_StartSound(player->mo, sfx_blssht);
}
//----------------------------------------------------------------------------
//
// PROC A_FireBlasterPL2
//
//----------------------------------------------------------------------------
void A_FireBlasterPL2(player_t *player, pspdef_t *psp)
{
mobj_t *mo;
player->ammo[am_blaster] -=
deathmatch ? USE_BLSR_AMMO_1 : USE_BLSR_AMMO_2;
mo = P_SpawnPlayerMissile(player->mo, MT_BLASTERFX1);
if(mo)
{
mo->thinker.function = P_BlasterMobjThinker;
}
S_StartSound(player->mo, sfx_blssht);
}
//----------------------------------------------------------------------------
//
// PROC A_FireGoldWandPL1
//
//----------------------------------------------------------------------------
void A_FireGoldWandPL1(player_t *player, pspdef_t *psp)
{
mobj_t *mo;
angle_t angle;
int damage;
mo = player->mo;
player->ammo[am_goldwand] -= USE_GWND_AMMO_1;
P_BulletSlope(mo);
damage = 7+(P_Random()&7);
angle = mo->angle;
if(player->refire)
{
angle += (P_Random()-P_Random())<<18;
}
PuffType = MT_GOLDWANDPUFF1;
P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
S_StartSound(player->mo, sfx_gldhit);
}
//----------------------------------------------------------------------------
//
// PROC A_FireGoldWandPL2
//
//----------------------------------------------------------------------------
void A_FireGoldWandPL2(player_t *player, pspdef_t *psp)
{
int i;
mobj_t *mo;
angle_t angle;
int damage;
fixed_t momz;
mo = player->mo;
player->ammo[am_goldwand] -=
deathmatch ? USE_GWND_AMMO_1 : USE_GWND_AMMO_2;
PuffType = MT_GOLDWANDPUFF2;
P_BulletSlope(mo);
momz = FixedMul(mobjinfo[MT_GOLDWANDFX2].speed, bulletslope);
P_SpawnMissileAngle(mo, MT_GOLDWANDFX2, mo->angle-(ANG45/8), momz);
P_SpawnMissileAngle(mo, MT_GOLDWANDFX2, mo->angle+(ANG45/8), momz);
angle = mo->angle-(ANG45/8);
for(i = 0; i < 5; i++)
{
damage = 1+(P_Random()&7);
P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
angle += ((ANG45/8)*2)/4;
}
S_StartSound(player->mo, sfx_gldhit);
}
//----------------------------------------------------------------------------
//
// PROC A_FireMacePL1B
//
//----------------------------------------------------------------------------
void A_FireMacePL1B(player_t *player, pspdef_t *psp)
{
mobj_t *pmo;
mobj_t *ball;
angle_t angle;
if(player->ammo[am_mace] < USE_MACE_AMMO_1)
{
return;
}
player->ammo[am_mace] -= USE_MACE_AMMO_1;
pmo = player->mo;
ball = P_SpawnMobj(pmo->x, pmo->y, pmo->z+28*FRACUNIT
- FOOTCLIPSIZE*(pmo->flags2&MF2_FEETARECLIPPED != 0), MT_MACEFX2);
ball->momz = 2*FRACUNIT+((player->lookdir)<<(FRACBITS-5));
angle = pmo->angle;
ball->target = pmo;
ball->angle = angle;
ball->z += (player->lookdir)<<(FRACBITS-4);
angle >>= ANGLETOFINESHIFT;
ball->momx = (pmo->momx>>1)
+FixedMul(ball->info->speed, finecosine[angle]);
ball->momy = (pmo->momy>>1)
+FixedMul(ball->info->speed, finesine[angle]);
S_StartSound(ball, sfx_lobsht);
P_CheckMissileSpawn(ball);
}
//----------------------------------------------------------------------------
//
// PROC A_FireMacePL1
//
//----------------------------------------------------------------------------
void A_FireMacePL1(player_t *player, pspdef_t *psp)
{
mobj_t *ball;
if(P_Random() < 28)
{
A_FireMacePL1B(player, psp);
return;
}
if(player->ammo[am_mace] < USE_MACE_AMMO_1)
{
return;
}
player->ammo[am_mace] -= USE_MACE_AMMO_1;
psp->sx = ((P_Random()&3)-2)*FRACUNIT;
psp->sy = WEAPONTOP+(P_Random()&3)*FRACUNIT;
ball = P_SPMAngle(player->mo, MT_MACEFX1, player->mo->angle
+(((P_Random()&7)-4)<<24));
if(ball)
{
ball->special1 = 16; // tics till dropoff
}
}
//----------------------------------------------------------------------------
//
// PROC A_MacePL1Check
//
//----------------------------------------------------------------------------
void A_MacePL1Check(mobj_t *ball)
{
angle_t angle;
if(ball->special1 == 0)
{
return;
}
ball->special1 -= 4;
if(ball->special1 > 0)
{
return;
}
ball->special1 = 0;
ball->flags2 |= MF2_LOGRAV;
angle = ball->angle>>ANGLETOFINESHIFT;
ball->momx = FixedMul(7*FRACUNIT, finecosine[angle]);
ball->momy = FixedMul(7*FRACUNIT, finesine[angle]);
ball->momz -= ball->momz>>1;
}
//----------------------------------------------------------------------------
//
// PROC A_MaceBallImpact
//
//----------------------------------------------------------------------------
void A_MaceBallImpact(mobj_t *ball)
{
if((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID))
{ // Landed in some sort of liquid
P_RemoveMobj(ball);
return;
}
if((ball->health != MAGIC_JUNK) && (ball->z <= ball->floorz)
&& ball->momz)
{ // Bounce
ball->health = MAGIC_JUNK;
ball->momz = (ball->momz*192)>>8;
ball->flags2 &= ~MF2_FLOORBOUNCE;
P_SetMobjState(ball, ball->info->spawnstate);
S_StartSound(ball, sfx_bounce);
}
else
{ // Explode
ball->flags |= MF_NOGRAVITY;
ball->flags2 &= ~MF2_LOGRAV;
S_StartSound(ball, sfx_lobhit);
}
}
//----------------------------------------------------------------------------
//
// PROC A_MaceBallImpact2
//
//----------------------------------------------------------------------------
void A_MaceBallImpact2(mobj_t *ball)
{
mobj_t *tiny;
angle_t angle;
if((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID))
{ // Landed in some sort of liquid
P_RemoveMobj(ball);
return;
}
if((ball->z != ball->floorz) || (ball->momz < 2*FRACUNIT))
{ // Explode
ball->momx = ball->momy = ball->momz = 0;
ball->flags |= MF_NOGRAVITY;
ball->flags2 &= ~(MF2_LOGRAV|MF2_FLOORBOUNCE);
}
else
{ // Bounce
ball->momz = (ball->momz*192)>>8;
P_SetMobjState(ball, ball->info->spawnstate);
tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_MACEFX3);
angle = ball->angle+ANG90;
tiny->target = ball->target;
tiny->angle = angle;
angle >>= ANGLETOFINESHIFT;
tiny->momx = (ball->momx>>1)+FixedMul(ball->momz-FRACUNIT,
finecosine[angle]);
tiny->momy = (ball->momy>>1)+FixedMul(ball->momz-FRACUNIT,
finesine[angle]);
tiny->momz = ball->momz;
P_CheckMissileSpawn(tiny);
tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_MACEFX3);
angle = ball->angle-ANG90;
tiny->target = ball->target;
tiny->angle = angle;
angle >>= ANGLETOFINESHIFT;
tiny->momx = (ball->momx>>1)+FixedMul(ball->momz-FRACUNIT,
finecosine[angle]);
tiny->momy = (ball->momy>>1)+FixedMul(ball->momz-FRACUNIT,
finesine[angle]);
tiny->momz = ball->momz;
P_CheckMissileSpawn(tiny);
}
}
//----------------------------------------------------------------------------
//
// PROC A_FireMacePL2
//
//----------------------------------------------------------------------------
void A_FireMacePL2(player_t *player, pspdef_t *psp)
{
mobj_t *mo;
player->ammo[am_mace] -=
deathmatch ? USE_MACE_AMMO_1 : USE_MACE_AMMO_2;
mo = P_SpawnPlayerMissile(player->mo, MT_MACEFX4);
if(mo)
{
mo->momx += player->mo->momx;
mo->momy += player->mo->momy;
mo->momz = 2*FRACUNIT+((player->lookdir)<<(FRACBITS-5));
if(linetarget)
{
mo->special1 = (int)linetarget;
}
}
S_StartSound(player->mo, sfx_lobsht);
}
//----------------------------------------------------------------------------
//
// PROC A_DeathBallImpact
//
//----------------------------------------------------------------------------
void A_DeathBallImpact(mobj_t *ball)
{
int i;
mobj_t *target;
angle_t angle;
boolean newAngle;
if((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID))
{ // Landed in some sort of liquid
P_RemoveMobj(ball);
return;
}
if((ball->z <= ball->floorz) && ball->momz)
{ // Bounce
newAngle = false;
target = (mobj_t *)ball->special1;
if(target)
{
if(!(target->flags&MF_SHOOTABLE))
{ // Target died
ball->special1 = 0;
}
else
{ // Seek
angle = R_PointToAngle2(ball->x, ball->y,
target->x, target->y);
newAngle = true;
}
}
else
{ // Find new target
angle = 0;
for(i = 0; i < 16; i++)
{
P_AimLineAttack(ball, angle, 10*64*FRACUNIT);
if(linetarget && ball->target != linetarget)
{
ball->special1 = (int)linetarget;
angle = R_PointToAngle2(ball->x, ball->y,
linetarget->x, linetarget->y);
newAngle = true;
break;
}
angle += ANGLE_45/2;
}
}
if(newAngle)
{
ball->angle = angle;
angle >>= ANGLETOFINESHIFT;
ball->momx = FixedMul(ball->info->speed, finecosine[angle]);
ball->momy = FixedMul(ball->info->speed, finesine[angle]);
}
P_SetMobjState(ball, ball->info->spawnstate);
S_StartSound(ball, sfx_pstop);
}
else
{ // Explode
ball->flags |= MF_NOGRAVITY;
ball->flags2 &= ~MF2_LOGRAV;
S_StartSound(ball, sfx_phohit);
}
}
//----------------------------------------------------------------------------
//
// PROC A_SpawnRippers
//
//----------------------------------------------------------------------------
void A_SpawnRippers(mobj_t *actor)
{
int i;
angle_t angle;
mobj_t *ripper;
for(i = 0; i < 8; i++)
{
ripper = P_SpawnMobj(actor->x, actor->y, actor->z, MT_RIPPER);
angle = i*ANG45;
ripper->target = actor->target;
ripper->angle = angle;
angle >>= ANGLETOFINESHIFT;
ripper->momx = FixedMul(ripper->info->speed, finecosine[angle]);
ripper->momy = FixedMul(ripper->info->speed, finesine[angle]);
P_CheckMissileSpawn(ripper);
}
}
//----------------------------------------------------------------------------
//
// PROC A_FireCrossbowPL1
//
//----------------------------------------------------------------------------
void A_FireCrossbowPL1(player_t *player, pspdef_t *psp)
{
mobj_t *pmo;
pmo = player->mo;
player->ammo[am_crossbow] -= USE_CBOW_AMMO_1;
P_SpawnPlayerMissile(pmo, MT_CRBOWFX1);
P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle-(ANG45/10));
P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle+(ANG45/10));
}
//----------------------------------------------------------------------------
//
// PROC A_FireCrossbowPL2
//
//----------------------------------------------------------------------------
void A_FireCrossbowPL2(player_t *player, pspdef_t *psp)
{
mobj_t *pmo;
pmo = player->mo;
player->ammo[am_crossbow] -=
deathmatch ? USE_CBOW_AMMO_1 : USE_CBOW_AMMO_2;
P_SpawnPlayerMissile(pmo, MT_CRBOWFX2);
P_SPMAngle(pmo, MT_CRBOWFX2, pmo->angle-(ANG45/10));
P_SPMAngle(pmo, MT_CRBOWFX2, pmo->angle+(ANG45/10));
P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle-(ANG45/5));
P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle+(ANG45/5));
}
//----------------------------------------------------------------------------
//
// PROC A_BoltSpark
//
//----------------------------------------------------------------------------
void A_BoltSpark(mobj_t *bolt)
{
mobj_t *spark;
if(P_Random() > 50)
{
spark = P_SpawnMobj(bolt->x, bolt->y, bolt->z, MT_CRBOWFX4);
spark->x += (P_Random()-P_Random())<<10;
spark->y += (P_Random()-P_Random())<<10;
}
}
//----------------------------------------------------------------------------
//
// PROC A_FireSkullRodPL1
//
//----------------------------------------------------------------------------
void A_FireSkullRodPL1(player_t *player, pspdef_t *psp)
{
mobj_t *mo;
if(player->ammo[am_skullrod] < USE_SKRD_AMMO_1)
{
return;
}
player->ammo[am_skullrod] -= USE_SKRD_AMMO_1;
mo = P_SpawnPlayerMissile(player->mo, MT_HORNRODFX1);
// Randomize the first frame
if(mo && P_Random() > 128)
{
P_SetMobjState(mo, S_HRODFX1_2);
}
}
//----------------------------------------------------------------------------
//
// PROC A_FireSkullRodPL2
//
// The special2 field holds the player number that shot the rain missile.
// The special1 field is used for the seeking routines, then as a counter
// for the sound looping.
//
//----------------------------------------------------------------------------
void A_FireSkullRodPL2(player_t *player, pspdef_t *psp)
{
player->ammo[am_skullrod] -=
deathmatch ? USE_SKRD_AMMO_1 : USE_SKRD_AMMO_2;
P_SpawnPlayerMissile(player->mo, MT_HORNRODFX2);
// Use MissileMobj instead of the return value from
// P_SpawnPlayerMissile because we need to give info to the mobj
// even if it exploded immediately.
if(netgame)
{ // Multi-player game
MissileMobj->special2 = P_GetPlayerNum(player);
}
else
{ // Always use red missiles in single player games
MissileMobj->special2 = 2;
}
if(linetarget)
{
MissileMobj->special1 = (int)linetarget;
}
S_StartSound(MissileMobj, sfx_hrnpow);
}
//----------------------------------------------------------------------------
//
// PROC A_SkullRodPL2Seek
//
//----------------------------------------------------------------------------
void A_SkullRodPL2Seek(mobj_t *actor)
{
P_SeekerMissile(actor, ANGLE_1*10, ANGLE_1*30);
}
//----------------------------------------------------------------------------
//
// PROC A_AddPlayerRain
//
//----------------------------------------------------------------------------
void A_AddPlayerRain(mobj_t *actor)
{
int playerNum;
player_t *player;
playerNum = netgame ? actor->special2 : 0;
if(!playeringame[playerNum])
{ // Player left the game
return;
}
player = &players[playerNum];
if(player->health <= 0)
{ // Player is dead
return;
}
if(player->rain1 && player->rain2)
{ // Terminate an active rain
if(player->rain1->health < player->rain2->health)
{
if(player->rain1->health > 16)
{
player->rain1->health = 16;
}
player->rain1 = NULL;
}
else
{
if(player->rain2->health > 16)
{
player->rain2->health = 16;
}
player->rain2 = NULL;
}
}
// Add rain mobj to list
if(player->rain1)
{
player->rain2 = actor;
}
else
{
player->rain1 = actor;
}
}
//----------------------------------------------------------------------------
//
// PROC A_SkullRodStorm
//
//----------------------------------------------------------------------------
void A_SkullRodStorm(mobj_t *actor)
{
fixed_t x;
fixed_t y;
mobj_t *mo;
int playerNum;
player_t *player;
if(actor->health-- == 0)
{
P_SetMobjState(actor, S_NULL);
playerNum = netgame ? actor->special2 : 0;
if(!playeringame[playerNum])
{ // Player left the game
return;
}
player = &players[playerNum];
if(player->health <= 0)
{ // Player is dead
return;
}
if(player->rain1 == actor)
{
player->rain1 = NULL;
}
else if(player->rain2 == actor)
{
player->rain2 = NULL;
}
return;
}
if(P_Random() < 25)
{ // Fudge rain frequency
return;
}
x = actor->x+((P_Random()&127)-64)*FRACUNIT;
y = actor->y+((P_Random()&127)-64)*FRACUNIT;
mo = P_SpawnMobj(x, y, ONCEILINGZ, MT_RAINPLR1+actor->special2);
mo->target = actor->target;
mo->momx = 1; // Force collision detection
mo->momz = -mo->info->speed;
mo->special2 = actor->special2; // Transfer player number
P_CheckMissileSpawn(mo);
if(!(actor->special1&31))
{
S_StartSound(actor, sfx_ramrain);
}
actor->special1++;
}
//----------------------------------------------------------------------------
//
// PROC A_RainImpact
//
//----------------------------------------------------------------------------
void A_RainImpact(mobj_t *actor)
{
if(actor->z > actor->floorz)
{
P_SetMobjState(actor, S_RAINAIRXPLR1_1+actor->special2);
}
else if(P_Random() < 40)
{
P_HitFloor(actor);
}
}
//----------------------------------------------------------------------------
//
// PROC A_HideInCeiling
//
//----------------------------------------------------------------------------
void A_HideInCeiling(mobj_t *actor)
{
actor->z = actor->ceilingz+4*FRACUNIT;
}
//----------------------------------------------------------------------------
//
// PROC A_FirePhoenixPL1
//
//----------------------------------------------------------------------------
void A_FirePhoenixPL1(player_t *player, pspdef_t *psp)
{
angle_t angle;
player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_1;
P_SpawnPlayerMissile(player->mo, MT_PHOENIXFX1);
//P_SpawnPlayerMissile(player->mo, MT_MNTRFX2);
angle = player->mo->angle+ANG180;
angle >>= ANGLETOFINESHIFT;
player->mo->momx += FixedMul(4*FRACUNIT, finecosine[angle]);
player->mo->momy += FixedMul(4*FRACUNIT, finesine[angle]);
}
//----------------------------------------------------------------------------
//
// PROC A_PhoenixPuff
//
//----------------------------------------------------------------------------
void A_PhoenixPuff(mobj_t *actor)
{
mobj_t *puff;
angle_t angle;
P_SeekerMissile(actor, ANGLE_1*5, ANGLE_1*10);
puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF);
angle = actor->angle+ANG90;
angle >>= ANGLETOFINESHIFT;
puff->momx = FixedMul(FRACUNIT*1.3, finecosine[angle]);
puff->momy = FixedMul(FRACUNIT*1.3, finesine[angle]);
puff->momz = 0;
puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF);
angle = actor->angle-ANG90;
angle >>= ANGLETOFINESHIFT;
puff->momx = FixedMul(FRACUNIT*1.3, finecosine[angle]);
puff->momy = FixedMul(FRACUNIT*1.3, finesine[angle]);
puff->momz = 0;
}
//----------------------------------------------------------------------------
//
// PROC A_InitPhoenixPL2
//
//----------------------------------------------------------------------------
void A_InitPhoenixPL2(player_t *player, pspdef_t *psp)
{
player->flamecount = FLAME_THROWER_TICS;
}
//----------------------------------------------------------------------------
//
// PROC A_FirePhoenixPL2
//
// Flame thrower effect.
//
//----------------------------------------------------------------------------
void A_FirePhoenixPL2(player_t *player, pspdef_t *psp)
{
mobj_t *mo;
mobj_t *pmo;
angle_t angle;
fixed_t x, y, z;
fixed_t slope;
if(--player->flamecount == 0)
{ // Out of flame
P_SetPsprite(player, ps_weapon, S_PHOENIXATK2_4);
player->refire = 0;
return;
}
pmo = player->mo;
angle = pmo->angle;
x = pmo->x+((P_Random()-P_Random())<<9);
y = pmo->y+((P_Random()-P_Random())<<9);
z = pmo->z+26*FRACUNIT+((player->lookdir)<<FRACBITS)/173;
if(pmo->flags2&MF2_FEETARECLIPPED)
{
z -= FOOTCLIPSIZE;
}
slope = ((player->lookdir)<<FRACBITS)/173+(FRACUNIT/10);
mo = P_SpawnMobj(x, y, z, MT_PHOENIXFX2);
mo->target = pmo;
mo->angle = angle;
mo->momx = pmo->momx+FixedMul(mo->info->speed,
finecosine[angle>>ANGLETOFINESHIFT]);
mo->momy = pmo->momy+FixedMul(mo->info->speed,
finesine[angle>>ANGLETOFINESHIFT]);
mo->momz = FixedMul(mo->info->speed, slope);
if(!player->refire || !(leveltime%38))
{
S_StartSound(player->mo, sfx_phopow);
}
P_CheckMissileSpawn(mo);
}
//----------------------------------------------------------------------------
//
// PROC A_ShutdownPhoenixPL2
//
//----------------------------------------------------------------------------
void A_ShutdownPhoenixPL2(player_t *player, pspdef_t *psp)
{
player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_2;
}
//----------------------------------------------------------------------------
//
// PROC A_FlameEnd
//
//----------------------------------------------------------------------------
void A_FlameEnd(mobj_t *actor)
{
actor->momz += 1.5*FRACUNIT;
}
//----------------------------------------------------------------------------
//
// PROC A_FloatPuff
//
//----------------------------------------------------------------------------
void A_FloatPuff(mobj_t *puff)
{
puff->momz += 1.8*FRACUNIT;
}
//---------------------------------------------------------------------------
//
// PROC A_GauntletAttack
//
//---------------------------------------------------------------------------
void A_GauntletAttack(player_t *player, pspdef_t *psp)
{
angle_t angle;
int damage;
int slope;
int randVal;
fixed_t dist;
psp->sx = ((P_Random()&3)-2)*FRACUNIT;
psp->sy = WEAPONTOP+(P_Random()&3)*FRACUNIT;
angle = player->mo->angle;
if(player->powers[pw_weaponlevel2])
{
damage = HITDICE(2);
dist = 4*MELEERANGE;
angle += (P_Random()-P_Random())<<17;
PuffType = MT_GAUNTLETPUFF2;
}
else
{
damage = HITDICE(2);
dist = MELEERANGE+1;
angle += (P_Random()-P_Random())<<18;
PuffType = MT_GAUNTLETPUFF1;
}
slope = P_AimLineAttack(player->mo, angle, dist);
P_LineAttack(player->mo, angle, dist, slope, damage);
if(!linetarget)
{
if(P_Random() > 64)
{
player->extralight = !player->extralight;
}
S_StartSound(player->mo, sfx_gntful);
return;
}
randVal = P_Random();
if(randVal < 64)
{
player->extralight = 0;
}
else if(randVal < 160)
{
player->extralight = 1;
}
else
{
player->extralight = 2;
}
if(player->powers[pw_weaponlevel2])
{
P_GiveBody(player, damage>>1);
S_StartSound(player->mo, sfx_gntpow);
}
else
{
S_StartSound(player->mo, sfx_gnthit);
}
// turn to face target
angle = R_PointToAngle2(player->mo->x, player->mo->y,
linetarget->x, linetarget->y);
if(angle-player->mo->angle > ANG180)
{
if(angle-player->mo->angle < -ANG90/20)
player->mo->angle = angle+ANG90/21;
else
player->mo->angle -= ANG90/20;
}
else
{
if(angle-player->mo->angle > ANG90/20)
player->mo->angle = angle-ANG90/21;
else
player->mo->angle += ANG90/20;
}
player->mo->flags |= MF_JUSTATTACKED;
}
void A_Light0(player_t *player, pspdef_t *psp)
{
player->extralight = 0;
}
void A_Light1(player_t *player, pspdef_t *psp)
{
player->extralight = 1;
}
void A_Light2(player_t *player, pspdef_t *psp)
{
player->extralight = 2;
}
//------------------------------------------------------------------------
//
// PROC P_SetupPsprites
//
// Called at start of level for each player
//
//------------------------------------------------------------------------
void P_SetupPsprites(player_t *player)
{
int i;
// Remove all psprites
for(i = 0; i < NUMPSPRITES; i++)
{
player->psprites[i].state = NULL;
}
// Spawn the ready weapon
player->pendingweapon = player->readyweapon;
P_BringUpWeapon(player);
}
//------------------------------------------------------------------------
//
// PROC P_MovePsprites
//
// Called every tic by player thinking routine
//
//------------------------------------------------------------------------
void P_MovePsprites(player_t *player)
{
int i;
pspdef_t *psp;
state_t *state;
psp = &player->psprites[0];
for(i = 0; i < NUMPSPRITES; i++, psp++)
{
if((state = psp->state) != 0) // a null state means not active
{
// drop tic count and possibly change state
if(psp->tics != -1) // a -1 tic count never changes
{
psp->tics--;
if(!psp->tics)
{
P_SetPsprite(player, i, psp->state->nextstate);
}
}
}
}
player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx;
player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy;
}