djcev.com

//

Git Repos / fte_dogmode / qc / monsters / playerclient.qc

Last update to this file was on 2024-11-20 at 23:54.

Show playerclient.qc

//==============================================================================
// client / player
//==============================================================================

//======================================================================
// constants
//======================================================================

#ifdef SSQC
const float PLAYER_HEALTH = 100; // id1 100
const float PLAYER_HEALTH_CORPSE = 30;

const vector PLAYER_HEAD_MINS = '-9.67 -12.38 -2.1';
const vector PLAYER_HEAD_MAXS = '11.49 50.7 30';
const vector PLAYER_CORPSE_C_MINS = '-50.28 -23.55 -49.85';
const vector PLAYER_CORPSE_C_MAXS = '30.66 14.49 30';
const vector PLAYER_CORPSE_E_MINS = '-38.72 -5.83 -50.45';
const vector PLAYER_CORPSE_E_MAXS = '28.73 33.85 30';
const vector PLAYER_CORPSE_AX_MINS = '-38.72 -5.83 -50.45';
const vector PLAYER_CORPSE_AX_MAXS = '28.73 33.85 30';
#endif

#ifdef CSQC
const float PLAYER_CROUCH_SMOOTH = 0.1f;
#endif

#if defined(CSQC) || defined(SSQC)
enumflags
{
PLAYER_NET_FRAME, // frame has changed
PLAYER_NET_MODEL, // model has changed
PLAYER_NET_ORIGIN, // origin has changed
PLAYER_NET_SIZE, // size has changed (mins, maxs)
PLAYER_NET_ANGLES, // player angles have changed
PLAYER_NET_VELOCITY, // velocity has changed
PLAYER_NET_FLAGS, // .flags & .pm_flags
PLAYER_NET_TIMERS, // .pm_timer
PLAYER_NET_EFFECTS, // .sveffects has changed
PLAYER_NET_SOLID, // .solid and/or .movetype have changed
PLAYER_NET_ITEMS, // .items (& others) have changed
PLAYER_NET_PUNCHANGLE // .punchangle has changed
};
#endif

//======================================================================
// globals
//======================================================================

#ifdef CSQC
float view_bob; // head bobbing -- CEV
float view_bob_old;
float view_crouch; // view smoothing for crouching -- CEV
float view_crouch_old;
float view_crouch_finished;
float view_punch1; // punchangle_x -- CEV
float view_punch2;
float view_punch_time;
float view_step; // view smoothing for steps -- CEV
float view_step_adjust;
float view_step_disable;
float view_step_oldz;
float view_step_time;
#endif

#ifdef SSQC
float modelindex_eyes;
float modelindex_player;
#endif

//======================================================================
// fields
//======================================================================

#ifdef SSQC
.float axhitme;
.float fly_sound;
.float jump_flag; // player jump flag
.float reset_items; // dumptruck_ds
#endif

#ifdef SSQC
.float air_finished; // when time > air_finished, drown
.float attack_finished;
.float pain_finished;
.float invincible_finished;
.float invisible_finished;
.float super_damage_finished;
.float radsuit_finished;
#endif

#ifdef SSQC
.float damage_time;
.float invincible_time, invincible_sound;
.float invisible_time, invisible_sound;
.float super_time, super_sound;
.float rad_time;
.float megahealth_rottime; // dumptruck_ds
#endif

#ifdef SSQC
.float step_time; // CEV

// set to time+0.2 whenever a client fires a weapon or takes damage.
// Used to alert monsters that otherwise would let the player go
.float show_hostile;

.string deathtype; // keeps track of how the player died
#endif

#ifdef SSQC
// DP_INPUTBUTTONS (in qw we set 1 to equal 3 to match zquake/fuhquake/mvdsv)
.float button3;
.float button4;
.float button5;
.float button6;
.float button7;
.float button8;
#endif

#ifdef CSQC
.float commandframe;
#endif

//======================================================================
// forward declarations
//======================================================================

// player
#ifdef CSQC
// PLAYER_PREDICTION_SAVE(e)
// PLAYER_PREDICTION_RESET(e)
// PLAYER_PREDICTION(e, endframe)
// PLAYER_VIEW_BOB(e)
// PLAYER_VIEW_CROUCH(e)
// PLAYER_VIEW_PUNCHANGLE()
// PLAYER_VIEW_ROLL(e)
// PLAYER_VIEW_STEPS(e)
void(float isnew) player_netreceive;
float() player_predraw;
static void() player_remove;
void(entity e) player_prediction_preframe;
void(entity e) player_prediction_postframe;
#endif
#ifdef SSQC
float(entity to, float netflags) player_netsend;
void() player_impulse_cheat; // impulse commands
void() player_impulse_quadcheat;
void() player_impulse_serverflags;
void() player_impulse_changeweapon;
void() player_impulse_cycleweapon;
void() player_impulse_cycleweaponreverse;
void() player_impulse;
void() player_superdamage_sound;
void() player_set_current_ammo; // ammo, weapon firing, attacks
float() player_best_weapon;
float() player_check_no_ammo;
void() player_fire_axe;
void() player_fire_shotgun;
void() player_fire_supershotgun;
void(float offset) player_fire_spikes;
void() player_fire_superspikes;
void() player_fire_grenade;
void() player_fire_tribolt;
void() player_fire_rocket;
void() player_fire_lightning;
void() player_attack;
void() player_set_suicide_frame; // pain, damage, death
void() player_pain_sound;
void() player_death_sound;
void() player_dead;
void() player_footstep; // thinking & animation frames
void() player_stand;
void() player_axstand;
void(void() axthink) player_run;
void(void() runthink) player_axrun;
void() pl_axstnd1; void() pl_axstnd2; void() pl_axstnd3; void() pl_axstnd4;
void() pl_axstnd5; void() pl_axstnd6; void() pl_axstnd7; void() pl_axstnd8;
void() pl_axstnd9; void() pl_axstnd10; void() pl_axstnd11; void() pl_axstnd12;
void() pl_stand1; void() pl_stand2; void() pl_stand3; void() pl_stand4;
void() pl_stand5;
void() pl_run1; void() pl_run2; void() pl_run3; void() pl_run4;
void() pl_run5; void() pl_run6;
void() pl_shot1; void() pl_shot2; void() pl_shot3; void() pl_shot4;
void() pl_shot5; void() pl_shot6;
void() pl_axe1; void() pl_axe2; void() pl_axe3; void() pl_axe4;
void() pl_axeb1; void() pl_axeb2; void() pl_axeb3; void() pl_axeb4;
void() pl_axec1; void() pl_axec2; void() pl_axec3; void() pl_axec4;
void() pl_axed1; void() pl_axed2; void() pl_axed3; void() pl_axed4;
void() pl_nail1; void() pl_nail2;
void() pl_light1; void() pl_light2;
void() pl_rocket1; void() pl_rocket2; void() pl_rocket3;
void() pl_rocket4; void() pl_rocket5; void() pl_rocket6;
void() pl_pain1; void() pl_pain2; void() pl_pain3;
void() pl_pain4; void() pl_pain5; void() pl_pain6;
void() pl_axpain1; void() pl_axpain2; void() pl_axpain3;
void() pl_axpain4; void() pl_axpain5; void() pl_axpain6;
void() pl_diea1; void() pl_diea2; void() pl_diea3; void() pl_diea4;
void() pl_diea5; void() pl_diea6; void() pl_diea7; void() pl_diea8;
void() pl_diea9; void() pl_diea10; void() pl_diea11;
void() pl_dieb1; void() pl_dieb2; void() pl_dieb3; void() pl_dieb4;
void() pl_dieb5; void() pl_dieb6; void() pl_dieb7; void() pl_dieb8;
void() pl_dieb9;
void() pl_diec1; void() pl_diec2; void() pl_diec3; void() pl_diec4;
void() pl_diec5; void() pl_diec6; void() pl_diec7; void() pl_diec8;
void() pl_diec9; void() pl_diec10; void() pl_diec11; void() pl_diec12;
void() pl_diec13; void() pl_diec14; void() pl_diec15;
void() pl_died1; void() pl_died2; void() pl_died3; void() pl_died4;
void() pl_died5; void() pl_died6; void() pl_died7; void() pl_died8;
void() pl_died9;
void() pl_diee1; void() pl_diee2; void() pl_diee3; void() pl_diee4;
void() pl_diee5; void() pl_diee6; void() pl_diee7; void() pl_diee8;
void() pl_diee9;
void() player_death_think;
void() player_prethink_watermove;
void() player_prethink;
void() player_postthink_powerups;
void() player_postthink;
void(entity attacker, float damage) player_pain;
void(vector dir) player_destroy_gib;
void(vector dir) player_destroy;
#endif
#if defined(CSQC) || defined(SSQC)
void() player_touch;
#endif
#ifdef SSQC
entity() player_init_selectspawnpoint; // initialization
void() player_init_level_parms;
void() player_respawn;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) player_init;
#endif
#ifdef SSQC
strip void() player;
#endif

#ifdef SSQC
// gib_head_player
void(entity act, vector dir, float dmg) throw_gib_head_player;
void(entity e) gib_head_player_init;
void() gib_head_player;
#endif

#ifdef SSQC
// player_dead_axe
void() player_dead_axe;
#endif

#ifdef SSQC
// player_dead_face_down
void() player_dead_face_down;
#endif

#ifdef SSQC
// player_dead_on_side
void() player_dead_on_side;
#endif

//======================================================================
// frame macros
//======================================================================

$cd id1/models/player_4
$origin 0 -6 24
$base base
$skin skin

$frame axrun1 axrun2 axrun3 axrun4 axrun5 axrun6

$frame rockrun1 rockrun2 rockrun3 rockrun4 rockrun5 rockrun6

$frame stand1 stand2 stand3 stand4 stand5

$frame axstnd1 axstnd2 axstnd3 axstnd4 axstnd5 axstnd6
$frame axstnd7 axstnd8 axstnd9 axstnd10 axstnd11 axstnd12

$frame axpain1 axpain2 axpain3 axpain4 axpain5 axpain6

$frame pain1 pain2 pain3 pain4 pain5 pain6

$frame axdeth1 axdeth2 axdeth3 axdeth4 axdeth5 axdeth6
$frame axdeth7 axdeth8 axdeth9

$frame deatha1 deatha2 deatha3 deatha4 deatha5 deatha6 deatha7 deatha8
$frame deatha9 deatha10 deatha11
$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8
$frame deathb9
$frame deathc1 deathc2 deathc3 deathc4 deathc5 deathc6 deathc7 deathc8
$frame deathc9 deathc10 deathc11 deathc12 deathc13 deathc14 deathc15
$frame deathd1 deathd2 deathd3 deathd4 deathd5 deathd6 deathd7
$frame deathd8 deathd9
$frame deathe1 deathe2 deathe3 deathe4 deathe5 deathe6 deathe7
$frame deathe8 deathe9

$frame nailatt1 nailatt2

$frame light1 light2

$frame rockatt1 rockatt2 rockatt3 rockatt4 rockatt5 rockatt6

$frame shotatt1 shotatt2 shotatt3 shotatt4 shotatt5 shotatt6

$frame axatt1 axatt2 axatt3 axatt4 axatt5 axatt6
$frame axattb1 axattb2 axattb3 axattb4 axattb5 axattb6
$frame axattc1 axattc2 axattc3 axattc4 axattc5 axattc6
$frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6

//------------------------------------------------------------------------------

//----------------------------------------------------------------------
// Player Class: spawn functions, animation, client handling, etc. -- CEV
//----------------------------------------------------------------------
// class player: entity
// {
//==============================================================
// Player/Client networking
//==============================================================

#ifdef CSQC
//--------------------------------------------------------------
#define PLAYER_PREDICTION_SAVE(e) \
{ \
e.origin_net = e.origin; \
e.velocity_net = e.velocity; \
e.angles_net = e.angles; \
e.flags_net = e.flags; \
e.pm_flags_net = e.pm_flags; \
e.pm_timer_net = e.pm_timer; \
}

//--------------------------------------------------------------
// was Pred_ResetPlayerPrediction in CSQCTest cs/prediction.qc
//--------------------------------------------------------------
#define PLAYER_PREDICTION_RESET(e) \
{ \
e.origin = e.origin_net; \
e.velocity = e.velocity_net; \
e.angles = e.angles_net; \
e.flags = e.flags_net; \
e.pm_flags = e.pm_flags_net; \
e.pm_timer = e.pm_timer_net; \
/* setsize (e, e.mins, e.maxs); */ \
if (e.pm_flags & PMF_CROUCHED) \
setsize (e, PM_CROUCH_MIN, PM_CROUCH_MAX); \
else \
setsize (e, PM_STAND_MIN, PM_STAND_MAX); \
if (e.commandframe < clientcommandframe - 128) \
/* avoid an infinite loop */ \
e.commandframe = clientcommandframe - 128; \
}

//--------------------------------------------------------------
// was Pred_RunMovement in CSQCTest cs/prediction.qc
//--------------------------------------------------------------
#define PLAYER_PREDICTION(e, endframe) \
{ \
if (servercommandframe >= e.commandframe + 63) \
{ \
/* we're meant to be updating the player faster than
* this. hopefully its just that we're throttled... */ \
/* you can comment out this block and the player will
* continue to be predicted locally. But its best to
* freeze them */ \
/* dprint ("player_prediction: slow update\n"); */ \
e.commandframe = servercommandframe - 63; \
} \
else \
{ \
if (getstatf(STAT_HEALTH) <= 0) \
{ \
/* dead, so don't run prediction. :D */ \
e.commandframe = clientcommandframe; \
if (getinputstate(e.commandframe - 1) == FALSE) \
{ \
dprint ("PLAYER_PREDICTION: noop?\n"); \
/* TODO CEV no-op ? */ \
} \
} \
else \
{ \
/* 'self' needs to be the entity moving for
* the macros below to work -- CEV */ \
local entity oself = self; \
self = e; \
/* update view_pl -- CEV */ \
if (self.entnum == player_localentnum) { \
if (self != view_pl) \
{ \
view_pl = self; \
} } \
for (float lc = e.commandframe + 1; \
lc <= endframe; lc++) \
{ \
local float f = getinputstate (lc); \
if (f == FALSE) \
{ \
/* no input from client */ \
break; \
} \
if (input_timelength <= 0) \
{ \
break; \
} \
/*
if (i == clientcommandframe)
CSQC_Input_Frame ();
*/ \
/* do the move; see pmove.qc -- CEV */ \
PM_MOVE_PRE () \
PM_MOVE_MOVETYPES () \
PM_MOVE_POST () \
/* don't do step smoothing when flagged
* not to -- CEV */ \
if (self.pm_flags & PMF_ONMOVINGENT) { \
if (view_step_disable == FALSE) \
{ \
view_step_disable = TRUE; \
} } \
else if (view_step_disable) \
{ \
view_step_disable = FALSE; \
} \
} \
/* restore 'self' -- CEV */ \
self = oself; \
/* add anything that was applied after
* (for low packet rate protocols) */ \
/* input_angles = view_angles; */ \
} \
} \
} \

//--------------------------------------------------------------
// PLAYER_VIEW_BOB -- view bob (based on Ironwail's V_CalcBob) -- CEV
//--------------------------------------------------------------
#define PLAYER_VIEW_BOB(e) \
{ \
local float cl_bob = autocvar (cl_bob, 0.02); \
local float cl_bobcycle = autocvar (cl_bobcycle, 0.6); \
if (cl_bob && cl_bobcycle) \
{ \
local float cl_bobup = autocvar (cl_bobup, 0.5); \
local float C = 0; \
C = time - rint((time / cl_bobcycle)) * cl_bobcycle; \
C /= cl_bobcycle; \
if (C < cl_bobup) \
C = M_PI * C / cl_bobup; \
else \
C = M_PI + M_PI * (C - cl_bobup) / \
(1.0 - cl_bobup); \
/* bob is proportional to velocity in the xy plane
* (don't count Z, or jumping messes it up) */ \
view_bob = vlen ([self.velocity_x, self.velocity_y]); \
view_bob *= cl_bob; \
view_bob = view_bob * 0.3 + view_bob * 0.7 * sin(C); \
view_bob = bound (-7, view_bob, 4); \
/* only bob when onground and try to limit abrupt
* view changes when landing -- CEV */ \
/* this is pretty tortured -- CEV */ \
if (e.pm_flags & PMF_ONGROUND && \
!(e.pm_flags & PMF_CROUCHSLIDE)) \
{ \
if (view_bob_old) \
{ \
if (fabs(view_bob) - \
fabs(view_bob_old) < cl_bob) \
{ \
view_bob_old = 0; \
} \
else \
{ \
view_bob = view_bob_old; \
} \
} \
} \
else \
{ \
if (view_bob_old) \
{ \
view_bob_old *= 0.9f; \
if (view_bob_old > 0) \
view_bob_old = max (PM_FLMIN, \
view_bob_old); \
else \
view_bob_old = min (-PM_FLMIN, \
view_bob_old); \
view_bob = view_bob_old; \
} \
else \
{ \
view_bob_old = view_bob; \
} \
} \
/*
dprint (sprintf("PLAYER_VIEW_BOB: view_bob "
"%g, old %g\n", view_bob, view_bob_old));
*/ \
} \
else \
{ \
if (view_bob) \
view_bob = 0; \
if (view_bob_old) \
view_bob_old = 0; \
} \
view_origin.z += view_bob; \
}

//--------------------------------------------------------------
// PLAYER_VIEW_CROUCH -- smooth crouching -- CEV
//--------------------------------------------------------------
#define PLAYER_VIEW_CROUCH(e) \
{ \
if (view_crouch_finished > time) \
{ \
if (view_crouch_old != e.view_ofs.z) \
{ \
local float zc; \
zc = 1 - (view_crouch_finished - time) / \
PLAYER_CROUCH_SMOOTH; \
view_crouch = lerp_hermite (view_crouch_old, \
e.view_ofs.z, zc); \
} \
} \
else \
{ \
if (view_crouch_old != e.view_ofs.z) \
view_crouch_old = e.view_ofs.z; \
view_crouch = e.view_ofs.z; \
} \
view_origin.z += view_crouch; \
}

//--------------------------------------------------------------
// PLAYER_VIEW_PUNCHANGLE -- punchangle code from Ironwail -- CEV
//--------------------------------------------------------------
#define PLAYER_VIEW_PUNCHANGLE() \
{ \
/* punchangle code from Ironwail -- CEV */ \
if (autocvar(v_gunkick, 1)) { \
if (view_punch2 || view_punch1) \
{ \
view_angles.x += view_punch2 + bound \
(0, (time - view_punch_time) / 0.1f, 1) * \
(view_punch1 - view_punch2); \
} } \
}

//--------------------------------------------------------------
// PLAYER_VIEW_ROLL -- sideways view roll code from Ironwail -- CEV
//--------------------------------------------------------------
#define PLAYER_VIEW_ROLL(e) \
{ \
local float view_rollspeed = autocvar (cl_rollspeed, 200); \
local float view_rollangle = autocvar (cl_rollangle, 2.0f); \
if (view_rollspeed && view_rollangle) \
{ \
local float view_roll = e.velocity * v_right; \
local float view_sign = view_roll < 0 ? -1 : 1; \
view_roll = fabs (view_roll); \
if (view_roll < view_rollspeed) \
view_roll *= view_rollangle / view_rollspeed; \
else \
view_roll = view_rollangle; \
view_angles.z += view_roll * view_sign; \
} \
}

//--------------------------------------------------------------
// PLAYER_VIEW_STEPS -- step smoothing, based on CSQCTest -- CEV
//--------------------------------------------------------------
#define PLAYER_VIEW_STEPS(e) \
{ \
local float view_step_diff = e.origin.z - view_step_oldz; \
if (view_step_disable == FALSE) { \
if (e.pm_flags & PMF_ONGROUND) { \
if (view_step_diff >= 4 && view_step_diff <= PM_STEPHEIGHT) \
{ \
if (e.speed) \
view_step_adjust = e.speed * 0.018; \
else \
view_step_adjust = PM_MAXSPEED * 0.018; \
view_step_adjust = bound (4, view_step_adjust, 16); \
/* evaluate out the remaining old step */ \
if (view_step_time - time > 0) \
view_step = (view_step_time - time) * \
view_step_adjust * view_step; \
else \
view_step = 0; \
view_step += view_step_diff; \
view_step_time = time + (1 / view_step_adjust); \
/*
dprint (sprintf("player_prediction_preframe: "
"pm_step %g, step %g, step_adjust %g\n",
view_pm_step, view_step, view_step_adjust));
*/ \
} } } \
view_step_oldz = e.origin.z; \
/* now do the adjustment -- CEV */ \
if (view_step_time - time > 0) \
view_origin.z -= (view_step_time - time) * \
view_step_adjust * view_step; \
}

//--------------------------------------------------------------
// called from CSQC_Ent_Update for CT_PLAYER entities
//--------------------------------------------------------------
void(float isnew) player_netreceive =
{
local float newframe = 0;
local float newmoveflags = 0;
local float netflags = ReadFloat ();

if (netflags & PLAYER_NET_FRAME)
newframe = ReadByte ();

if (netflags & PLAYER_NET_MODEL)
self.modelindex = ReadShort ();

if (netflags & PLAYER_NET_ORIGIN)
{
self.origin_x = ReadCoord ();
self.origin_y = ReadCoord ();
self.origin_z = ReadCoord ();
}

// we can safely infer PLAYER_NET_SIZE from .pm_flags;
// if it's necessary to transmit size (mins & maxs) in
// the future we'd do so here -- CEV

if (netflags & PLAYER_NET_ANGLES)
{
self.angles_x = ReadAngle ();
self.angles_y = ReadAngle ();
self.angles_z = ReadAngle ();
}

if (netflags & PLAYER_NET_VELOCITY)
{
self.velocity_x = ReadShort() * 0.125;
self.velocity_y = ReadShort() * 0.125;
self.velocity_z = ReadShort() * 0.125;
self.speed = vlen ([self.velocity_x,self.velocity_y,0]);
}

if (netflags & PLAYER_NET_FLAGS)
{
self.flags = ReadFloat ();
newmoveflags = ReadFloat ();
}
else
{
newmoveflags = self.pm_flags;
}

if (netflags & PLAYER_NET_TIMERS)
self.pm_timer = ReadFloat ();

if (netflags & PLAYER_NET_EFFECTS)
self.sveffects = ReadByte ();

if (netflags & PLAYER_NET_SOLID)
{
self.solid = ReadByte ();
self.movetype = ReadByte ();
}

if (netflags & PLAYER_NET_ITEMS)
self.items = ReadFloat ();

if (netflags & PLAYER_NET_PUNCHANGLE)
{
self.punchangle_x = ReadShort ();

// punchangle code from Ironwail -- CEV
if (self.entnum == player_localentnum) {
if (view_punch1 != self.punchangle_x)
{
view_punch2 = view_punch1;
view_punch1 = self.punchangle_x;
view_punch_time = time;
} }
}

if (isnew && !(self.predraw))
{
dprint ("player_netreceive: init player...\n");
self.pm_flags = newmoveflags;
player_init (self);
}
else if (self.pm_flags != newmoveflags)
{
if (newmoveflags & PMF_CROUCHED &&
(!(self.pm_flags & PMF_CROUCHED)))
{
self.pm_flags = newmoveflags;
PM_CrouchStart ();
}
else if ((!(newmoveflags & PMF_CROUCHED)) &&
self.pm_flags & PMF_CROUCHED)
{
self.pm_flags = newmoveflags;
PM_CrouchStop ();
}
else
{
if (newmoveflags & PMF_CROUCHED)
setsize (self, PM_CROUCH_MIN,
PM_CROUCH_MAX);
else
setsize (self, PM_STAND_MIN,
PM_STAND_MAX);
self.pm_flags = newmoveflags;
}
}
else
{
self.pm_flags = newmoveflags;
// Make sure mins & maxs match the server -- CEV
if (self.pm_flags & PMF_CROUCHED)
setsize (self, PM_CROUCH_MIN, PM_CROUCH_MAX);
else
setsize (self, PM_STAND_MIN, PM_STAND_MAX);
}

if (self.entnum == player_localentnum)
{
view_pl = self;
self.commandframe = servercommandframe;
PLAYER_PREDICTION_SAVE (self)
}

// TODO CEV movement interpolation for other players

if (newframe != self.frame || isnew)
{
self.frame2 = self.frame;
self.lerptime = time;
self.frame = newframe;
}

self.oldframe = self.frame;
};

//--------------------------------------------------------------
// Based on pieces of Pred_UpdateLocalMovement from CSQCTest
//--------------------------------------------------------------
float() player_predraw =
{
// player visual effects; this might need to be some place
// other than predraw for multiplayer support -- CEV
if (self.sveffects & EF_MUZZLEFLASH)
{
self.sveffects &= ~EF_MUZZLEFLASH;
makevectors ([0, self.angles_y, 0]);
pointparticles (particleeffectnum("te_muzzleflash"),
self.origin, v_forward, 1);
}

if (self.sveffects & EF_DIMLIGHT)
{
local vector col;
makevectors (self.v_angle);

// rely on sitems here instead of transmitting .items
// through SendEntity; might reduce net traffic? -- CEV
// sitems set in cl_hud already -- CEV
// sitems = getstatf (STAT_ITEMS, 0, 23);

// quad + pent, pent, quad, normal -- CEV
if (sitems & IT_INVULNERABILITY)
if (sitems & IT_QUAD)
col = '0.5 0.3 0.4';
else
col = '0.4 0 0';
else if (sitems & IT_QUAD)
col = '0.05 0.05 0.94';
else
col = '0.5 0.5 0.2';

// cubemap orientation is read from v_forward etc.
dynamiclight_add (self.origin, 200, col, 0, "",
PFLAGS_NOSHADOW);
}

if (self.lerptime)
self.lerpfrac = 1 - (time - self.lerptime) * 10;

if (self.entnum != player_localentnum)
self.renderflags = 0;
else
self.renderflags |= RF_EXTERNALMODEL;

addentity (self);
return PREDRAW_NEXT;
};

//--------------------------------------------------------------
static void() player_remove =
{
if (view_pl == self)
view_pl = world;

setmodel (self, "");
self.oldskin = "";
self.predraw = __NULL__;
};

//--------------------------------------------------------------
void(entity e) player_prediction_preframe =
{
if (serverkeyfloat(SERVERKEY_PAUSESTATE))
return;

if (intermission == TRUE)
{
view_origin = e.origin;
return;
}

// PLAYER_PREDICTION_SAVE (e)
PLAYER_PREDICTION (e, clientcommandframe)

view_origin = e.origin;

// view_origin: head bob, crouch smoothing, steps -- CEV
PLAYER_VIEW_BOB (e)
PLAYER_VIEW_CROUCH (e)
PLAYER_VIEW_STEPS (e)

// view_angles: punchangle, sideways view roll -- CEV
makevectors (view_angles);
PLAYER_VIEW_PUNCHANGLE ()
PLAYER_VIEW_ROLL (e)
};

//--------------------------------------------------------------
void(entity e) player_prediction_postframe =
{
PLAYER_PREDICTION_RESET (e)
setsize (e, e.mins, e.maxs);
setorigin (e, e.origin);
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
// SendEntity -- transmit updates from server to client -- CEV
//--------------------------------------------------------------
float(entity to, float netflags) player_netsend =
{
WriteShort (MSG_ENTITY, self.classtype);
WriteFloat (MSG_ENTITY, netflags);

if (netflags & PLAYER_NET_FRAME)
WriteByte (MSG_ENTITY, self.frame);

if (netflags & PLAYER_NET_MODEL)
WriteShort (MSG_ENTITY, self.modelindex);

if (netflags & PLAYER_NET_ORIGIN)
{
WriteCoord (MSG_ENTITY, self.origin_x);
WriteCoord (MSG_ENTITY, self.origin_y);
WriteCoord (MSG_ENTITY, self.origin_z);
}

// we can safely infer PLAYER_NET_SIZE from .pm_flags;
// if it's necessary to transmit size (mins & maxs) in
// the future we'd do so here -- CEV
// if (netflags & PLAYER_NET_SIZE)

if (netflags & PLAYER_NET_ANGLES)
{
WriteAngle (MSG_ENTITY, self.angles_x);
WriteAngle (MSG_ENTITY, self.angles_y);
WriteAngle (MSG_ENTITY, self.angles_z);
}

if (netflags & PLAYER_NET_VELOCITY)
{
WriteShort (MSG_ENTITY, floor(self.velocity_x * 8));
WriteShort (MSG_ENTITY, floor(self.velocity_y * 8));
WriteShort (MSG_ENTITY, floor(self.velocity_z * 8));
}

if (netflags & PLAYER_NET_FLAGS)
{
WriteFloat (MSG_ENTITY, self.flags);
WriteFloat (MSG_ENTITY, self.pm_flags);
}

if (netflags & PLAYER_NET_TIMERS)
WriteFloat (MSG_ENTITY, self.pm_timer);

if (netflags & PLAYER_NET_EFFECTS)
WriteByte (MSG_ENTITY, self.sveffects);

if (netflags & PLAYER_NET_SOLID)
{
WriteByte (MSG_ENTITY, self.solid);
WriteByte (MSG_ENTITY, self.movetype);
}

if (netflags & PLAYER_NET_ITEMS)
WriteFloat (MSG_ENTITY, self.items);

if (netflags & PLAYER_NET_PUNCHANGLE)
{
WriteShort (MSG_ENTITY, self.punchangle_x);
self.punchangle_x = 0;
}

// only muzzleflash once, should be cleared elsewhere -- CEV
if (self.sveffects & EF_MUZZLEFLASH)
self.sveffects &= ~EF_MUZZLEFLASH;

return TRUE;
};

//==============================================================
// Client Input Handling
//==============================================================

//--------------------------------------------------------------
// CheatCommand
//--------------------------------------------------------------
void() player_impulse_cheat =
{
// 1998-07-29 Cheats coop fix by Maddes start
// if (deathmatch || coop)
if (deathmatch)
// 1998-07-29 Cheats coop fix by Maddes end
return;

self.ammo_cells = 200;
self.ammo_nails = 200;
self.ammo_rockets = 100;
self.ammo_shells = 100;
self.items = self.items | IT_AXE | IT_SHOTGUN |
IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN |
IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING;

// support for item_key_custom -- iw
base_item_key_giveallkeys (self);

self.weapon = IT_ROCKET_LAUNCHER;
self.impulse = 0;
player_set_current_ammo ();
};

//--------------------------------------------------------------
void() player_impulse_quadcheat =
{
// 1998-07-29 Cheats coop fix by Maddes start
// if (deathmatch || coop)
if (deathmatch)
// 1998-07-29 Cheats coop fix by Maddes end
return;

self.super_time = 1;
self.super_damage_finished = time + 30;
self.items = self.items | IT_QUAD;
dprint ("player::quad_cheat: quad damage\n");
};

//--------------------------------------------------------------
// ServerflagsCommand -- Just for development
//--------------------------------------------------------------
void() player_impulse_serverflags =
{
// 1998-07-29 Cheats coop fix by Maddes start
if (deathmatch)
return;
// 1998-07-29 Cheats coop fix by Maddes end

serverflags = serverflags * 2 + 1;
};

//--------------------------------------------------------------
// ChangeWeaponCommand -- was W_ChangeWeapon
//--------------------------------------------------------------
void() player_impulse_changeweapon =
{
local float it, haveammo, fl;

// assign fl to silence a warning -- CEV
fl = IT_AXE;
it = self.items;
haveammo = TRUE;

switch (self.impulse)
{
case 1:
fl = IT_AXE;
break;
case 2:
fl = IT_SHOTGUN;
if (self.ammo_shells < 1)
haveammo = FALSE;
break;
case 3:
fl = IT_SUPER_SHOTGUN;
if (self.ammo_shells < 2)
haveammo = FALSE;
break;
case 4:
fl = IT_NAILGUN;
if (self.ammo_nails < 1)
haveammo = FALSE;
break;
case 5:
fl = IT_SUPER_NAILGUN;
if (self.ammo_nails < 2)
haveammo = FALSE;
break;
case 6:
fl = IT_GRENADE_LAUNCHER;
if (self.ammo_rockets < 1)
haveammo = FALSE;
break;
case 7:
fl = IT_ROCKET_LAUNCHER;
if (self.ammo_rockets < 1)
haveammo = FALSE;
break;
case 8:
fl = IT_LIGHTNING;
if (self.ammo_cells < 1)
haveammo = FALSE;
break;
default:
dprint (sprintf("player_impulse_changeweapon: "
"WARNING bad impulse: %f\n",
self.impulse));
return;
}

self.impulse = 0;

if (!(self.items & fl))
{
// don't have the weapon or the ammo
sprint (self, "no weapon.\n");
return;
}

if (haveammo == FALSE)
{
// don't have the ammo
sprint (self, "not enough ammo.\n");
return;
}

// set weapon, set ammo
self.weapon = fl;
player_set_current_ammo ();
};

//--------------------------------------------------------------
// CycleWeaponCommand -- Go to the next weapon with ammo
//--------------------------------------------------------------
void() player_impulse_cycleweapon =
{
local float haveammo;

self.impulse = 0;

while (1)
{
haveammo = TRUE;

if (self.weapon == IT_LIGHTNING)
{
self.weapon = IT_AXE;
}
else if (self.weapon == IT_AXE)
{
self.weapon = IT_SHOTGUN;
if (self.ammo_shells < 1)
haveammo = FALSE;
}
else if (self.weapon == IT_SHOTGUN)
{
self.weapon = IT_SUPER_SHOTGUN;
if (self.ammo_shells < 2)
haveammo = FALSE;
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
self.weapon = IT_NAILGUN;
if (self.ammo_nails < 1)
haveammo = FALSE;
}
else if (self.weapon == IT_NAILGUN)
{
self.weapon = IT_SUPER_NAILGUN;
if (self.ammo_nails < 2)
haveammo = FALSE;
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
self.weapon = IT_GRENADE_LAUNCHER;
if (self.ammo_rockets < 1)
haveammo = FALSE;
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
self.weapon = IT_ROCKET_LAUNCHER;
if (self.ammo_rockets < 1)
haveammo = FALSE;
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
self.weapon = IT_LIGHTNING;
if (self.ammo_cells < 1)
haveammo = FALSE;
}

if ((self.items & self.weapon) && haveammo == TRUE)
{
player_set_current_ammo ();
return;
}
}
};

//--------------------------------------------------------------
// CycleWeaponReverseCommand -- Go to the prev weapon with ammo
//--------------------------------------------------------------
void() player_impulse_cycleweaponreverse =
{
local float haveammo;

self.impulse = 0;

while (1)
{
haveammo = TRUE;

if (self.weapon == IT_LIGHTNING)
{
self.weapon = IT_ROCKET_LAUNCHER;
if (self.ammo_rockets < 1)
haveammo = FALSE;
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
self.weapon = IT_GRENADE_LAUNCHER;
if (self.ammo_rockets < 1)
haveammo = FALSE;
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
self.weapon = IT_SUPER_NAILGUN;
if (self.ammo_nails < 2)
haveammo = FALSE;
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
self.weapon = IT_NAILGUN;
if (self.ammo_nails < 1)
haveammo = FALSE;
}
else if (self.weapon == IT_NAILGUN)
{
self.weapon = IT_SUPER_SHOTGUN;
if (self.ammo_shells < 2)
haveammo = FALSE;
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
self.weapon = IT_SHOTGUN;
if (self.ammo_shells < 1)
haveammo = FALSE;
}
else if (self.weapon == IT_SHOTGUN)
{
self.weapon = IT_AXE;
}
else if (self.weapon == IT_AXE)
{
self.weapon = IT_LIGHTNING;
if (self.ammo_cells < 1)
haveammo = FALSE;
}

if ((self.items & self.weapon) && haveammo == TRUE)
{
player_set_current_ammo ();
return;
}
}
};

//--------------------------------------------------------------
// ImpulseCommands
//--------------------------------------------------------------
void() player_impulse =
{
switch (self.impulse)
{
case 1..8:
player_impulse_changeweapon ();
return;
case 9:
player_impulse_cheat ();
break;
case 10:
player_impulse_cycleweapon ();
break;
case 11:
player_impulse_serverflags ();
break;
case 12:
player_impulse_cycleweaponreverse ();
break;
case 100:
// dumptruck_ds version inspired by Copper
sprint (self, version);
break;
case 255:
player_impulse_quadcheat ();
break;
default:
dprint (sprintf("player_impulse: "
"unknown impulse %g\n", self.impulse));
break;
}

self.impulse = 0;
};

//==============================================================
// Client & Player Sounds
//==============================================================

//--------------------------------------------------------------
// SuperDamageSound -- Plays sound if needed
//--------------------------------------------------------------
void() player_superdamage_sound =
{
if (self.super_damage_finished > time &&
self.super_sound < time)
{
self.super_sound = time + 1;
sound (self, CHAN_AUTO, "items/damage3.wav",
VOL_HIGH, ATTN_NORM);
}
};

//==============================================================
// Ammo Handling, Weapon Switching, Attack
//==============================================================

//--------------------------------------------------------------
// player_set_current_ammo -- was W_SetCurrentAmmo in weapons.qc
//--------------------------------------------------------------
void() player_set_current_ammo =
{
// get out of any weapon firing states
pl_run1 ();

self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS |
IT_ROCKETS | IT_CELLS));

if (self.weapon == IT_AXE)
{
self.currentammo = 0;
self.weaponmodel = "progs/v_axe.mdl";
}
else if (self.weapon == IT_SHOTGUN)
{
self.currentammo = self.ammo_shells;
self.weaponmodel = "progs/v_shot.mdl";
self.items = self.items | IT_SHELLS;
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
self.currentammo = self.ammo_shells;
self.weaponmodel = "progs/v_shot2.mdl";
self.items = self.items | IT_SHELLS;
}
else if (self.weapon == IT_NAILGUN)
{
self.currentammo = self.ammo_nails;
self.weaponmodel = "progs/v_nail.mdl";
self.items = self.items | IT_NAILS;
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
self.currentammo = self.ammo_nails;
self.weaponmodel = "progs/v_nail2.mdl";
self.items = self.items | IT_NAILS;
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
self.currentammo = self.ammo_rockets;
self.weaponmodel = "progs/v_rock.mdl";
self.items = self.items | IT_ROCKETS;
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
self.currentammo = self.ammo_rockets;
self.weaponmodel = "progs/v_rock2.mdl";
self.items = self.items | IT_ROCKETS;
}
else if (self.weapon == IT_LIGHTNING)
{
self.currentammo = self.ammo_cells;
self.weaponmodel = "progs/v_light.mdl";
self.items = self.items | IT_CELLS;
}
else
{
self.currentammo = 0;
self.weaponmodel = "";
}

// TODO CEV
self.weaponframe = 0;
};

//--------------------------------------------------------------
// best_weapon -- was W_BestWeapon in weapons.qc
//--------------------------------------------------------------
float() player_best_weapon =
{
if (self.conlevel <= WATERLEVEL_FEET &&
self.ammo_cells >= 1 && (self.items & IT_LIGHTNING))
{
return IT_LIGHTNING;
}

if (self.ammo_nails >= 2 && (self.items & IT_SUPER_NAILGUN))
return IT_SUPER_NAILGUN;

if (self.ammo_shells >= 2 && (self.items & IT_SUPER_SHOTGUN))
return IT_SUPER_SHOTGUN;

if (self.ammo_nails >= 1 && (self.items & IT_NAILGUN))
return IT_NAILGUN;

if (self.ammo_shells >= 1 && (self.items & IT_SHOTGUN))
return IT_SHOTGUN;

return IT_AXE;
};

//--------------------------------------------------------------
float() player_check_no_ammo =
{
if (self.currentammo > 0)
return TRUE;

if (self.weapon == IT_AXE)
return TRUE;

self.weapon = player_best_weapon ();
player_set_current_ammo ();

// drop the weapon down
return FALSE;
};

//--------------------------------------------------------------
// Weapon 1: W_FireAxe
//--------------------------------------------------------------
void() player_fire_axe =
{
local vector source;
local vector org;
local float player_solid;

makevectors (self.v_angle);
source = self.origin + '0 0 16';
// set player to SOLID_BBOX, trace, then revert that change,
// as per comments on SOLID_CORPSE in fteextensions.qc -- CEV
player_solid = self.solid;
self.solid = SOLID_BBOX;
traceline (source, source + v_forward * 64, FALSE, self);
self.solid = player_solid;
if (trace_fraction == 1.0)
return;
org = trace_endpos - v_forward * 4;

if (trace_ent.takedamage)
{
trace_ent.axhitme = 1;
spawn_blood (org, '0 0 0', 20);
t_damage2 (trace_ent, self, self, 20);
}
else
{
// hit wall
sound (self, CHAN_WEAPON, "player/axhit2.wav",
VOL_HIGH, ATTN_NORM);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_GUNSHOT);
WriteCoord (MSG_BROADCAST, org_x);
WriteCoord (MSG_BROADCAST, org_y);
WriteCoord (MSG_BROADCAST, org_z);
}
};

//--------------------------------------------------------------
// Weapon 2: W_FireShotgun
//--------------------------------------------------------------
void() player_fire_shotgun =
{
local vector org, dir, vdir;
local float vspeed;

sound (self, CHAN_WEAPON, "weapons/guncock.wav",
VOL_HIGH, ATTN_NORM);

self.punchangle_x = -2;
// self.SendFlags |= PLAYER_NET_PUNCHANGLE;

self.currentammo = self.ammo_shells = self.ammo_shells - 1;
// dir = aim (self, 100000);
makevectors (self.v_angle);

org = self.origin + (self.view_ofs - '0 0 16') +
(v_forward * 10) + (v_right * 0) + (v_up * 8);
dir = normalize (v_forward * BULLET_SPEED);

// 5 bullets instead of 6 -- CEV
for (float i = 0; i < 5; i++)
{
vspeed = crandom () * 10 + BULLET_SPEED;
vdir = dir + crandom() * 0.04 * v_right +
crandom() * 0.04 * v_up;
/*
vdir = dir +
((((i / 10.0) - 0.3) * 0.12) * v_right) +
((((i / 10.0) - 0.3) * 0.12) * v_up);
*/
vdir *= min (vspeed, world_maxvelocity);

spawn_projectile_bullet (self, org, vdir);
}
};

//--------------------------------------------------------------
// Weapon 3: W_FireSuperShotgun
//--------------------------------------------------------------
void() player_fire_supershotgun =
{
local vector org, dir, vdir;
local float vspeed;

if (self.currentammo == 1)
{
player_fire_shotgun ();
return;
}

sound (self, CHAN_WEAPON, "weapons/shotgn2.wav",
VOL_HIGH, ATTN_NORM);

self.punchangle_x = -4;
// self.SendFlags |= PLAYER_NET_PUNCHANGLE;

self.currentammo = self.ammo_shells = self.ammo_shells - 2;
// dir = aim (self, 100000);
makevectors (self.v_angle);

org = self.origin + (self.view_ofs - '0 0 16') +
(v_forward * 10) + (v_right * 0) + (v_up * 8);
dir = normalize (v_forward * BULLET_SPEED);

// 12 bullets instead of 14 -- CEV
for (float i = 0; i < 12; i++)
{
vspeed = crandom () * 10 + BULLET_SPEED;
vdir = dir + (crandom() * 0.14) * v_right +
(crandom() * 0.08) * v_up;
vdir *= min (vspeed, world_maxvelocity);

spawn_projectile_bullet (self, org, vdir);
}
};

//--------------------------------------------------------------
// Weapon 4: W_FireSpikes
//--------------------------------------------------------------
void(float offset) player_fire_spikes =
{
local vector dir;
local vector org = self.origin + self.view_ofs;

makevectors (self.v_angle);

if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
{
player_fire_superspikes ();
return;
}

if (self.ammo_nails < 1)
{
self.weapon = player_best_weapon ();
player_set_current_ammo ();
return;
}

sound (self, CHAN_WEAPON, "weapons/rocket1i.wav",
VOL_HIGH, ATTN_NORM);
self.attack_finished = time + 0.2;
self.currentammo = self.ammo_nails = self.ammo_nails - 1;

dir = aim (self, SPIKE_SPEED);
// dir = normalize (dir);
// SetSpeed
dir *= min (SPIKE_SPEED, world_maxvelocity);

// seven Nailgun position fix - thanks to Greenwood
// -- dumptruck_ds
org += v_up * -8 + v_right * (offset * 0.5);

spawn_projectile_spike (self, org, dir, SPIKE_NORMAL_DAMAGE);

self.punchangle_x = -2;
// self.SendFlags |= PLAYER_NET_PUNCHANGLE;
};

//--------------------------------------------------------------
// Weapon 5: W_FireSuperSpikes
//--------------------------------------------------------------
void() player_fire_superspikes =
{
local vector dir;
local vector org = self.origin + (self.view_ofs - '0 0 4');

sound (self, CHAN_WEAPON, "weapons/spike2.wav",
VOL_HIGH, ATTN_NORM);
self.attack_finished = time + 0.2;
self.currentammo = self.ammo_nails = self.ammo_nails - 2;

dir = aim (self, SPIKE_SPEED);
// dir = normalize (dir);
// SetSpeed
dir *= min (SPIKE_SPEED, world_maxvelocity);

// seven Nailgun position fix - thanks to Greenwood
// -- dumptruck_ds
spawn_projectile_spike (self, org, dir, SPIKE_SUPER_DAMAGE);

self.punchangle_x = -2;
// self.SendFlags |= PLAYER_NET_PUNCHANGLE;
};

//--------------------------------------------------------------
// Weapon 6: W_FireGrenade
//--------------------------------------------------------------
void() player_fire_grenade =
{
local vector missile_velocity = '0 0 0';
local vector org = self.origin + (self.view_ofs - '0 0 8');

self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;

sound (self, CHAN_WEAPON, "weapons/grenade.wav",
VOL_HIGH, ATTN_NORM);

self.punchangle_x = -2;
// self.SendFlags |= PLAYER_NET_PUNCHANGLE;

// set missile speed
makevectors (self.v_angle);

if (self.v_angle_x)
{
missile_velocity = v_forward * GRENADE_SPEED +
v_up * 200 + crandom() * v_right * 10 +
crandom() * v_up * 10;
}
else
{
missile_velocity = aim (self, 10000);
missile_velocity = missile_velocity * GRENADE_SPEED;
missile_velocity_z = 200;
}

spawn_projectile_grenade (self, org, missile_velocity);
};

//--------------------------------------------------------------
void() player_fire_tribolt =
{
local vector missile_vel = '0 0 0';

self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;

sound (self, CHAN_WEAPON, "weapons/grenade.wav",
VOL_HIGH, ATTN_NORM);

self.punchangle_x = -2;
// self.SendFlags |= PLAYER_NET_PUNCHANGLE;

// called a tribolt 'cause there's three of 'em -- CEV
spawn_projectile_bolt (self, 0);
spawn_projectile_bolt (self, BOLT_FIRING_DELAY);
spawn_projectile_bolt (self, BOLT_FIRING_DELAY * 2.0f);
};

//--------------------------------------------------------------
// Weapon 7: W_FireRocket
//--------------------------------------------------------------
void() player_fire_rocket =
{
local vector org = self.origin + (self.view_ofs - '0 0 8');
local vector missile_velocity = '0 0 0';

self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;

sound (self, CHAN_WEAPON, "weapons/sgun1.wav",
VOL_HIGH, ATTN_NORM);

self.punchangle_x = -2;
// self.SendFlags |= PLAYER_NET_PUNCHANGLE;

// set missile speed
makevectors (self.v_angle);
missile_velocity = aim (self, 1000);
missile_velocity *= ROCKET_SPEED;

org += v_forward * 8;

spawn_projectile_rocket (self, org, missile_velocity);
};

//--------------------------------------------------------------
// Weapon 8: W_FireLightning
//--------------------------------------------------------------
void() player_fire_lightning =
{
if (self.ammo_cells < 1)
{
self.weapon = player_best_weapon ();
player_set_current_ammo ();
return;
}

// explode if under water
if (self.conlevel > WATERLEVEL_FEET)
{
local float cells = self.ammo_cells;
self.ammo_cells = 0;
player_set_current_ammo ();
t_radiusdamage2 (self, self, 35 * cells, world);
return;
}

if (self.t_width < time)
{
sound (self, CHAN_WEAPON, "weapons/lhit.wav",
VOL_HIGH, ATTN_NORM);
self.t_width = time + 0.6;
}
self.punchangle_x = -2;
// self.SendFlags |= PLAYER_NET_PUNCHANGLE;

self.currentammo = self.ammo_cells = self.ammo_cells - 1;

// TODO CEV
local vector org = self.origin + (self.view_ofs - '0 0 8');
makevectors (self.v_angle);

// set player to SOLID_BBOX, trace, then revert that change,
// same as in fire_axe -- CEV
local float player_solid = self.solid;
self.solid = SOLID_BBOX;
traceline (org, org + v_forward * 600, TRUE, self);
self.solid = player_solid;

WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
WriteEntity (MSG_BROADCAST, self);
WriteCoord (MSG_BROADCAST, org_x);
WriteCoord (MSG_BROADCAST, org_y);
WriteCoord (MSG_BROADCAST, org_z);
WriteCoord (MSG_BROADCAST, trace_endpos_x);
WriteCoord (MSG_BROADCAST, trace_endpos_y);
WriteCoord (MSG_BROADCAST, trace_endpos_z);

fire_lightning (self.origin, trace_endpos + v_forward * 4,
self, 30);
};

//--------------------------------------------------------------
// PlayerAttack -- An attack impulse can be triggered now
//--------------------------------------------------------------
void() player_attack =
{
local float r;

if (player_check_no_ammo() == FALSE)
return;

// calculate forward angle for velocity
makevectors (self.v_angle);
// wake monsters up
self.show_hostile = time + 1;

if (self.weapon == IT_AXE)
{
sound (self, CHAN_WEAPON, "weapons/ax1.wav",
VOL_HIGH, ATTN_NORM);
r = random ();
if (r < 0.25)
pl_axe1 ();
else if (r < 0.5)
pl_axeb1 ();
else if (r < 0.75)
pl_axec1 ();
else
pl_axed1 ();
self.attack_finished = time + 0.5;
}
else if (self.weapon == IT_SHOTGUN)
{
pl_shot1 ();
player_fire_shotgun ();
self.attack_finished = time + 0.5;
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
pl_shot1 ();
player_fire_supershotgun ();
self.attack_finished = time + 0.7;
}
else if (self.weapon == IT_NAILGUN)
{
pl_nail1 ();
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
pl_nail1 ();
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
pl_rocket1 ();
// TODO CEV
// player_fire_grenade ();
player_fire_tribolt ();
// self.attack_finished = time + 0.6;
self.attack_finished = time + 1.3;
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
pl_rocket1 ();
player_fire_rocket ();
self.attack_finished = time + 0.8;
}
else if (self.weapon == IT_LIGHTNING)
{
pl_light1 ();
self.attack_finished = time + 0.1;
sound (self, CHAN_AUTO, "weapons/lstart.wav",
VOL_HIGH, ATTN_NORM);
}
};

//==============================================================
// Pain and Death
//==============================================================

//--------------------------------------------------------------
void() player_set_suicide_frame =
{
// used by klill command and disconnect command
if (self.model != "progs/player.mdl")
// allready gibbed
return;
self.frame = $deatha11;
self.solid = SOLID_NOT;
self.movetype = MOVETYPE_TOSS;
self.deadflag = DEAD_DEAD;
self.nextthink = -1;
};

//--------------------------------------------------------------
// PainSound
//--------------------------------------------------------------
void() player_pain_sound =
{
local float rs;

if (self.health < 0)
return;

if (damage_attacker.classname == "teledeath")
{
sound (self, CHAN_VOICE, "player/teledth1.wav",
VOL_HIGH, ATTN_NONE);
return;
}

// water pain sounds
if (self.contype == CONTENT_WATER &&
self.conlevel == WATERLEVEL_EYES)
{
// PlayerDeathBubbles
spawn_air_bubbles (self, self.origin, 1);
if (random() > 0.5)
sound (self, CHAN_VOICE, "player/drown1.wav",
VOL_HIGH, ATTN_NORM);
else
sound (self, CHAN_VOICE, "player/drown2.wav",
VOL_HIGH, ATTN_NORM);
return;
}

// slime pain sounds
if (self.contype == CONTENT_SLIME)
{
// FIX ME put in some steam here
// 1998-08-10 Player gulps bubbles when hurt in slime
// by Maddes start
if (self.conlevel == WATERLEVEL_EYES)
// PlayerDeathBubbles
spawn_air_bubbles (self, self.origin, 1);
// 1998-08-10 Player gulps bubbles when hurt in slime
// by Maddes end
if (random() > 0.5)
sound (self, CHAN_VOICE, "player/lburn1.wav",
VOL_HIGH, ATTN_NORM);
else
sound (self, CHAN_VOICE, "player/lburn2.wav",
VOL_HIGH, ATTN_NORM);
return;
}

if (self.contype == CONTENT_LAVA)
{
if (random() > 0.5)
sound (self, CHAN_VOICE, "player/lburn1.wav",
VOL_HIGH, ATTN_NORM);
else
sound (self, CHAN_VOICE, "player/lburn2.wav",
VOL_HIGH, ATTN_NORM);
return;
}

if (self.pain_finished > time)
{
self.axhitme = 0;
return;
}

// don't make multiple pain sounds right after each other
self.pain_finished = time + 0.5;

// ax pain sound
if (self.axhitme == 1)
{
self.axhitme = 0;
sound (self, CHAN_VOICE, "player/axhit1.wav",
VOL_HIGH, ATTN_NORM);
return;
}

rs = rint ((random() * 5) + 1);

self.noise = "";
if (rs == 1)
self.noise = "player/pain1.wav";
else if (rs == 2)
self.noise = "player/pain2.wav";
else if (rs == 3)
self.noise = "player/pain3.wav";
else if (rs == 4)
self.noise = "player/pain4.wav";
else if (rs == 5)
self.noise = "player/pain5.wav";
else
self.noise = "player/pain6.wav";

sound (self, CHAN_VOICE, self.noise, VOL_HIGH, ATTN_NORM);
return;
};

//--------------------------------------------------------------
// PlayerDeathSound
//--------------------------------------------------------------
void() player_death_sound =
{
local float rs;

// water death sounds
if (self.conlevel == WATERLEVEL_EYES)
{
// PlayerDeathBubbles
spawn_air_bubbles (self, self.origin, 20);
sound (self, CHAN_VOICE, "player/h2odeath.wav",
VOL_HIGH, ATTN_NONE);
return;
}

rs = rint ((random() * 4) + 1);
if (rs == 1)
self.noise = "player/death1.wav";
else if (rs == 2)
self.noise = "player/death2.wav";
else if (rs == 3)
self.noise = "player/death3.wav";
else if (rs == 4)
self.noise = "player/death4.wav";
else if (rs == 5)
self.noise = "player/death5.wav";

sound (self, CHAN_VOICE, self.noise, VOL_HIGH, ATTN_NONE);
return;
};

//--------------------------------------------------------------
// PlayerDead -- the player is dead, hold them there
//--------------------------------------------------------------
void() player_dead =
{
self.nextthink = -1;
// allow respawn after a certain time
self.deadflag = DEAD_DEAD;
};

//==============================================================
// Player Think Functions
//==============================================================

//--------------------------------------------------------------
void() player_footstep =
{
// not moving, no steps
if (self.velocity_x == 0 || self.velocity_y == 0)
return;

// no steps when crouching
if (self.pm_flags & PMF_CROUCHED)
return;

// no steps when on a slick/icy surface
if (self.pm_flags & PMF_ONSLICK)
return;

// at least 200ms between steps
if (self.step_time >= time - 0.2)
return;

// no steps when submerged fully
if (self.conlevel >= WATERLEVEL_EYES)
return;

if (self.speed < PM_WALKSPEED * 0.9)
// no footsteps below PM_WALKSPEED * 0.9
return;

if (self.speed < PM_MAXSPEED * 0.9)
if (self.frame != $rockrun2 && self.frame != $axrun2)
// half the footsteps when walking
return;

local float vol = 0;
local string wav = "";

if (self.conlevel == WATERLEVEL_FEET)
{
// the water foot
vol = 0.3 + (random() * 0.1);
self.cnt = rint (random() * 3);

switch (self.cnt)
{
case 0:
wav = "player/stepwater1.ogg";
break;
case 1:
wav = "player/stepwater2.ogg";
break;
case 2:
wav = "player/stepwater3.ogg";
break;
case 3:
wav = "player/stepwater4.ogg";
}
}
else if (self.conlevel == WATERLEVEL_WAIST)
{
// the deep water foot
if (self.frame != $rockrun2 && self.frame != $axrun2)
return;

vol = 0.3 + (random() * 0.1);
if (self.cnt > 3)
self.cnt = 0;

switch (self.cnt)
{
case 0:
wav = "player/stepwade1.ogg";
break;
case 1:
wav = "player/stepwade2.ogg";
}
}
else
{
// call world_surface_type (which then calls out
// to compatibility modules) to get a material type
// under the player -- CEV
switch (world_surface_type(self, [0, 0, self.mins_z]))
{
case SURFACE_DIRT:
vol = 0.3 + (random() * 0.2);
if (self.cnt > 4)
self.cnt = 0;
wav = sprintf ("player/stepdirt%g.ogg",
self.cnt + 1);
break;
case SURFACE_METAL:
vol = 0.3 + (random() * 0.2);
self.cnt = rint (random() * 8);
wav = sprintf ("player/stepmetal%g.ogg",
self.cnt + 1);
break;
case SURFACE_WOOD:
vol = 0.3 + (random() * 0.2);
if (self.cnt > 3)
self.cnt = 0;
wav = sprintf ("player/stepwood%g.ogg",
self.cnt + 1);
break;
default:
// default is SURFACE_STONE -- CEV
vol = 0.3 + (random() * 0.2);
if (self.cnt > 5)
self.cnt = 0;
wav = sprintf ("player/stepstone%g.ogg",
self.cnt + 1);
}
}

sound (self, CHAN_FEET, wav, vol, ATTN_FEET);
self.cnt++;
self.step_time = time;

if (self.lefty == FALSE)
self.lefty = TRUE;
else
self.lefty = FALSE;
};

//--------------------------------------------------------------
void() player_stand =
{
self.weaponframe = 0;

if (self.velocity_x || self.velocity_y)
{
if (self.weapon == IT_AXE)
pl_axrun1 ();
else
pl_run1 ();
}
else if (self.weapon == IT_AXE)
{
pl_axstnd1 ();
}
};

//--------------------------------------------------------------
void() player_axstand =
{
self.weaponframe = 0;

if (self.velocity_x || self.velocity_y)
{
if (self.weapon == IT_AXE)
pl_axrun1 ();
else
pl_run1 ();
return;
}
else if (self.weapon != IT_AXE)
{
pl_stand1 ();
}
};

//--------------------------------------------------------------
void(void() axthink) player_run =
{
// dprint (sprintf("player_run: frame %g\n", self.frame));

if (self.velocity_x == 0 && self.velocity_y == 0)
pl_stand1 ();
else if (self.weapon == IT_AXE)
axthink ();
};

//--------------------------------------------------------------
void(void() runthink) player_axrun =
{
// dprint (sprintf("player_axrun: frame %g\n", self.frame));

if (self.velocity_x == 0 && self.velocity_y == 0)
pl_stand1 ();
else if (self.weapon != IT_AXE)
runthink ();
};

//--------------------------------------------------------------
// Player Axe Stand function
//--------------------------------------------------------------
void() pl_axstnd1 = [$axstnd1, pl_axstnd2] { player_axstand (); };
void() pl_axstnd2 = [$axstnd2, pl_axstnd3] { player_axstand (); };
void() pl_axstnd3 = [$axstnd3, pl_axstnd4] { player_axstand (); };
void() pl_axstnd4 = [$axstnd4, pl_axstnd5] { player_axstand (); };
void() pl_axstnd5 = [$axstnd5, pl_axstnd6] { player_axstand (); };
void() pl_axstnd6 = [$axstnd6, pl_axstnd7] { player_axstand (); };
void() pl_axstnd7 = [$axstnd7, pl_axstnd8] { player_axstand (); };
void() pl_axstnd8 = [$axstnd8, pl_axstnd9] { player_axstand (); };
void() pl_axstnd9 = [$axstnd9, pl_axstnd10] { player_axstand (); };
void() pl_axstnd10 = [$axstnd10, pl_axstnd11] { player_axstand (); };
void() pl_axstnd11 = [$axstnd11, pl_axstnd12] { player_axstand (); };
void() pl_axstnd12 = [$axstnd12, pl_axstnd1] { player_axstand (); };

//--------------------------------------------------------------
// Player Stand function
//--------------------------------------------------------------
void() pl_stand1 = [$stand1, pl_stand2] { player_stand (); };
void() pl_stand2 = [$stand2, pl_stand3] { player_stand (); };
void() pl_stand3 = [$stand3, pl_stand4] { player_stand (); };
void() pl_stand4 = [$stand4, pl_stand5] { player_stand (); };
void() pl_stand5 = [$stand5, pl_stand1] { player_stand (); };

//--------------------------------------------------------------
// Player Axe Run function
//--------------------------------------------------------------
void() pl_axrun1 = [$axrun1, pl_axrun2]
{
self.weaponframe = 0;
self.lefty = FALSE;
player_axrun (pl_run1);
};
void() pl_axrun2 = [$axrun2, pl_axrun3]
{
// left foot down
player_axrun (pl_run2);
if (self.flags & FL_ONGROUND)
player_footstep ();
};
void() pl_axrun3 = [$axrun3, pl_axrun4] { player_axrun (pl_run3); };
void() pl_axrun4 = [$axrun4, pl_axrun5] { player_axrun (pl_run4); };
void() pl_axrun5 = [$axrun5, pl_axrun6]
{
// right foot down
player_axrun (pl_run5);
if (self.flags & FL_ONGROUND)
player_footstep ();
};
void() pl_axrun6 = [$axrun6, pl_axrun1] { player_axrun (pl_run6); };

//--------------------------------------------------------------
// Player Run function
//--------------------------------------------------------------
void() pl_run1 = [$rockrun1, pl_run2]
{
self.weaponframe = 0;
self.lefty = FALSE;
player_run (pl_axrun1);
};
void() pl_run2 = [$rockrun2, pl_run3]
{
// left foot down
player_run (pl_axrun2);
if (self.flags & FL_ONGROUND)
player_footstep ();
};
void() pl_run3 = [$rockrun3, pl_run4] { player_run (pl_axrun3); };
void() pl_run4 = [$rockrun4, pl_run5] { player_run (pl_axrun4); };
void() pl_run5 = [$rockrun5, pl_run6]
{
// right foot down
player_run (pl_axrun5);
if (self.flags & FL_ONGROUND)
player_footstep ();
};
void() pl_run6 = [$rockrun6, pl_run1] { player_run (pl_axrun6); };

//--------------------------------------------------------------
// Player Projectile Attack
//--------------------------------------------------------------
void() pl_shot1 = [$shotatt1, pl_shot2]
{
self.weaponframe = 1;
self.sveffects |= EF_MUZZLEFLASH;
// self.SendFlags |= PLAYER_NET_EFFECTS;
};
void() pl_shot2 = [$shotatt2, pl_shot3] { self.weaponframe = 2; };
void() pl_shot3 = [$shotatt3, pl_shot4] { self.weaponframe = 3; };
void() pl_shot4 = [$shotatt4, pl_shot5] { self.weaponframe = 4; };
void() pl_shot5 = [$shotatt5, pl_shot6] { self.weaponframe = 5; };
void() pl_shot6 = [$shotatt6, pl_run1] { self.weaponframe = 6; };

//--------------------------------------------------------------
// Player Axe Attack A
//--------------------------------------------------------------
void() pl_axe1 = [$axatt1, pl_axe2] { self.weaponframe = 1; };
void() pl_axe2 = [$axatt2, pl_axe3] { self.weaponframe = 2; };
void() pl_axe3 = [$axatt3, pl_axe4]
{
self.weaponframe = 3;
player_fire_axe ();
};
void() pl_axe4 = [$axatt4, pl_run1] { self.weaponframe = 4; };

//--------------------------------------------------------------
// Player Axe Attack B
//--------------------------------------------------------------
void() pl_axeb1 = [$axattb1, pl_axeb2] { self.weaponframe = 5; };
void() pl_axeb2 = [$axattb2, pl_axeb3] { self.weaponframe = 6; };
void() pl_axeb3 = [$axattb3, pl_axeb4]
{
self.weaponframe = 7;
player_fire_axe ();
};
void() pl_axeb4 = [$axattb4, pl_run1] { self.weaponframe = 8; };

//--------------------------------------------------------------
// Player Axe Attack C
//--------------------------------------------------------------
void() pl_axec1 = [$axattc1, pl_axec2] { self.weaponframe = 1; };
void() pl_axec2 = [$axattc2, pl_axec3] { self.weaponframe = 2; };
void() pl_axec3 = [$axattc3, pl_axec4]
{
self.weaponframe = 3;
player_fire_axe ();
};
void() pl_axec4 = [$axattc4, pl_run1] { self.weaponframe = 4; };

//--------------------------------------------------------------
// Player Axe Attack D
//--------------------------------------------------------------
void() pl_axed1 = [$axattd1, pl_axed2] { self.weaponframe = 5; };
void() pl_axed2 = [$axattd2, pl_axed3] { self.weaponframe = 6; };
void() pl_axed3 = [$axattd3, pl_axed4]
{
self.weaponframe = 7;
player_fire_axe ();
};
void() pl_axed4 = [$axattd4, pl_run1] { self.weaponframe = 8; };

//--------------------------------------------------------------
// Player Nail Attack
//--------------------------------------------------------------
void() pl_nail1 = [$nailatt1, pl_nail2]
{
self.sveffects |= EF_MUZZLEFLASH;
// self.SendFlags |= PLAYER_NET_EFFECTS;

if (!self.button0)
{
pl_run1 ();
return;
}

self.weaponframe = self.weaponframe + 1;
if (self.weaponframe == 9)
self.weaponframe = 1;
player_superdamage_sound ();
player_fire_spikes (4);
self.attack_finished = time + 0.2;
};
void() pl_nail2 = [$nailatt2, pl_nail1]
{
self.sveffects |= EF_MUZZLEFLASH;
// self.SendFlags |= PLAYER_NET_EFFECTS;

if (!self.button0)
{
pl_run1 ();
return;
}

self.weaponframe = self.weaponframe + 1;
if (self.weaponframe == 9)
self.weaponframe = 1;
player_superdamage_sound ();
player_fire_spikes (-4);
self.attack_finished = time + 0.2;
};

//--------------------------------------------------------------
// Player LG Attack
//--------------------------------------------------------------
void() pl_light1 = [$light1, pl_light2]
{
self.sveffects |= EF_MUZZLEFLASH;
// self.SendFlags |= PLAYER_NET_EFFECTS;

if (!self.button0)
{
pl_run1 ();
return;
}

self.weaponframe = self.weaponframe + 1;
if (self.weaponframe == 5)
self.weaponframe = 1;
player_superdamage_sound ();
player_fire_lightning ();
self.attack_finished = time + 0.2;
};
void() pl_light2 = [$light2, pl_light1]
{
self.sveffects |= EF_MUZZLEFLASH;
// self.SendFlags |= PLAYER_NET_EFFECTS;

if (!self.button0)
{
pl_run1 ();
return;
}

self.weaponframe = self.weaponframe + 1;
if (self.weaponframe == 5)
self.weaponframe = 1;
player_superdamage_sound ();
player_fire_lightning ();
self.attack_finished = time + 0.2;
};

//--------------------------------------------------------------
// Player Rocket Attack
//--------------------------------------------------------------
void() pl_rocket1 = [$rockatt1, pl_rocket2]
{
self.weaponframe = 1;
self.sveffects |= EF_MUZZLEFLASH;
// self.SendFlags |= PLAYER_NET_EFFECTS;
};
void() pl_rocket2 = [$rockatt2, pl_rocket3] { self.weaponframe = 2; };
void() pl_rocket3 = [$rockatt3, pl_rocket4] { self.weaponframe = 3; };
void() pl_rocket4 = [$rockatt4, pl_rocket5] { self.weaponframe = 4; };
void() pl_rocket5 = [$rockatt5, pl_rocket6] { self.weaponframe = 5; };
void() pl_rocket6 = [$rockatt6, pl_run1] { self.weaponframe = 6; };

//--------------------------------------------------------------
// Player Pain state A
//--------------------------------------------------------------
void() pl_pain1 = [$pain1, pl_pain2]
{
player_pain_sound ();
self.weaponframe = 0;
};
void() pl_pain2 = [$pain2, pl_pain3] { };
void() pl_pain3 = [$pain3, pl_pain4] { };
void() pl_pain4 = [$pain4, pl_pain5] { };
void() pl_pain5 = [$pain5, pl_pain6] { };
void() pl_pain6 = [$pain6, pl_run1] { };

//--------------------------------------------------------------
// Player Axe Pain state A
//--------------------------------------------------------------
void() pl_axpain1 = [$axpain1, pl_axpain2]
{
player_pain_sound ();
self.weaponframe = 0;
};
void() pl_axpain2 = [$axpain2, pl_axpain3] {};
void() pl_axpain3 = [$axpain3, pl_axpain4] {};
void() pl_axpain4 = [$axpain4, pl_axpain5] {};
void() pl_axpain5 = [$axpain5, pl_axpain6] {};
void() pl_axpain6 = [$axpain6, pl_run1] {};

//--------------------------------------------------------------
// Player Death state A
//--------------------------------------------------------------
void() pl_diea1 = [$deatha1, pl_diea2] {};
void() pl_diea2 = [$deatha2, pl_diea3] {};
void() pl_diea3 = [$deatha3, pl_diea4] {};
void() pl_diea4 = [$deatha4, pl_diea5] {};
void() pl_diea5 = [$deatha5, pl_diea6] {};
void() pl_diea6 = [$deatha6, pl_diea7] {};
void() pl_diea7 = [$deatha7, pl_diea8] {};
void() pl_diea8 = [$deatha8, pl_diea9] {};
void() pl_diea9 = [$deatha9, pl_diea10] {};
void() pl_diea10 = [$deatha10, pl_diea11] {};
void() pl_diea11 = [$deatha11, pl_diea11] { player_dead (); };

//--------------------------------------------------------------
// Player Death state B
//--------------------------------------------------------------
void() pl_dieb1 = [$deathb1, pl_dieb2] {};
void() pl_dieb2 = [$deathb2, pl_dieb3] {};
void() pl_dieb3 = [$deathb3, pl_dieb4] {};
void() pl_dieb4 = [$deathb4, pl_dieb5] {};
void() pl_dieb5 = [$deathb5, pl_dieb6] {};
void() pl_dieb6 = [$deathb6, pl_dieb7] {};
void() pl_dieb7 = [$deathb7, pl_dieb8] {};
void() pl_dieb8 = [$deathb8, pl_dieb9] {};
void() pl_dieb9 = [$deathb9, pl_dieb9] { player_dead (); };

//--------------------------------------------------------------
// Player Death state C
//--------------------------------------------------------------
void() pl_diec1 = [$deathc1, pl_diec2] {};
void() pl_diec2 = [$deathc2, pl_diec3] {};
void() pl_diec3 = [$deathc3, pl_diec4] {};
void() pl_diec4 = [$deathc4, pl_diec5] {};
void() pl_diec5 = [$deathc5, pl_diec6] {};
void() pl_diec6 = [$deathc6, pl_diec7] {};
void() pl_diec7 = [$deathc7, pl_diec8] {};
void() pl_diec8 = [$deathc8, pl_diec9] {};
void() pl_diec9 = [$deathc9, pl_diec10] {};
void() pl_diec10 = [$deathc10, pl_diec11] {};
void() pl_diec11 = [$deathc11, pl_diec12] {};
void() pl_diec12 = [$deathc12, pl_diec13] {};
void() pl_diec13 = [$deathc13, pl_diec14] {};
void() pl_diec14 = [$deathc14, pl_diec15] {};
void() pl_diec15 = [$deathc15, pl_diec15] { player_dead (); };

//--------------------------------------------------------------
// Player Death state D
//--------------------------------------------------------------
void() pl_died1 = [$deathd1, pl_died2] {};
void() pl_died2 = [$deathd2, pl_died3] {};
void() pl_died3 = [$deathd3, pl_died4] {};
void() pl_died4 = [$deathd4, pl_died5] {};
void() pl_died5 = [$deathd5, pl_died6] {};
void() pl_died6 = [$deathd6, pl_died7] {};
void() pl_died7 = [$deathd7, pl_died8] {};
void() pl_died8 = [$deathd8, pl_died9] {};
void() pl_died9 = [$deathd9, pl_died9] { player_dead (); };

//--------------------------------------------------------------
// Player Death state E
//--------------------------------------------------------------
void() pl_diee1 = [$deathe1, pl_diee2] {};
void() pl_diee2 = [$deathe2, pl_diee3] {};
void() pl_diee3 = [$deathe3, pl_diee4] {};
void() pl_diee4 = [$deathe4, pl_diee5] {};
void() pl_diee5 = [$deathe5, pl_diee6] {};
void() pl_diee6 = [$deathe6, pl_diee7] {};
void() pl_diee7 = [$deathe7, pl_diee8] {};
void() pl_diee8 = [$deathe8, pl_diee9] {};
void() pl_diee9 = [$deathe9, pl_diee9] { player_dead (); };

//--------------------------------------------------------------
// Player Axe Death state A
//--------------------------------------------------------------
void() pl_die_ax1 = [$axdeth1, pl_die_ax2] {};
void() pl_die_ax2 = [$axdeth2, pl_die_ax3] {};
void() pl_die_ax3 = [$axdeth3, pl_die_ax4] {};
void() pl_die_ax4 = [$axdeth4, pl_die_ax5] {};
void() pl_die_ax5 = [$axdeth5, pl_die_ax6] {};
void() pl_die_ax6 = [$axdeth6, pl_die_ax7] {};
void() pl_die_ax7 = [$axdeth7, pl_die_ax8] {};
void() pl_die_ax8 = [$axdeth8, pl_die_ax9] {};
void() pl_die_ax9 = [$axdeth9, pl_die_ax9] { player_dead (); };

//--------------------------------------------------------------
// PlayerDeathThink -- called from prethink when dead
//--------------------------------------------------------------
void() player_death_think =
{
local float forward;

if ((self.flags & FL_ONGROUND))
{
forward = vlen (self.velocity);
forward = forward - 20;
if (forward <= 0)
self.velocity = '0 0 0';
else
self.velocity = forward *
normalize (self.velocity);
}

// wait for all buttons released
if (self.deadflag == DEAD_DEAD)
{
if (self.button2 || self.button1 || self.button0)
return;
self.deadflag = DEAD_RESPAWNABLE;
return;
}

// wait for any button down
if (!self.button2 && !self.button1 && !self.button0)
return;

self.button0 = 0;
self.button1 = 0;
self.button2 = 0;
player_respawn ();
};

//--------------------------------------------------------------
// WaterMove
//--------------------------------------------------------------
void() player_prethink_watermove =
{
if (self.movetype == MOVETYPE_NOCLIP)
{
self.air_finished = time + 120;
return;
}

if (self.health < 0)
return;

if (self.conlevel != WATERLEVEL_EYES)
{
if (self.air_finished < time)
sound (self, CHAN_VOICE, "player/gasp2.wav",
VOL_HIGH, ATTN_NORM);
else if (self.air_finished < time + 9)
sound (self, CHAN_VOICE, "player/gasp1.wav",
VOL_HIGH, ATTN_NORM);
self.air_finished = time + 12;
self.dmg = 2;
}
else if (self.air_finished < time)
{
// drown!
if (self.pain_finished < time)
{
self.dmg = self.dmg + 2;
if (self.dmg > 15)
self.dmg = 10;
self.deathtype = "drowning";
t_damage2 (self, world, world, self.dmg);
self.deathtype = "";
self.pain_finished = time + 1;
}
}

if (self.conlevel == WATERLEVEL_NONE)
{
if (self.flags & FL_INWATER)
{
// play leave water sound
sound (self, CHAN_AUTO, "misc/outwater.wav",
VOL_HIGH, ATTN_NORM);
self.flags &= ~FL_INWATER;
}
return;
}

if (self.contype == CONTENT_LAVA)
{
// do damage
if (self.damage_time < time)
{
if (self.radsuit_finished > time)
self.damage_time = time + 1;
else
self.damage_time = time + 0.2;

self.deathtype = "lava";
t_damage2 (self, world, world,
10 * self.conlevel);
self.deathtype = "";
}
}
else if (self.contype == CONTENT_SLIME)
{
// do damage
if (self.damage_time < time &&
self.radsuit_finished < time)
{
self.damage_time = time + 1;
self.deathtype = "slime";
t_damage2 (self, world, world,
4 * self.conlevel);
self.deathtype = "";
}
}

if (!(self.flags & FL_INWATER))
{
// player enter water sound
if (self.contype == CONTENT_LAVA)
sound (self, CHAN_AUTO, "player/inlava.wav",
VOL_HIGH, ATTN_NORM);
if (self.contype == CONTENT_WATER)
sound (self, CHAN_AUTO, "player/inh2o.wav",
VOL_HIGH, ATTN_NORM);
if (self.contype == CONTENT_SLIME)
sound (self, CHAN_AUTO, "player/slimbrn2.wav",
VOL_HIGH, ATTN_NORM);

self.flags |= FL_INWATER;
self.damage_time = 0;
}
};

//--------------------------------------------------------------
// Called by PlayerPreThink in entrypoints.qc -- CEV
//--------------------------------------------------------------
void() player_prethink =
{
local float do_ladder_physics = FALSE;

// If just spawned in, try to recover previous fog values
// from own client entity, if any
if (clean_up_client_stuff)
fog_set_from_ent (self, self);

self.gravity = self.wantedgravity;

player_prethink_watermove ();

if (self.deadflag >= DEAD_DEAD)
{
// dead, so run the death think -- CEV
player_death_think ();
return;
}

if (self.deadflag == DEAD_DYING)
// dying, so do nothing
return;

// teleporters can force a non-moving pause time
if (time < self.pausetime)
self.velocity = '0 0 0';

if (time > self.attack_finished && self.currentammo == 0
&& self.weapon != IT_AXE)
{
self.weapon = player_best_weapon ();
player_set_current_ammo ();
}
};

//--------------------------------------------------------------
// CheckPowerups -- Check for turning off powerups
//--------------------------------------------------------------
void() player_postthink_powerups =
{
if (self.health <= 0)
return;

// invisibility
if (self.invisible_finished)
{
// sound and screen flash when items starts to run out
if (self.invisible_sound < time)
{
sound (self, CHAN_AUTO, "items/inv3.wav",
VOL_MID, ATTN_IDLE);
self.invisible_sound = time +
((random() * 3) + 1);
}

if (self.invisible_finished < time + 3)
{
if (self.invisible_time == 1)
{
sprint (self, "Ring of Shadows magic is"
" fading\n");
stuffcmd (self, "bf\n");
sound (self, CHAN_AUTO,"items/inv2.wav",
VOL_HIGH, ATTN_NORM);
self.invisible_time = time + 1;
}

if (self.invisible_time < time)
{
self.invisible_time = time + 1;
stuffcmd (self, "bf\n");
}
}

if (self.invisible_finished < time)
{
// just stopped
self.items = self.items - IT_INVISIBILITY;
self.invisible_finished = 0;
self.invisible_time = 0;
}

// use the eyes
if (self.modelindex != modelindex_eyes)
{
self.frame = 0;
self.modelindex = modelindex_eyes;
// self.SendFlags |= PLAYER_NET_FRAME |
// PLAYER_NET_MODEL;
}
}
else
{
// don't use the eyes
if (self.modelindex != modelindex_player)
{
self.modelindex = modelindex_player;
// self.SendFlags |= PLAYER_NET_FRAME |
// PLAYER_NET_MODEL;
}
}

// invincibility
if (self.invincible_finished)
{
// sound and screen flash when items starts to run out
if (self.invincible_finished < time + 3)
{
if (self.invincible_time == 1)
{
sprint (self, "Protection is almost "
"burned out\n");
stuffcmd (self, "bf\n");
sound (self, CHAN_AUTO,
"items/protect2.wav",
VOL_HIGH, ATTN_NORM);
self.invincible_time = time + 1;
}

if (self.invincible_time < time)
{
self.invincible_time = time + 1;
stuffcmd (self, "bf\n");
}
}

if (self.invincible_finished < time)
{
// just stopped
self.items = self.items - IT_INVULNERABILITY;
self.invincible_time = 0;
self.invincible_finished = 0;
}
if (self.invincible_finished > time)
self.sveffects |= EF_DIMLIGHT;
else
self.sveffects &= ~EF_DIMLIGHT;

// self.SendFlags |= PLAYER_NET_EFFECTS;
}

// super damage
if (self.super_damage_finished)
{
// sound and screen flash when items starts to run out
if (self.super_damage_finished < time + 3)
{
if (self.super_time == 1)
{
sprint (self, "Quad Damage is wearing "
"off\n");
stuffcmd (self, "bf\n");
sound (self, CHAN_AUTO,
"items/damage2.wav",
VOL_HIGH, ATTN_NORM);
self.super_time = time + 1;
}

if (self.super_time < time)
{
self.super_time = time + 1;
stuffcmd (self, "bf\n");
}
}

if (self.super_damage_finished < time)
{
// just stopped
self.items = self.items - IT_QUAD;
self.super_damage_finished = 0;
self.super_time = 0;
}
if (self.super_damage_finished > time)
self.sveffects |= EF_DIMLIGHT;
else
self.sveffects &= ~EF_DIMLIGHT;

// self.SendFlags |= PLAYER_NET_EFFECTS;
}

// suit
if (self.radsuit_finished)
{
// don't drown
self.air_finished = time + 12;

// sound and screen flash when items starts to run out
if (self.radsuit_finished < time + 3)
{
if (self.rad_time == 1)
{
sprint (self, "Air supply in Biosuit "
"expiring\n");
stuffcmd (self, "bf\n");
sound (self, CHAN_AUTO,
"items/suit2.wav",
VOL_HIGH, ATTN_NORM);
self.rad_time = time + 1;
}

if (self.rad_time < time)
{
self.rad_time = time + 1;
stuffcmd (self, "bf\n");
}
}

if (self.radsuit_finished < time)
{
// just stopped
self.items = self.items - IT_SUIT;
self.rad_time = 0;
self.radsuit_finished = 0;
}
}
};

//--------------------------------------------------------------
// Called by PlayerPostThink in entrypoints.qc -- CEV
//--------------------------------------------------------------
void() player_postthink =
{
// load up the sendflags -- CEV
// if (self.oldorigin != self.origin)
// self.SendFlags |= PLAYER_NET_ORIGIN;
self.SendFlags = PLAYER_NET_FRAME | PLAYER_NET_MODEL |
PLAYER_NET_ORIGIN | PLAYER_NET_ANGLES |
PLAYER_NET_VELOCITY | PLAYER_NET_FLAGS |
PLAYER_NET_TIMERS | PLAYER_NET_EFFECTS |
PLAYER_NET_SOLID | PLAYER_NET_PUNCHANGLE;

if (self.view_ofs == '0 0 0')
// intermission or finale
return;

if (self.deadflag)
return;

if (self.pm_flags & PMF_ONGROUND)
{
if (self.pm_flags & PMF_CROUCHED)
{
// TODO CEV
local vector l = getlight (self.origin);
/*
l = normalize (l);
*/

/*
dprint (sprintf("player_postthink: light %v, "
"level %g\n", l, vlen(l)));
*/
}
}

// next block was in W_WeaponFrame -- CEV
if (time >= self.attack_finished)
{
if (self.impulse)
player_impulse ();

if (input_buttons & PM_BTN_ATTACK)
{
player_superdamage_sound ();
player_attack ();
}
}

// check to see if player landed and play landing sound
if (self.jump_flag < -300 && self.health > 0)
{
if (self.contype == CONTENT_WATER)
sound (self, CHAN_BODY, "player/h2ojump.wav",
VOL_HIGH, ATTN_NORM);
else if (self.jump_flag < -650)
{
self.deathtype = "falling";
t_damage2 (self, world, world, 5);
self.deathtype = "";
sound (self, CHAN_VOICE, "player/land2.wav",
VOL_HIGH, ATTN_NORM);
}
else
sound (self, CHAN_VOICE, "player/land.wav",
VOL_HIGH, ATTN_NORM);

self.jump_flag = 0;
}

// dumptruck_ds -- self replaces item_megahealth_rot in items.qc
if (self.health > self.max_health)
{
if (self.megahealth_rottime < time)
{
self.megahealth_rottime = time + 1;
self.health = self.health - 1;
}
else if (self.health <= 100)
{
// thanks ydrol!!!
self.items = self.items -
(self.items & IT_SUPERHEALTH);
}
}

player_postthink_powerups ();
};

//==============================================================
// Interaction
//==============================================================

//--------------------------------------------------------------
// player_pain
//--------------------------------------------------------------
void(entity attacker, float damage) player_pain =
{
if (self.weaponframe)
return;

if (self.invisible_finished > time)
// eyes don't have pain frames
return;

if (self.weapon == IT_AXE)
pl_axpain1 ();
else
pl_pain1 ();
};

//--------------------------------------------------------------
// gib_player
//--------------------------------------------------------------
void(vector dir) player_destroy_gib =
{
throw_gib_head_player (self, dir, self.health);
throw_gib_1 (self, dir, self.health);
throw_gib_2 (self, dir, self.health);
throw_gib_3 (self, dir, self.health);

self.deadflag = DEAD_DEAD;

if (damage_attacker.classname == "teledeath")
sound (self, CHAN_VOICE, "player/teledth1.wav",
VOL_HIGH, ATTN_NONE);
else if (damage_attacker.classname == "teledeath2")
sound (self, CHAN_VOICE, "player/teledth1.wav",
VOL_HIGH, ATTN_NONE);
else
if (random() < 0.5)
sound (self, CHAN_VOICE, "player/gib.wav",
VOL_HIGH, ATTN_NONE);
else
sound (self, CHAN_VOICE, "player/udeath.wav",
VOL_HIGH, ATTN_NONE);
};

//--------------------------------------------------------------
// PlayerDie
//--------------------------------------------------------------
void(vector dir) player_destroy =
{
local float i;

// 1998-07-23 Palette shift when player dies with quad/pentagram
// fix by Maddes start
// self.items = self.items - (self.items & IT_INVISIBILITY);
self.items = self.items - (self.items &
(IT_INVISIBILITY | IT_INVULNERABILITY |
IT_SUIT | IT_QUAD));
// 1998-07-23 Palette shift when player dies with quad/pentagram
// fix by Maddes end

// don't die as eyes
// self.invisible_finished = 0;
self.invincible_finished = 0;
self.super_damage_finished = 0;
self.radsuit_finished = 0;

// 1998-07-23 Glowing corpse of players which had quad/pentagram
// until respawn fix by Maddes
self.effects = 0;
self.sveffects = 0;

// don't use eyes
self.modelindex = modelindex_player;

if (deathmatch || coop)
item_backpack_drop (self);

self.weaponmodel = "";
self.view_ofs = '0 0 -8';
self.deadflag = DEAD_DYING;
self.solid = SOLID_NOT;
self.flags = self.flags - (self.flags & FL_ONGROUND);
self.movetype = MOVETYPE_TOSS;

if (self.velocity_z < 10)
self.velocity_z = self.velocity_z + random() * 300;

if (self.health < -40)
{
player_destroy_gib (dir);
return;
}

player_death_sound ();

self.angles_x = 0;
self.angles_z = 0;

if (self.weapon == IT_AXE)
{
pl_die_ax1 ();
return;
}

i = cvar ("temp1");
if (!i)
i = 1 + floor (random() * 6);

if (i == 1)
pl_diea1 ();
else if (i == 2)
pl_dieb1 ();
else if (i == 3)
pl_diec1 ();
else if (i == 4)
pl_died1 ();
else
pl_diee1 ();
};
#endif

#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
// by: Philip Martin aka: Kryten
// When on top of monsters or players you slide. This is a QuakeC
// problem. The function below fixes that problem.
// based on code given to Kryten by: Michael Turitzin (MaNiAc)
//--------------------------------------------------------------
void() player_touch =
{
// 1998-09-16 Sliding/not-jumping on monsters/boxes/players
// fix by Maddes/Kryten start

// can cause problems for monsters on top of a player,
// so only players
if (other.classtype != CT_PLAYER)
return;
if (other.health <= 0)
return;

if ((!(other.flags & FL_ONGROUND)) &&
((other.absmin_z >= self.absmax_z - 2)))
{
other.flags = other.flags + FL_ONGROUND;
}

// you can add other stuff like pushable players/monsters here

// 1998-09-16 Sliding/not-jumping on monsters/boxes/players
// fix by Maddes/Kryten end
};
#endif

//==============================================================
// Initialization
//==============================================================

#ifdef SSQC
//--------------------------------------------------------------
// SelectSpawnPoint -- Returns the entity to spawn at
//--------------------------------------------------------------
entity() player_init_selectspawnpoint =
{
local entity spot, thing;
local float pcount;

// testinfo_player_start is only found in regioned levels
spot = findfloat (world, classtype, CT_INFO_TESTPLAYERSTART);
if (spot)
return spot;

// choose a info_player_deathmatch point
if (coop)
{
lastspawn = findfloat (lastspawn, classtype,
CT_INFO_PLAYER_COOP);
if (lastspawn == world)
lastspawn = findfloat (lastspawn, classtype,
CT_INFO_PLAYER_START);
if (lastspawn != world)
return lastspawn;
}
else if (deathmatch)
{
spot = lastspawn;
// TODO CEV this loops infinitely if no
// info_player_deathmatch
while (1)
{
spot = findfloat (spot, classtype,
CT_INFO_PLAYER_DEATHMATCH);
if (spot != world)
{
if (spot == lastspawn)
return lastspawn;
pcount = 0;
thing = findradius (spot.origin, 32);
while (thing)
{
if (thing.classtype==CT_PLAYER)
pcount = pcount + 1;
thing = thing.chain;
}
if (pcount == 0)
{
lastspawn = spot;
return spot;
}
}
}
}

if (serverflags)
{
// return with a rune to start
spot = findfloat (world, classtype,
CT_INFO_PLAYER_START2);
if (spot)
return spot;
}

spot = findfloat (world, classtype, CT_INFO_PLAYER_START);
if (!spot)
error ("player_init_selectspawnpoint: "
"no info_player_start on level");

return spot;
};

//--------------------------------------------------------------
void() player_init_level_parms =
{
// Reset the player's inventory if they returned to the
// start map with a rune, or if the mapper set the
// "reset_items" field of worldspawn to a non-zero value.
// (The old "reset_items" check, which this replaces,
// had a comment from dumptruck_ds thanking Spike.) -- iw
if ((serverflags != 0 && world.model == "maps/start.bsp") ||
world.reset_items != 0)
{
SetNewParms ();
}

self.items = parm1;
self.health = parm2;
self.armorvalue = parm3;
self.ammo_shells = parm4;
self.ammo_nails = parm5;
self.ammo_rockets = parm6;
self.ammo_cells = parm7;
self.weapon = parm8;
self.armortype = parm9 * 0.01;
};

//--------------------------------------------------------------
// respawn -- called by ClientKill and DeadThink
//--------------------------------------------------------------
void() player_respawn =
{
if (coop)
{
// make a copy of the dead body for appearances sake
CopyToBodyQue (self);
// get the spawn parms as they were at level start
setspawnparms (self);
// respawn
player_init (self);
}
else if (deathmatch)
{
// make a copy of the dead body for appearances sake
CopyToBodyQue (self);
// set default spawn parms
SetNewParms ();
// respawn
player_init (self);
}
else
{
// restart the entire server
localcmd ("restart\n");
}
};
#endif

#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
// most of this was previously in PutClientInServer -- CEV
//--------------------------------------------------------------
void(entity e) player_init =
{
#ifdef SSQC
local entity spot = player_init_selectspawnpoint ();
#endif

// block common to both client & server -- CEV
e.classname = "player";
e.classtype = CT_PLAYER;
e.solid = SOLID_SLIDEBOX;
e.movetype = MOVETYPE_WALK;
e.touch = player_touch;

#ifdef CSQC
e.customphysics = sub_null;
e.drawmask = DRAWMASK_NORMAL;
e.predraw = player_predraw;
e.preframe = player_prediction_preframe;
e.postframe = player_prediction_postframe;
e.removefunc = player_remove;
e.view_ofs = PM_STAND_VIEWOFS;
e.velocity = '0 0 0';

setmodelindex (e, e.modelindex);
if (e.pm_flags & PMF_CROUCHED)
setsize (e, PM_CROUCH_MIN, PM_CROUCH_MAX);
else
setsize (e, PM_STAND_MIN, PM_STAND_MAX);
setorigin (e, e.origin);
#endif

#ifdef SSQC
e.flags = FL_CLIENT;
e.effects = 0;
e.gravity = 0;
e.wantedgravity = 0;
e.health = PLAYER_HEALTH;
e.takedamage = DAMAGE_AIM;
e.show_hostile = 0;
e.max_health = 100;
e.air_finished = time + 12;
// initial water damage
e.dmg = 2;
e.super_damage_finished = 0;
e.radsuit_finished = 0;
e.invisible_finished = 0;
e.invincible_finished = 0;
e.invincible_time = 0;
e.deathtype = "";
// support for item_key_custom -- iw
e.customkeys = 0;

// Setup cutscene stuff. Legacy code from Zerstorer.
// -- dumptruck_ds
e.script_count = 2;
e.script_delay = 1;
e.script_time = 0;

player_init_level_parms ();
player_set_current_ammo ();

e.attack_finished = time;
e.th_pain = player_pain;
e.destroy = player_destroy;
e.contentstransition = base_monster_contentstransition;
e.SendEntity = player_netsend;
e.deadflag = DEAD_NO;
// pausetime is set by teleporters to keep the player
// from moving for a while
e.pausetime = 0;

e.origin = spot.origin + '0 0 1';
e.angles = spot.angles;
// turn this way immediately
e.fixangle = TRUE;

// fog control.
// Looks if there's any fog values set at the current
// spawn point. If not, looks for those in worldspawn instead
if (spot.fog_density)
fog_save (e, spot.fog_density, spot.fog_color);
else if (world.fog_density)
fog_save (e, world.fog_density, world.fog_color);

if (spot.skyfog_density)
skyfog_save (e, spot.skyfog_density);
else if (world.skyfog_density)
skyfog_save (e, world.skyfog_density);

// decreased on subsequent frames, used to start some
// fog-related stuff
clean_up_client_stuff = 2;

// oh, this is a hack!
setmodel (e, "progs/eyes.mdl");
modelindex_eyes = e.modelindex;

// Drake -- dumptruck_ds
setmodel (e, "progs/s_null.spr");
// Drake -- dumptruck_ds
// setmodel (e, "progs/null_256.spr");
mindex_inviso = e.modelindex;

setmodel (e, "progs/player.mdl");
modelindex_player = e.modelindex;

setsize (e, PM_STAND_MIN, PM_STAND_MAX);
e.view_ofs = PM_STAND_VIEWOFS;
// Mod - Xian (May.20.97)
// Bug where player would have velocity from their last kill
e.velocity = '0 0 0';
// 1998-07-21 Player moves after respawn fix by Xian

// full send the new entity -- CEV
e.SendFlags = 0xffffff;

// pl_stand1 needs 'self' to be 'e' -- CEV
if (self == e)
pl_stand1 ();
else
sub_runvoidas (e, pl_stand1);

if (deathmatch || coop)
{
makevectors (e.angles);
spawn_tfog (e.origin + v_forward * 20);
}

spawn_tdeath (e.origin, e);
#endif
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
strip void() player =
{
player_init (self);
};
#endif
// };

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

#ifdef SSQC
/*QUAKED gib_head_player (0 0.5 0.8) (-16 -16 0) (16 16 56) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ("progs/h_player.mdl");
}*/
//----------------------------------------------------------------------
// class gib_head_player: base_gib_head
// {
//--------------------------------------------------------------
// ThrowHead
//--------------------------------------------------------------
void(entity act, vector dir, float dmg) throw_gib_head_player =
{
base_gib_head_throw (act, dir, dmg, gib_head_player_init);
};

//--------------------------------------------------------------
void(entity e) gib_head_player_init =
{
// don't reset class if passed a client entity -- CEV
if (!(e.flags & FL_CLIENT))
{
e.classname = "gib_head_player";
e.classtype = CT_GORE_HEAD_PLAYER;
}

// gib_init interprets spawnflags and will set .solid -- CEV
base_gib_head_init (e);

if (e.mdl_head != "")
{
precache_model (e.mdl_head);
setmodel (e, e.mdl_head);
e.SendFlags |= PLAYER_NET_MODEL | PLAYER_NET_SOLID |
PLAYER_NET_SIZE;
}
else
{
precache_model ("progs/h_player.mdl");
setmodel (e, "progs/h_player.mdl");
if (e.solid == SOLID_BBOX)
setsize (e, PLAYER_HEAD_MINS, PLAYER_HEAD_MAXS);
else if (e.solid == SOLID_TRIGGER)
setsize (e, '-16 -16 0', '16 16 56');
e.SendFlags |= PLAYER_NET_MODEL | PLAYER_NET_SOLID |
PLAYER_NET_SIZE;
}

e.frame = 0;
};

//--------------------------------------------------------------
void() gib_head_player =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

gib_head_player_init (self);
};
// };
#endif

#ifdef SSQC
/*QUAKED player_dead_axe (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ({"path":"progs/player.mdl","frame":49});
}
*/
void() player_dead_axe =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

precache_model ("progs/player.mdl");
setmodel (self, "progs/player.mdl");
self.frame = $axdeth9;

if (self.spawnflags & 1)
{
self.solid = SOLID_BBOX;
setsize (self, PLAYER_CORPSE_AX_MINS, PLAYER_CORPSE_AX_MAXS);
}
else
{
self.solid = SOLID_NOT;
}
};
#endif

#ifdef SSQC
/*QUAKED player_dead_face_down (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ({"path":"progs/player.mdl","frame":84});
}
*/
void() player_dead_face_down =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

precache_model ("progs/player.mdl");
setmodel (self, "progs/player.mdl");
self.frame = $deathc14;

if (self.spawnflags & 1)
{
self.solid = SOLID_BBOX;
setsize (self, PLAYER_CORPSE_C_MINS, PLAYER_CORPSE_C_MAXS);
}
else
{
self.solid = SOLID_NOT;
}
};
#endif

#ifdef SSQC
/*QUAKED player_dead_on_side (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ({"path":"progs/player.mdl","frame":102});
}
*/
void() player_dead_on_side =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

precache_model ("progs/player.mdl");
setmodel (self, "progs/player.mdl");
self.frame = $deathe9;

if (self.spawnflags & 1)
{
self.solid = SOLID_BBOX;
setsize (self, PLAYER_CORPSE_E_MINS, PLAYER_CORPSE_E_MAXS);
}
else
{
self.solid = SOLID_NOT;
}
};
#endif

//======================================================================
// END Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds
//======================================================================

Return to the top of this page or return to the overview of this repo.

Log playerclient.qc

Return to the top of this page or return to the overview of this repo.