thirtyflightsofloving/missionpack/p_view.c
Knightmare66 3ce18b138c Refactored spincontrol menu control with value lists, simplifying menu implementations.
Simplified loading and saving of cvars in slider menu control.
Enlarged text in Game, Multiplayer, and Options menus.
Fixed repeat of failed file causing HTTP downloads to restart.
Added cl_zoommode cvar to simplify Lazarus zoom command.
Changed zoom command to use new cl_zoommode cvar in default Lazarus and missionpack DLLs.
Removed unused "crossh" cvar in default Lazarus and missionpack DLLs.
Fixed Makron not having a classname when spawned from Jorg in default Lazarus and missionpack DLLs.
Made Tactician Gunner ignore small amounts of damage in missionpack DLL.
2021-09-04 02:18:06 -04:00

1754 lines
46 KiB
C

#include "g_local.h"
#include "m_player.h"
static edict_t *current_player;
static gclient_t *current_client;
static vec3_t forward, right, up;
float xyspeed;
float bobmove;
int bobcycle; // odd cycles are right foot going forward
float bobfracsin; // sin(bobfrac*M_PI)
qboolean PlayerOnFloor (edict_t *player);
/*
===============
SV_CalcRoll
===============
*/
float SV_CalcRoll (vec3_t angles, vec3_t velocity)
{
float sign;
float side;
float value;
side = DotProduct (velocity, right);
sign = side < 0 ? -1 : 1;
side = fabs(side);
value = sv_rollangle->value;
if (side < sv_rollspeed->value)
side = side * value / sv_rollspeed->value;
else
side = value;
return side*sign;
}
/*
===============
P_DamageFeedback
Handles color blends and view kicks
===============
*/
void P_DamageFeedback (edict_t *player)
{
gclient_t *client;
float side;
float realcount, count, kick;
vec3_t v;
int r, l;
static vec3_t power_color = {0.0, 1.0, 0.0};
static vec3_t acolor = {1.0, 1.0, 1.0};
static vec3_t bcolor = {1.0, 0.0, 0.0};
client = player->client;
// flash the backgrounds behind the status numbers
client->ps.stats[STAT_FLASHES] = 0;
if (client->damage_blood)
client->ps.stats[STAT_FLASHES] |= 1;
if (client->damage_armor && !(player->flags & FL_GODMODE) && (client->invincible_framenum <= level.framenum))
client->ps.stats[STAT_FLASHES] |= 2;
// total points of damage shot at the player this frame
count = (client->damage_blood + client->damage_armor + client->damage_parmor);
if (count == 0)
return; // didn't take any damage
// start a pain animation if still in the player model
if (client->anim_priority < ANIM_PAIN && player->s.modelindex == (MAX_MODELS-1)) //was 255
{
static int i;
client->anim_priority = ANIM_PAIN;
if (client->ps.pmove.pm_flags & PMF_DUCKED)
{
player->s.frame = FRAME_crpain1-1;
client->anim_end = FRAME_crpain4;
}
else
{
i = (i+1)%3;
switch (i)
{
case 0:
player->s.frame = FRAME_pain101-1;
client->anim_end = FRAME_pain104;
break;
case 1:
player->s.frame = FRAME_pain201-1;
client->anim_end = FRAME_pain204;
break;
case 2:
player->s.frame = FRAME_pain301-1;
client->anim_end = FRAME_pain304;
break;
}
}
}
realcount = count;
if (count < 10)
count = 10; // always make a visible effect
// play an apropriate pain sound
if ((level.time > player->pain_debounce_time) && !(player->flags & FL_GODMODE) && (client->invincible_framenum <= level.framenum))
{
r = 1 + (rand()&1);
player->pain_debounce_time = level.time + 0.7;
if (player->health < 25)
l = 25;
else if (player->health < 50)
l = 50;
else if (player->health < 75)
l = 75;
else
l = 100;
gi.sound (player, CHAN_VOICE, gi.soundindex(va("*pain%i_%i.wav", l, r)), 1, ATTN_NORM, 0);
}
// the total alpha of the blend is always proportional to count
if (client->damage_alpha < 0)
client->damage_alpha = 0;
client->damage_alpha += count*0.01;
if (client->damage_alpha < 0.2)
client->damage_alpha = 0.2;
if (client->damage_alpha > 0.6)
client->damage_alpha = 0.6; // don't go too saturated
// the color of the blend will vary based on how much was absorbed
// by different armors
VectorClear (v);
if (client->damage_parmor)
VectorMA (v, (float)client->damage_parmor/realcount, power_color, v);
if (client->damage_armor)
VectorMA (v, (float)client->damage_armor/realcount, acolor, v);
if (client->damage_blood)
VectorMA (v, (float)client->damage_blood/realcount, bcolor, v);
VectorCopy (v, client->damage_blend);
//
// calculate view angle kicks
//
kick = abs(client->damage_knockback);
if (kick && player->health > 0) // kick of 0 means no view adjust at all
{
kick = kick * 100 / player->health;
if (kick < count*0.5)
kick = count*0.5;
if (kick > 50)
kick = 50;
VectorSubtract (client->damage_from, player->s.origin, v);
VectorNormalize (v);
side = DotProduct (v, right);
client->v_dmg_roll = kick*side*0.3;
side = -DotProduct (v, forward);
client->v_dmg_pitch = kick*side*0.3;
client->v_dmg_time = level.time + DAMAGE_TIME;
}
//
// clear totals
//
client->damage_blood = 0;
client->damage_armor = 0;
client->damage_parmor = 0;
client->damage_knockback = 0;
}
//Knightmare- Gen cam code
/*======================================================================
//Skid added
//Common stuff in the 4 View Offset Functions
//end Skid
======================================================================*/
/*static*/ void CommonViewOffsets (edict_t *ent, vec3_t v)
{
// absolutely bound offsets
// so the view can never be outside the player box
//CHASECAM added
if (ent->client->chaseactive)
{
VectorSet (v, 0, 0, 0);
if (ent->client->chasecam != NULL)
{
ent->client->ps.pmove.origin[0] = ent->client->chasecam->s.origin[0]*8;
ent->client->ps.pmove.origin[1] = ent->client->chasecam->s.origin[1]*8;
ent->client->ps.pmove.origin[2] = ent->client->chasecam->s.origin[2]*8;
VectorCopy (ent->client->chasecam->s.angles, ent->client->ps.viewangles);
}
}
//CHASECAM added
// Lazarus
else if (ent->client->spycam)
{
VectorSet (v, 0, 0, 0);
VectorCopy (ent->client->spycam->s.angles, ent->client->ps.viewangles);
if (ent->client->spycam->svflags & SVF_MONSTER)
ent->client->ps.viewangles[PITCH] = ent->client->spycam->move_angles[PITCH];
}
// if (!ent->client->chasetoggle)
else
{
if (v[0] < -14)
v[0] = -14;
else if (v[0] > 14)
v[0] = 14;
if (v[1] < -14)
v[1] = -14;
else if (v[1] > 14)
v[1] = 14;
if (v[2] < -22)
v[2] = -22;
else if (v[2] > 30)
v[2] = 30;
}
VectorCopy (v, ent->client->ps.viewoffset);
}
/*
===============
SV_CalcViewOffset
Auto pitching on slopes?
fall from 128: 400 = 160000
fall from 256: 580 = 336400
fall from 384: 720 = 518400
fall from 512: 800 = 640000
fall from 640: 960 =
damage = deltavelocity*deltavelocity * 0.0001
===============
*/
void SV_CalcViewOffset (edict_t *ent)
{
float *angles;
float bob;
float ratio;
float delta;
vec3_t v;
//===================================
// base angles
angles = ent->client->ps.kick_angles;
// if dead, fix the angle and don't add any kick
if (ent->deadflag)
{
if (ent->deadflag != DEAD_FROZEN)
{
VectorClear (angles);
if (ent->flags & FL_SAM_RAIMI)
{
ent->client->ps.viewangles[ROLL] = 0;
ent->client->ps.viewangles[PITCH] = 0;
}
else
{
ent->client->ps.viewangles[ROLL] = 40;
ent->client->ps.viewangles[PITCH] = -15;
}
ent->client->ps.viewangles[YAW] = ent->client->killer_yaw;
}
}
else
{
// add angles based on weapon kick
VectorCopy (ent->client->kick_angles, angles);
// add angles based on damage kick
ratio = (ent->client->v_dmg_time - level.time) / DAMAGE_TIME;
if (ratio < 0)
{
ratio = 0;
ent->client->v_dmg_pitch = 0;
ent->client->v_dmg_roll = 0;
}
angles[PITCH] += ratio * ent->client->v_dmg_pitch;
angles[ROLL] += ratio * ent->client->v_dmg_roll;
// Knightmare- no bobbing if player is controlling a turret
if (ent->flags & FL_TURRET_OWNER)
return;
// add pitch based on fall kick
ratio = (ent->client->fall_time - level.time) / FALL_TIME;
if (ratio < 0)
ratio = 0;
angles[PITCH] += ratio * ent->client->fall_value;
// add angles based on velocity
delta = DotProduct (ent->velocity, forward);
angles[PITCH] += delta*run_pitch->value;
delta = DotProduct (ent->velocity, right);
angles[ROLL] += delta*run_roll->value;
// add angles based on bob
delta = bobfracsin * bob_pitch->value * xyspeed;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
delta *= 6; // crouching
angles[PITCH] += delta;
delta = bobfracsin * bob_roll->value * xyspeed;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
delta *= 6; // crouching
if (bobcycle & 1)
delta = -delta;
angles[ROLL] += delta;
}
//===================================
// base origin
VectorClear (v);
// add view height
v[2] += ent->viewheight;
// add fall height
ratio = (ent->client->fall_time - level.time) / FALL_TIME;
if (ratio < 0)
ratio = 0;
v[2] -= ratio * ent->client->fall_value * 0.4;
// add bob height
bob = bobfracsin * xyspeed * bob_up->value;
if (bob > 6)
bob = 6;
//gi.DebugGraph (bob *2, 255);
v[2] += bob;
// add kick offset
VectorAdd (v, ent->client->kick_origin, v);
// CommonViewOffsets(ent, v);
// absolutely bound offsets
// so the view can never be outside the player box
// Zaero
if (ent->client->zCameraTrack)
{
int i;
VectorAdd (ent->client->zCameraTrack->s.origin, ent->client->zCameraOffset, v);
if (ent->client->zCameraTrack->client)
{
vec3_t f;
VectorAdd(ent->client->zCameraTrack->client->ps.viewoffset, v, v);
// AngleVectors (ent->client->zCameraTrack->client->v_angle, f, NULL, NULL);
AngleVectors (ent->client->zCameraTrack->s.angles, f, NULL, NULL);
VectorMA(v, 10, f, v);
}
else if (Q_stricmp(ent->client->zCameraTrack->classname, "misc_securitycamera") == 0)
{
float framepercent = sin(((float)(level.framenum & 63) / 64.0) * M_PI * 2);
VectorCopy(ent->client->zCameraTrack->move_origin, v);
VectorCopy(ent->client->zCameraTrack->move_angles, ent->client->ps.viewangles);
// adjust yaw a bit due to sway
ent->client->ps.viewangles[YAW] += framepercent * 15;
}
else
VectorCopy (ent->client->zCameraTrack->s.angles, ent->client->ps.viewangles);
for (i = 0; i < 3; i++)
{
ent->client->ps.pmove.origin[i] = v[i] * 8;
}
VectorSet (ent->client->ps.viewoffset, 0, 0, 0);
// make our "double" do what we're doing
if (ent->client->zCameraLocalEntity)
{
edict_t *e = ent->client->zCameraLocalEntity;
VectorCopy(ent->s.origin, e->s.origin);
e->s.frame = ent->s.frame;
e->s.modelindex = ent->s.modelindex;
e->s.modelindex2 = ent->s.modelindex2;
e->s.skinnum = ent->s.skinnum;
}
}
else
// end Zaero
{
// CHASECAM added
if (ent->client->chaseactive)
{
VectorSet (v, 0, 0, 0);
if (ent->client->chasecam != NULL)
{
ent->client->ps.pmove.origin[0] = ent->client->chasecam->s.origin[0]*8;
ent->client->ps.pmove.origin[1] = ent->client->chasecam->s.origin[1]*8;
ent->client->ps.pmove.origin[2] = ent->client->chasecam->s.origin[2]*8;
VectorCopy (ent->client->chasecam->s.angles, ent->client->ps.viewangles);
}
}
// CHASECAM added
// Lazarus
else if (ent->client->spycam)
{
VectorSet (v, 0, 0, 0);
VectorCopy (ent->client->spycam->s.angles, ent->client->ps.viewangles);
if (ent->client->spycam->svflags & SVF_MONSTER)
ent->client->ps.viewangles[PITCH] = ent->client->spycam->move_angles[PITCH];
}
else
{
if (v[0] < -14)
v[0] = -14;
else if (v[0] > 14)
v[0] = 14;
if (v[1] < -14)
v[1] = -14;
else if (v[1] > 14)
v[1] = 14;
if (v[2] < -22)
v[2] = -22;
else if (v[2] > 30)
v[2] = 30;
}
VectorCopy (v, ent->client->ps.viewoffset);
}
}
/*
==============
SV_CalcGunOffset
==============
*/
void SV_CalcGunOffset (edict_t *ent)
{
int i;
float delta;
// ROGUE
static gitem_t *heatbeam;
if (!heatbeam)
heatbeam = FindItemByClassname ("weapon_plasmabeam");
// ROGUE - heatbeam shouldn't bob so the beam looks right
if (ent->client->pers.weapon != heatbeam)
{
// ROGUE
// gun angles from bobbing
ent->client->ps.gunangles[ROLL] = xyspeed * bobfracsin * 0.005;
ent->client->ps.gunangles[YAW] = xyspeed * bobfracsin * 0.01;
if (bobcycle & 1)
{
ent->client->ps.gunangles[ROLL] = -ent->client->ps.gunangles[ROLL];
ent->client->ps.gunangles[YAW] = -ent->client->ps.gunangles[YAW];
}
ent->client->ps.gunangles[PITCH] = xyspeed * bobfracsin * 0.005;
// gun angles from delta movement
for (i=0 ; i<3 ; i++)
{
delta = ent->client->oldviewangles[i] - ent->client->ps.viewangles[i];
if (delta > 180)
delta -= 360;
if (delta < -180)
delta += 360;
if (delta > 45)
delta = 45;
if (delta < -45)
delta = -45;
if (i == YAW)
ent->client->ps.gunangles[ROLL] += 0.1*delta;
ent->client->ps.gunangles[i] += 0.2 * delta;
}
}
// ROGUE
else
{
for (i=0; i<3; i++)
ent->client->ps.gunangles[i] = 0;
}
//ROGUE
// gun height
VectorClear (ent->client->ps.gunoffset);
// ent->ps->gunorigin[2] += bob;
// gun_x / gun_y / gun_z are development tools
for (i=0 ; i<3 ; i++)
{
ent->client->ps.gunoffset[i] += forward[i]*(gun_y->value);
ent->client->ps.gunoffset[i] += right[i]*gun_x->value;
ent->client->ps.gunoffset[i] += up[i]* (-gun_z->value);
}
}
/*
=============
SV_AddBlend
=============
*/
void SV_AddBlend (float r, float g, float b, float a, float *v_blend)
{
float a2, a3;
if (a <= 0)
return;
a2 = v_blend[3] + (1-v_blend[3])*a; // new total alpha
a3 = v_blend[3]/a2; // fraction of color from old
v_blend[0] = v_blend[0]*a3 + r*(1-a3);
v_blend[1] = v_blend[1]*a3 + g*(1-a3);
v_blend[2] = v_blend[2]*a3 + b*(1-a3);
v_blend[3] = a2;
}
/*
=============
SV_CalcBlend
=============
*/
void SV_CalcBlend (edict_t *ent)
{
int contents;
vec3_t vieworg;
int remaining;
ent->client->ps.blend[0] = ent->client->ps.blend[1] =
ent->client->ps.blend[2] = ent->client->ps.blend[3] = 0;
// add for contents
// if (ent->client->chasetoggle)
if (ent->client->chaseactive) //Knightmare- different check for chasecam mode
VectorCopy (ent->client->chasecam->s.origin, vieworg);
else
VectorAdd (ent->s.origin, ent->client->ps.viewoffset, vieworg);
contents = gi.pointcontents (vieworg);
if (contents & (CONTENTS_LAVA|CONTENTS_SLIME|CONTENTS_WATER) )
ent->client->ps.rdflags |= RDF_UNDERWATER;
else
ent->client->ps.rdflags &= ~RDF_UNDERWATER;
if (contents & CONTENTS_LAVA) //(CONTENTS_SOLID|CONTENTS_LAVA))
SV_AddBlend (1.0, 0.3, 0.0, 0.6, ent->client->ps.blend);
else if (contents & CONTENTS_SLIME)
SV_AddBlend (0.0, 0.1, 0.05, 0.6, ent->client->ps.blend);
else if (contents & CONTENTS_WATER)
{
if (ent->in_mud == 3)
SV_AddBlend (0.4, 0.3, 0.2, 0.9, ent->client->ps.blend);
else
SV_AddBlend (0.5, 0.3, 0.2, 0.4, ent->client->ps.blend);
}
// add for powerups
#ifdef JETPACK_MOD
if ( ent->client->jetpack )
{
remaining = ent->client->pers.inventory[fuel_index];
// beginning to fade if 4 secs or less
if (remaining > 40)
{
if ( ((level.framenum % 6) == 0) && ( level.framenum - ent->client->jetpack_activation > 30 ) )
{
if (ent->client->jetpack_thrusting && (level.framenum - ent->client->jetpack_start_thrust > 10))
gi.sound (ent, CHAN_AUTO, gi.soundindex("jetpack/revrun.wav"), 1, ATTN_NORM, 0);
gi.sound (ent, CHAN_GIZMO, gi.soundindex("jetpack/running.wav"), 1, ATTN_NORM, 0);
}
}
}
#endif // #ifdef JETPACK_MOD
if (ent->client->quad_framenum > level.framenum)
{
remaining = ent->client->quad_framenum - level.framenum;
if (remaining == 30) // beginning to fade
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage2.wav"), 1, ATTN_NORM, 0);
if (remaining > 30 || (remaining & 4) )
SV_AddBlend (0, 0, 1, 0.08, ent->client->ps.blend);
}
// PMM - double damage
else if (ent->client->double_framenum > level.framenum)
{
remaining = ent->client->double_framenum - level.framenum;
if (remaining == 30) // beginning to fade
gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage2.wav"), 1, ATTN_NORM, 0);
if (remaining > 30 || (remaining & 4) )
SV_AddBlend (0.9, 0.7, 0, 0.08, ent->client->ps.blend);
}
// PMM
// RAFAEL
else if (ent->client->quadfire_framenum > level.framenum)
{
remaining = ent->client->quadfire_framenum - level.framenum;
if (remaining == 30) // beginning to fade
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/quadfire2.wav"), 1, ATTN_NORM, 0);
if (remaining > 30 || (remaining & 4) )
SV_AddBlend (1, 0.2, 0.5, 0.08, ent->client->ps.blend);
}
else if (ent->client->invincible_framenum > level.framenum)
{
remaining = ent->client->invincible_framenum - level.framenum;
if (remaining == 30) // beginning to fade
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/protect2.wav"), 1, ATTN_NORM, 0);
if (remaining > 30 || (remaining & 4) )
SV_AddBlend (1, 1, 0, 0.08, ent->client->ps.blend);
}
else if (ent->client->enviro_framenum > level.framenum)
{
remaining = ent->client->enviro_framenum - level.framenum;
if (remaining == 30) // beginning to fade
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0);
if (remaining > 30 || (remaining & 4) )
SV_AddBlend (0, 1, 0, 0.08, ent->client->ps.blend);
}
else if (ent->client->breather_framenum > level.framenum)
{
remaining = ent->client->breather_framenum - level.framenum;
if (remaining == 30) // beginning to fade
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0);
if (remaining > 30 || (remaining & 4) )
SV_AddBlend (0.4, 1, 0.4, 0.04, ent->client->ps.blend);
}
//PGM
if (ent->client->nuke_framenum > level.framenum)
{
float brightness;
brightness = (ent->client->nuke_framenum - level.framenum) / 20.0;
SV_AddBlend (1, 1, 1, brightness, ent->client->ps.blend);
}
if (ent->client->ir_framenum > level.framenum)
{
remaining = ent->client->ir_framenum - level.framenum;
if (remaining > 30 || (remaining & 4))
{
ent->client->ps.rdflags |= RDF_IRGOGGLES;
SV_AddBlend (1, 0, 0, 0.2, ent->client->ps.blend);
}
else
ent->client->ps.rdflags &= ~RDF_IRGOGGLES;
}
else
{
ent->client->ps.rdflags &= ~RDF_IRGOGGLES;
}
//PGM
// added stasis generator support
if (level.freeze && (level.freezeframes % 30 == 0))
{
if (level.freezeframes == (sk_stasis_time->value*10 - 30)) // was 270
gi.sound(ent,CHAN_ITEM,gi.soundindex("items/stasis_stop.wav"), 1, ATTN_NORM, 0);
else
gi.sound(ent,CHAN_ITEM,gi.soundindex("items/stasis.wav"), 1, ATTN_NORM, 0);
}
// add for damage
if (ent->client->damage_alpha > 0)
SV_AddBlend (ent->client->damage_blend[0],ent->client->damage_blend[1]
,ent->client->damage_blend[2], ent->client->damage_alpha, ent->client->ps.blend);
if (ent->client->bonus_alpha > 0)
SV_AddBlend (0.85, 0.7, 0.3, ent->client->bonus_alpha, ent->client->ps.blend);
// Zaero added
// for blinding
if (ent->client->flashTime > 0)
{
float alpha = (float)ent->client->flashTime / (float)ent->client->flashBase;
if (alpha > 1)
alpha = 1;
SV_AddBlend (1, 1, 1, alpha, ent->client->ps.blend);
ent->client->flashTime--;
}
if (ent->client->zCameraStaticFramenum > level.time) {
SV_AddBlend (1, 1, 1, 1, ent->client->ps.blend);
}
// end Zaero
// drop the damage value
ent->client->damage_alpha -= 0.06;
if (ent->client->damage_alpha < 0)
ent->client->damage_alpha = 0;
// drop the bonus value
ent->client->bonus_alpha -= 0.1;
if (ent->client->bonus_alpha < 0)
ent->client->bonus_alpha = 0;
// DWH: Screen fade from target_failure or target_fade
if (ent->client->fadein > 0)
{
float alpha;
// Turn off fade for dead software players or they won't see menu
if ((ent->health <= 0) && (Q_stricmp(vid_ref->string,"gl")) && (Q_stricmp(vid_ref->string,"kmgl")))
ent->client->fadein = 0;
if (ent->client->fadein > level.framenum)
{
alpha = ent->client->fadealpha*(1.0 - (ent->client->fadein-level.framenum)/(ent->client->fadein-ent->client->fadestart));
SV_AddBlend (ent->client->fadecolor[0],
ent->client->fadecolor[1],
ent->client->fadecolor[2],
alpha, ent->client->ps.blend);
}
else if (ent->client->fadehold > level.framenum)
{
SV_AddBlend (ent->client->fadecolor[0],
ent->client->fadecolor[1],
ent->client->fadecolor[2],
ent->client->fadealpha, ent->client->ps.blend);
}
else if (ent->client->fadeout > level.framenum)
{
alpha = ent->client->fadealpha*((ent->client->fadeout-level.framenum)/(ent->client->fadeout-ent->client->fadehold));
SV_AddBlend (ent->client->fadecolor[0],
ent->client->fadecolor[1],
ent->client->fadecolor[2],
alpha, ent->client->ps.blend);
}
else
ent->client->fadein = 0;
}
}
/*
=================
P_SlamDamage
Serves same purpose as P_FallingDamage, but detects wall impacts
=================
*/
void P_SlamDamage (edict_t *ent)
{
float delta;
int damage;
vec3_t dir;
vec3_t deltav;
if (ent->s.modelindex != (MAX_MODELS-1)) // was 255
return; // not in the player model
if (ent->movetype == MOVETYPE_NOCLIP)
return;
deltav[0] = ent->velocity[0] - ent->client->oldvelocity[0];
deltav[1] = ent->velocity[1] - ent->client->oldvelocity[1];
deltav[2] = 0;
delta = VectorLength(deltav);
delta = delta*delta * 0.0001;
if (delta > 40*(player_max_speed->value/300)) // Knightmare changed
{
if (ent->health > 0)
{
/* if (delta > 65)
ent->s.event = EV_FALLFAR;
else
ent->s.event = EV_FALL;*/
// play correct PPM sounds while in third person mode
if (delta >= 65*(player_max_speed->value/300)) // Knightmare changed
gi.sound(ent, CHAN_VOICE, gi.soundindex("*fall1.wav"), 1.0, ATTN_NORM, 0);
else
gi.sound(ent, CHAN_VOICE, gi.soundindex("*fall2.wav"), 1.0, ATTN_NORM, 0);
}
ent->pain_debounce_time = level.time; // no normal pain sound
damage = (delta-40*(player_max_speed->value/300))/2; // Knightmare changed
if (damage < 1)
damage = 1;
VectorCopy(deltav,dir);
VectorNegate(dir,dir);
VectorNormalize(dir);
if (!deathmatch->value || !((int)dmflags->value & DF_NO_FALLING) )
T_Damage (ent, world, world, dir, ent->s.origin, vec3_origin, damage, 0, 0, MOD_FALLING);
}
}
/*
=================
P_FallingDamage
=================
*/
void P_FallingDamage (edict_t *ent)
{
float delta;
int damage;
vec3_t dir;
if (ent->s.modelindex != (MAX_MODELS-1)) //was 255
return; // not in the player model
// Knightmare- no falling if player is controlling a turret
if (ent->flags & FL_TURRET_OWNER)
return;
if (ent->movetype == MOVETYPE_NOCLIP)
return;
if (ent->client->jetpack && ent->client->ucmd.upmove > 0)
return;
if ((ent->client->oldvelocity[2] < 0) && (ent->velocity[2] > ent->client->oldvelocity[2]) && (!ent->groundentity))
{
delta = ent->client->oldvelocity[2];
}
else
{
if (!ent->groundentity)
return;
delta = ent->velocity[2] - ent->client->oldvelocity[2];
}
delta = delta*delta * 0.0001;
// never take falling damage if completely underwater
if (ent->waterlevel == 3)
return;
if (ent->waterlevel == 2)
delta *= 0.25;
if (ent->waterlevel == 1)
delta *= 0.5;
if (delta < 1)
return;
// Lazarus: Changed here to NOT play footstep sounds if ent isn't on the ground.
// So player will no longer play footstep sounds when descending a ladder.
if (delta < 7) // Knightmare- was 15, changed to 7
{
if (!(ent->watertype & CONTENTS_MUD) && !ent->vehicle && !ent->turret && (ent->groundentity || PlayerOnFloor(ent)) )
#ifndef FMOD_FOOTSTEPS
ent->s.event = EV_FOOTSTEP; // Knightmare- move Lazarus footsteps client-side
#else
FootStep(ent);
#endif
return;
}
ent->client->fall_value = delta*0.5;
if (ent->client->fall_value > 40)
ent->client->fall_value = 40;
ent->client->fall_time = level.time + FALL_TIME;
if (delta > 30)
{
if (ent->health > 0)
{
/* if (delta >= 55)
ent->s.event = EV_FALLFAR;
else
ent->s.event = EV_FALL;*/
// play correct PPM sounds while in third person mode
if (delta >= 55)
gi.sound(ent, CHAN_VOICE, gi.soundindex("*fall1.wav"), 1.0, ATTN_NORM, 0);
else
gi.sound(ent, CHAN_VOICE, gi.soundindex("*fall2.wav"), 1.0, ATTN_NORM,0);
if (world->effects & FX_WORLDSPAWN_ALERTSOUNDS)
PlayerNoise(ent,ent->s.origin,PNOISE_SELF);
}
ent->pain_debounce_time = level.time; // no normal pain sound
damage = (delta-30)/2;
if (damage < 1)
damage = 1;
VectorSet (dir, 0, 0, 1);
if (!deathmatch->value || !((int)dmflags->value & DF_NO_FALLING) )
T_Damage (ent, world, world, dir, ent->s.origin, vec3_origin, damage, 0, 0, MOD_FALLING);
}
else if (delta > 15)
{
ent->s.event = EV_FALLSHORT;
if (world->effects & FX_WORLDSPAWN_ALERTSOUNDS)
PlayerNoise(ent,ent->s.origin,PNOISE_SELF);
return;
}
else // if delta > 7
#ifndef FMOD_FOOTSTEPS
ent->s.event = EV_LOUDSTEP; // Knightmare- loud footstep for softer landing
#else
FootStep(ent);
#endif
}
/*
=============
P_WorldEffects
=============
*/
void P_WorldEffects (void)
{
qboolean breather;
qboolean envirosuit;
int waterlevel, old_waterlevel, old_watertype;
if (current_player->movetype == MOVETYPE_NOCLIP)
{
current_player->air_finished = level.time + 12; // don't need air
return;
}
waterlevel = current_player->waterlevel;
old_waterlevel = current_client->old_waterlevel;
old_watertype = current_player->old_watertype;
current_client->old_waterlevel = waterlevel;
current_player->old_watertype = current_player->watertype;
breather = current_client->breather_framenum > level.framenum;
envirosuit = current_client->enviro_framenum > level.framenum;
//
// if just entered a water volume, play a sound
//
if (!old_waterlevel && waterlevel)
{
PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF);
if (current_player->watertype & CONTENTS_LAVA)
gi.sound (current_player, CHAN_BODY, gi.soundindex("player/lava_in.wav"), 1, ATTN_NORM, 0);
else if (current_player->watertype & CONTENTS_SLIME)
gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0);
else if (current_player->watertype & CONTENTS_MUD)
gi.sound (current_player, CHAN_BODY, gi.soundindex("mud/mud_in2.wav"), 1, ATTN_NORM, 0);
else if (current_player->watertype & CONTENTS_WATER)
gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0);
current_player->flags |= FL_INWATER;
// clear damage_debounce, so the pain sound will play immediately
current_player->damage_debounce_time = level.time - 1;
}
//
// if just completely exited a water volume, play a sound
//
if (old_waterlevel && ! waterlevel)
{
PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF);
if (old_watertype & CONTENTS_MUD)
gi.sound (current_player, CHAN_BODY, gi.soundindex("mud/mud_out1.wav"), 1, ATTN_NORM, 0);
else
gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_out.wav"), 1, ATTN_NORM, 0);
current_player->flags &= ~FL_INWATER;
}
//
// check for head just going under water
//
if (old_waterlevel != 3 && waterlevel == 3)
{
if (current_player->in_mud)
gi.sound (current_player, CHAN_BODY, gi.soundindex("mud/mud_un1.wav"), 1, ATTN_NORM, 0);
else
gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_un.wav"), 1, ATTN_NORM, 0);
}
//
// check for head just coming out of water
//
if (old_waterlevel == 3 && waterlevel != 3)
{
if (current_player->air_finished < level.time)
{ // gasp for air
gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/gasp1.wav"), 1, ATTN_NORM, 0);
PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF);
}
else if (current_player->air_finished < level.time + 11)
{ // just break surface
gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/gasp2.wav"), 1, ATTN_NORM, 0);
}
}
//
// check for drowning
//
if (waterlevel == 3)
{
#ifdef JETPACK_MOD
if ( current_player->client->jetpack )
{
if ( (current_player->watertype & (CONTENTS_LAVA|CONTENTS_SLIME)) && !(current_player->flags & FL_GODMODE ) ) // blow up in lava/slime
T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, current_player->health+1, 0, DAMAGE_NO_ARMOR, 0);
else
{
gitem_t *jetpack = FindItem("jetpack");
Use_Jet (current_player, jetpack); // shut down in water
}
}
#endif
// breather or envirosuit give air
if (breather || envirosuit)
{
current_player->air_finished = level.time + 10;
if (((int)(current_client->breather_framenum - level.framenum) % 25) == 0)
{
if (!current_client->breather_sound)
gi.sound (current_player, CHAN_AUTO, gi.soundindex("player/u_breath1.wav"), 1, ATTN_NORM, 0);
else
gi.sound (current_player, CHAN_AUTO, gi.soundindex("player/u_breath2.wav"), 1, ATTN_NORM, 0);
current_client->breather_sound ^= 1;
PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF);
//FIXME: release a bubble?
}
}
// if out of air, start drowning
if (current_player->air_finished < level.time)
{ // drown!
if (current_player->client->next_drown_time < level.time
&& current_player->health > 0)
{
current_player->client->next_drown_time = level.time + 1;
// take more damage the longer underwater
current_player->dmg += 2;
if (current_player->dmg > 15)
current_player->dmg = 15;
// play a gurp sound instead of a normal pain sound
if (current_player->health <= current_player->dmg)
gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/drown1.wav"), 1, ATTN_NORM, 0);
else if (rand()&1)
gi.sound (current_player, CHAN_VOICE, gi.soundindex("*gurp1.wav"), 1, ATTN_NORM, 0);
else
gi.sound (current_player, CHAN_VOICE, gi.soundindex("*gurp2.wav"), 1, ATTN_NORM, 0);
current_player->pain_debounce_time = level.time;
T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, current_player->dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER);
}
}
}
else
{
current_player->air_finished = level.time + 12;
current_player->dmg = 2;
}
//
// check for sizzle damage
//
if (waterlevel && (current_player->watertype&(CONTENTS_LAVA|CONTENTS_SLIME)) )
{
if (current_player->watertype & CONTENTS_LAVA)
{
if (current_player->health > 0
&& current_player->pain_debounce_time <= level.time
&& current_client->invincible_framenum < level.framenum)
{
if (rand()&1)
gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/burn1.wav"), 1, ATTN_NORM, 0);
else
gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/burn2.wav"), 1, ATTN_NORM, 0);
current_player->pain_debounce_time = level.time + 1;
}
if (envirosuit) // take 1/3 damage with envirosuit
T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1*waterlevel, 0, 0, MOD_LAVA);
else
T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 3*waterlevel, 0, 0, MOD_LAVA);
}
if (current_player->watertype & CONTENTS_SLIME)
{
if (!envirosuit)
{ // no damage from slime with envirosuit
T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1*waterlevel, 0, 0, MOD_SLIME);
}
}
}
}
/*
===============
G_SetClientEffects
===============
*/
void G_SetClientEffects (edict_t *ent)
{
int pa_type;
int remaining;
ent->s.effects = 0;
// ent->s.renderfx = 0;
// PGM - player is always ir visible, even dead.
ent->s.renderfx = RF_IR_VISIBLE;
if (ent->health <= 0 || level.intermissiontime)
return;
//=========
//PGM
if (ent->flags & FL_DISGUISED)
ent->s.renderfx |= RF_USE_DISGUISE;
if (gamerules && gamerules->value)
{
if (DMGame.PlayerEffects)
DMGame.PlayerEffects(ent);
}
//PGM
//=========
if (ent->powerarmor_time > level.time)
{
pa_type = PowerArmorType (ent);
if (pa_type == POWER_ARMOR_SCREEN)
{
ent->s.effects |= EF_POWERSCREEN;
}
else if (pa_type == POWER_ARMOR_SHIELD)
{
ent->s.effects |= EF_COLOR_SHELL;
ent->s.renderfx |= RF_SHELL_GREEN;
}
}
if (ent->client->quad_framenum > level.framenum)
{
remaining = ent->client->quad_framenum - level.framenum;
if (remaining > 30 || (remaining & 4) )
ent->s.effects |= EF_QUAD;
}
// RAFAEL
if (ent->client->quadfire_framenum > level.framenum)
{
remaining = ent->client->quadfire_framenum - level.framenum;
if (remaining > 30 || (remaining & 4) )
ent->s.effects |= EF_DOUBLE;
}
//=======
//ROGUE
if (ent->client->double_framenum > level.framenum)
{
remaining = ent->client->double_framenum - level.framenum;
if (remaining > 30 || (remaining & 4) )
ent->s.effects |= EF_DOUBLE;
}
if ((ent->client->owned_sphere) && (ent->client->owned_sphere->spawnflags == 1))
{
ent->s.effects |= EF_HALF_DAMAGE;
}
if (ent->client->tracker_pain_framenum > level.framenum)
{
ent->s.effects |= EF_TRACKERTRAIL;
}
//ROGUE
//=======
if (ent->client->invincible_framenum > level.framenum)
{
remaining = ent->client->invincible_framenum - level.framenum;
if (remaining > 30 || (remaining & 4) )
ent->s.effects |= EF_PENT;
}
// show god mode
if ( (coop->value || deathmatch->value) && (ent->flags & FL_GODMODE) && !(ent->client && ent->client->chaseactive) )
{
ent->s.effects |= EF_COLOR_SHELL;
ent->s.renderfx |= (RF_SHELL_RED|RF_SHELL_GREEN|RF_SHELL_BLUE);
}
//PGM
/*
if (ent->client->torch_framenum > level.framenum)
{
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_FLASHLIGHT);
gi.WritePosition (ent->s.origin);
gi.WriteShort (ent - g_edicts);
gi.multicast (ent->s.origin, MULTICAST_PVS);
}
*/
//PGM
//Knightmare- flashlight
if (ent->client->flashlight_active)
{
vec3_t forward;
vec3_t flashpoint;
trace_t tr;
int mask;
mask = MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA;
//if set to use cells and at the end of the minute
if (ent->client->flashlight_framenum == level.time && ent->client->flashlight_cell_usage > 0)
{ //check if have the cells, if not, switch off
if (ent->client->pers.inventory[ITEM_INDEX(FindItem("Cells"))] < ent->client->flashlight_cell_usage)
{
ent->client->flashlight_active = false;
ent->client->flashlight_framenum = 0;
return;
}
ent->client->pers.inventory[ITEM_INDEX(FindItem("Cells"))] -= ent->client->flashlight_cell_usage;
ent->client->flashlight_framenum = level.time + 60;
}
AngleVectors (ent->client->v_angle, forward, NULL, NULL);
VectorMA (ent->s.origin, 384, forward, flashpoint);
tr = gi.trace (ent->s.origin, NULL, NULL, flashpoint, ent, mask);
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_FLASHLIGHT);
gi.WritePosition (tr.endpos);
gi.WriteShort (ent - g_edicts);
gi.multicast (tr.endpos, MULTICAST_PVS);
}
}
/*
===============
G_SetClientEvent
===============
*/
void G_SetClientEvent (edict_t *ent)
{
if (ent->s.event)
return;
if ( ent->groundentity || PlayerOnFloor(ent) )
{
if (!ent->waterlevel && (xyspeed > 225) && !ent->vehicle)
{
if ( (int)(current_client->bobtime+bobmove) != bobcycle )
#ifndef FMOD_FOOTSTEPS
ent->s.event = EV_FOOTSTEP; // Knightmare- move Lazarus footsteps client-side
#else
FootStep(ent);
#endif
}
else if (ent->in_mud && (ent->waterlevel == 1) && (xyspeed > 40))
{
if ( (level.framenum % 10) == 0 )
{
#ifndef FMOD_FOOTSTEPS
ent->s.event = EV_WADE_MUD; // Knightmare- move this client-side
#else
if ( rand() & 1 )
// gi.sound(ent, CHAN_BODY, gi.soundindex("mud/wade_mud1.wav"), 1, ATTN_NORM, 0);
PlayFootstep(ent,FOOTSTEP_MUD_WADE1);
else
// gi.sound(ent, CHAN_BODY, gi.soundindex("mud/wade_mud2.wav"), 1, ATTN_NORM, 0);
PlayFootstep(ent,FOOTSTEP_MUD_WADE2);
#endif
}
}
else if ( ((ent->waterlevel == 1) || (ent->waterlevel == 2)) && (xyspeed > 100) && !(ent->in_mud) )
{
if ( (int)(current_client->bobtime+bobmove) != bobcycle )
{
#ifndef FMOD_FOOTSTEPS
if (ent->waterlevel == 1)
ent->s.event = EV_SLOSH; // Knightmare- move Lazarus footsteps client-side
else if (ent->waterlevel == 2)
ent->s.event = EV_WADE; // Knightmare- move Lazarus footsteps client-side
#else
FootStep(ent);
#endif
}
}
}
// Knightmare- swimming sounds
else if ((ent->waterlevel == 2) && (xyspeed > 60) && !(ent->in_mud) && (world->effects & FX_WORLDSPAWN_STEPSOUNDS))
{
if ( (int)(current_client->bobtime+bobmove) != bobcycle )
#ifndef FMOD_FOOTSTEPS
ent->s.event = EV_WADE; // Knightmare- move Lazarus footsteps client-side
#else
FootStep(ent);
#endif
}
// Ladder sounds
else if ( (level.framenum % 4) == 0)
{
if (!ent->waterlevel && (ent->movetype != MOVETYPE_NOCLIP) && (fabs(ent->velocity[2]) > 50))
{
vec3_t end, forward;
trace_t tr;
AngleVectors(ent->s.angles,forward,NULL,NULL);
VectorMA(ent->s.origin,2,forward,end);
tr = gi.trace(ent->s.origin,ent->mins,ent->maxs,end,ent,CONTENTS_LADDER);
if (tr.fraction < 1.0)
#ifndef FMOD_FOOTSTEPS
ent->s.event = EV_CLIMB_LADDER; // Knightmare- move Lazarus footsteps client-side
#else
{
int r;
r = rand() & 1 + ent->client->leftfoot*2;
ent->client->leftfoot = 1 - ent->client->leftfoot;
switch (r)
{
case 0: PlayFootstep(ent,FOOTSTEP_LADDER1); break;
case 1: PlayFootstep(ent,FOOTSTEP_LADDER3); break;
case 2: PlayFootstep(ent,FOOTSTEP_LADDER2); break;
case 3: PlayFootstep(ent,FOOTSTEP_LADDER4); break;
}
}
#endif //FMOD_FOOTSTEPS
}
}
}
/*
===============
G_SetClientSound
===============
*/
void G_SetClientSound (edict_t *ent)
{
char *weap;
if (ent->client->pers.game_helpchanged != game.helpchanged)
{
ent->client->pers.game_helpchanged = game.helpchanged;
ent->client->pers.helpchanged = 1;
}
// help beep (no more than three times)
if (ent->client->pers.helpchanged && ent->client->pers.helpchanged <= 3 && !(level.framenum&63) )
{
ent->client->pers.helpchanged++;
gi.sound (ent, CHAN_VOICE, gi.soundindex ("misc/pc_up.wav"), 1, ATTN_STATIC, 0);
}
if (ent->client->pers.weapon)
weap = ent->client->pers.weapon->classname;
else
weap = "";
if (ent->waterlevel && (ent->watertype&(CONTENTS_LAVA|CONTENTS_SLIME)) )
ent->s.sound = snd_fry;
else if ( ent->client->jetpack && (ent->client->pers.inventory[fuel_index] < 40 ))
ent->s.sound = gi.soundindex("jetpack/stutter.wav");
else if (strcmp(weap, "weapon_railgun") == 0)
ent->s.sound = gi.soundindex("weapons/rg_hum.wav");
#ifdef KMQUAKE2_ENGINE_MOD
else if (strcmp(weap, "weapon_bfg") == 0)
ent->s.sound = gi.soundindex("weapons/bfg_hum.wav");
// RAFAEL
else if (strcmp (weap, "weapon_phalanx") == 0)
ent->s.sound = gi.soundindex ("weapons/phaloop.wav");
// Knightmare - ambient sounds for ION Ripper and Shockwave
else if ( (strcmp (weap, "weapon_boomer") == 0) && sk_ionripper_extra_sounds->value)
ent->s.sound = gi.soundindex ("weapons/ion_hum.wav");
else if (strcmp (weap, "weapon_shockwave") == 0)
ent->s.sound = gi.soundindex ("weapons/shock_hum.wav");
// SKWiD MOD
else if (strcmp(weap, "weapon_plasma") == 0)
ent->s.sound = gi.soundindex(PLASMA_SOUND_IDLE);
// END
#endif
else if (ent->client->weapon_sound)
ent->s.sound = ent->client->weapon_sound;
else
ent->s.sound = 0;
}
//#define MAX_STEP_FRACTION 0.80
qboolean PlayerOnFloor (edict_t *player)
{
trace_t tr;
vec3_t end = {0, 0, -2};
if (!player->client)
return false;
VectorMA (player->s.origin, 50, end, end);
tr = gi.trace (player->s.origin, NULL, NULL, end, player, MASK_ALL);
//Com_Printf("%f\n", tr.fraction);
if (tr.fraction >= sv_step_fraction->value)
return false;
else if (player->client->oldvelocity[2] > 0 || player->velocity[2] > 0)
return false;
return true;
}
/*
===============
G_SetClientFrame
===============
*/
void G_SetClientFrame (edict_t *ent)
{
gclient_t *client;
qboolean duck, run;
qboolean floor;
if (ent->s.modelindex != (MAX_MODELS-1)) // was 255
return; // not in the player model
client = ent->client;
if (client->ps.pmove.pm_flags & PMF_DUCKED)
duck = true;
else
duck = false;
// Knightmare- don't always play running animation when in mud
if (ent->in_mud && xyspeed > 40)
run = true;
else if (!ent->in_mud && xyspeed)
run = true;
else
run = false;
// Lazarus: override run animations for vehicle drivers
if (ent->vehicle)
run = false;
// Knightmare- do the check here, to be sure not to skip over the frame increment
floor = PlayerOnFloor(ent);
// check for stand/duck and stop/go transitions
if (duck != client->anim_duck && client->anim_priority < ANIM_DEATH)
goto newanim;
if (run != client->anim_run && client->anim_priority == ANIM_BASIC)
goto newanim;
// Knightmare- only skip increment if greater than step or swimming
if (!ent->groundentity && client->anim_priority <= ANIM_WAVE && (!floor || ent->waterlevel > 2))
goto newanim;
if (client->anim_priority == ANIM_REVERSE)
{
if (ent->s.frame > client->anim_end)
{
ent->s.frame--;
return;
}
}
else if (ent->s.frame < client->anim_end)
{ // continue an animation
ent->s.frame++;
return;
}
if (client->anim_priority == ANIM_DEATH)
return; // stay there
if (client->anim_priority == ANIM_JUMP)
{
if (!ent->groundentity)
return; // stay there
ent->client->anim_priority = ANIM_WAVE;
ent->s.frame = FRAME_jump3;
ent->client->anim_end = FRAME_jump6;
return;
}
newanim:
// return to either a running or standing frame
client->anim_priority = ANIM_BASIC;
client->anim_duck = duck;
client->anim_run = run;
// Knightmare- added swimming check
if (!ent->groundentity && (!floor || ent->waterlevel > 2)) // CDawg modify this
{
client->anim_priority = ANIM_JUMP;
if (ent->s.frame != FRAME_jump2)
ent->s.frame = FRAME_jump1;
client->anim_end = FRAME_jump2;
}
// else if (run)
else if (run && client->zCameraTrack == NULL) // Zaero
{ // running
if (duck)
{
ent->s.frame = FRAME_crwalk1;
client->anim_end = FRAME_crwalk6;
}
else
{ // CDawg - add here!
if (client->backpedaling)
{
client->anim_priority = ANIM_REVERSE;
ent->s.frame = FRAME_run6;
client->anim_end = FRAME_run1;
}
else
{
ent->s.frame = FRAME_run1;
client->anim_end = FRAME_run6;
} // CDawg end here!
}
}
else
{ // standing
if (duck)
{
ent->s.frame = FRAME_crstnd01;
client->anim_end = FRAME_crstnd19;
}
else
{
ent->s.frame = FRAME_stand01;
client->anim_end = FRAME_stand40;
}
}
}
/*
=================
ClientEndServerFrame
Called for each player at the end of the server frame
and right after spawning
=================
*/
// Lazarus: "whatsit" display
void WhatsIt( edict_t *ent)
{
char string[128];
if (!ent->client->whatsit)
return;
Com_sprintf(string, sizeof(string), "xv 0 yb -68 cstring2 \"%s\" ", ent->client->whatsit);
gi.WriteByte (svc_layout);
gi.WriteString (string);
gi.unicast(ent,true);
}
void CheckChasecam_Viewent (edict_t *ent);
void ClientEndServerFrame (edict_t *ent)
{
float bobtime;
int i;
current_player = ent;
current_client = ent->client;
//
// If the origin or velocity have changed since ClientThink(),
// update the pmove values. This will happen when the client
// is pushed by a bmodel or kicked by an explosion.
//
// If it wasn't updated here, the view position would lag a frame
// behind the body position when pushed -- "sinking into plats"
//
for (i=0 ; i<3 ; i++)
{
current_client->ps.pmove.origin[i] = ent->s.origin[i]*8.0;
current_client->ps.pmove.velocity[i] = ent->velocity[i]*8.0;
}
//
// If the end of unit layout is displayed, don't give
// the player any normal movement attributes
//
if (level.intermissiontime)
{
// FIXME: add view drifting here?
current_client->ps.blend[3] = 0;
current_client->ps.fov = 90;
G_SetStats (ent);
return;
}
AngleVectors (ent->client->v_angle, forward, right, up);
// burn from lava, etc
P_WorldEffects ();
//
// set model angles from view angles so other things in
// the world can tell which direction you are looking
//
if (ent->client->v_angle[PITCH] > 180)
ent->s.angles[PITCH] = (-360 + ent->client->v_angle[PITCH])/3;
else
ent->s.angles[PITCH] = ent->client->v_angle[PITCH]/3;
ent->s.angles[YAW] = ent->client->v_angle[YAW];
ent->s.angles[ROLL] = 0;
ent->s.angles[ROLL] = SV_CalcRoll (ent->s.angles, ent->velocity)*4;
//
// calculate speed and cycle to be used for
// all cyclic walking effects
//
xyspeed = sqrt(ent->velocity[0]*ent->velocity[0] + ent->velocity[1]*ent->velocity[1]);
if (xyspeed < 5)
{
bobmove = 0;
current_client->bobtime = 0; // start at beginning of cycle again
}
// Kngightmare- exception for wading
else if (ent->groundentity || ent->waterlevel == 2)
{ // so bobbing only cycles when on ground
if (xyspeed > 450) // Knightmare added
bobmove = 0.50;
else if (xyspeed > 210)
bobmove = 0.25;
else if (!ent->groundentity && ent->waterlevel == 2 && xyspeed > 100)
bobmove = 0.45;
else if (xyspeed > 100)
bobmove = 0.125;
else if (!ent->groundentity && ent->waterlevel == 2)
bobmove = 0.325;
else
bobmove = 0.0625;
}
bobtime = (current_client->bobtime += bobmove);
if (current_client->ps.pmove.pm_flags & PMF_DUCKED)
bobtime *= 4;
bobcycle = (int)bobtime;
// Lazarus: vehicle drivers don't bob
if (ent->vehicle)
bobfracsin = 0.;
else
bobfracsin = fabs(sin(bobtime*M_PI));
// detect hitting the floor
if (ent->groundentity) //Kngihtmare- no falling damage with sharp jetpack descent
P_FallingDamage (ent);
// Lazarus: detect hitting walls
P_SlamDamage (ent);
// apply all the damage taken this frame
P_DamageFeedback (ent);
// determine the view offsets
SV_CalcViewOffset (ent);
// determine the gun offsets
SV_CalcGunOffset (ent);
// determine the full screen color blend
// must be after viewoffset, so eye contents can be
// accurately determined
// FIXME: with client prediction, the contents
// should be determined by the client
SV_CalcBlend (ent);
// chase cam stuff
if (ent->client->resp.spectator)
G_SetSpectatorStats(ent);
else
G_SetStats (ent);
G_CheckChaseStats(ent);
G_SetClientEvent (ent);
G_SetClientEffects (ent);
G_SetClientSound (ent);
G_SetClientFrame (ent);
VectorCopy (ent->velocity, ent->client->oldvelocity);
VectorCopy (ent->client->ps.viewangles, ent->client->oldviewangles);
// clear weapon kicks
VectorClear (ent->client->kick_origin);
VectorClear (ent->client->kick_angles);
// if the scoreboard is up, update it
if (!(level.framenum & 31))
{
if (ent->client->showscores)
{
if (ent->client->menu)
PMenu_Update (ent);
else if (ent->client->textdisplay)
Text_Update (ent);
// Zaero
else if (ent->client->zCameraTrack)
updateVisorHud (ent);
// end Zaero
else
DeathmatchScoreboardMessage (ent, ent->enemy);
gi.unicast (ent, false);
}
else if (ent->client->whatsit)
WhatsIt (ent);
}
// Zaero
// this we want to do regardless
if (ent->client->zCameraTrack)
{
// decrease the visor frame time
ent->client->pers.visorFrames--;
if (ent->client->pers.visorFrames == 0)
{
stopCamera (ent);
ent->client->pers.inventory[ITEM_INDEX(FindItem("Visor"))]--;
ValidateSelectedItem (ent);
}
}
// end Zaero
// CHASECAM Knightmare- Gen cam code
// if (ent->client->chasetoggle == 1)
if (ent->client->chaseactive == 1)
CheckChasecam_Viewent (ent);
}