1870 lines
44 KiB
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;
|
||
|
}
|