X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=view.c;h=c02459debcf06065ee4e765db5428684be9c6e4b;hp=4839e64ef1357a55e054ad29fbc5a9108160c907;hb=868e31d920af94a1a825dbbe24aa530f9927aceb;hpb=127c0d85081316ab9299b9912a36b11c4c22e3f8 diff --git a/view.c b/view.c index 4839e64e..c02459de 100644 --- a/view.c +++ b/view.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // view.c -- player eye positioning #include "quakedef.h" +#include "cl_collision.h" /* @@ -55,6 +56,16 @@ cvar_t crosshair = {CVAR_SAVE, "crosshair", "0"}; cvar_t v_centermove = {0, "v_centermove", "0.15"}; cvar_t v_centerspeed = {0, "v_centerspeed","500"}; +cvar_t cl_stairsmoothspeed = {CVAR_SAVE, "cl_stairsmoothspeed", "160"}; + +cvar_t chase_back = {CVAR_SAVE, "chase_back", "48"}; +cvar_t chase_up = {CVAR_SAVE, "chase_up", "24"}; +cvar_t chase_active = {CVAR_SAVE, "chase_active", "0"}; +// GAME_GOODVSBAD2 +cvar_t chase_stevie = {0, "chase_stevie", "0"}; + +cvar_t cl_deathtilt = {0, "cl_deathtilt", "1"}; + float v_dmg_time, v_dmg_roll, v_dmg_pitch; @@ -71,7 +82,7 @@ float V_CalcRoll (vec3_t angles, vec3_t velocity) float sign; float side; float value; - + AngleVectors (angles, NULL, right, NULL); side = DotProduct (velocity, right); sign = side < 0 ? -1 : 1; @@ -88,34 +99,6 @@ float V_CalcRoll (vec3_t angles, vec3_t velocity) } -static float V_CalcBob (void) -{ - double bob, cycle; - - // LordHavoc: easy case - if (cl_bob.value == 0) - return 0; - if (cl_bobcycle.value == 0) - return 0; - - // LordHavoc: FIXME: this code is *weird*, redesign it sometime - cycle = cl.time / cl_bobcycle.value; - cycle -= (int) cycle; - if (cycle < cl_bobup.value) - cycle = M_PI * cycle / cl_bobup.value; - else - cycle = M_PI + M_PI*(cycle-cl_bobup.value)/(1.0 - cl_bobup.value); - - // bob is proportional to velocity in the xy plane - // (don't count Z, or jumping messes it up) - - bob = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]) * cl_bob.value; - bob = bob*0.3 + bob*0.7*sin(cycle); - bob = bound(-7, bob, 4); - return bob; - -} - void V_StartPitchDrift (void) { if (cl.laststop == cl.time) @@ -149,7 +132,7 @@ Drifting is enabled when the center view key is hit, mlook is released and lookspring is non 0, or when =============== */ -static void V_DriftPitch (void) +void V_DriftPitch (void) { float delta, move; @@ -223,15 +206,17 @@ V_ParseDamage */ void V_ParseDamage (void) { - int i, armor, blood; - vec3_t from, forward, right; + int armor, blood; + vec3_t from; + //vec3_t forward, right; + vec3_t localfrom; entity_t *ent; - float side, count; + //float side; + float count; armor = MSG_ReadByte (); blood = MSG_ReadByte (); - for (i=0 ; i<3 ; i++) - from[i] = MSG_ReadCoord (); + MSG_ReadVector(from, cl.protocol); count = blood*0.5 + armor*0.5; if (count < 10) @@ -264,23 +249,16 @@ void V_ParseDamage (void) cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0; } -// -// calculate view angle kicks -// - ent = &cl_entities[cl.viewentity]; - - VectorSubtract (from, ent->render.origin, from); - VectorNormalize (from); - - AngleVectors (ent->render.angles, forward, right, NULL); - - side = DotProduct (from, right); - v_dmg_roll = count*side*v_kickroll.value; - - side = DotProduct (from, forward); - v_dmg_pitch = count*side*v_kickpitch.value; - - v_dmg_time = v_kicktime.value; + // calculate view angle kicks + if (cl_entities[cl.viewentity].state_current.active) + { + ent = &cl_entities[cl.viewentity]; + Matrix4x4_Transform(&ent->render.inversematrix, from, localfrom); + VectorNormalize(localfrom); + v_dmg_pitch = count * localfrom[0] * v_kickpitch.value; + v_dmg_roll = count * localfrom[1] * v_kickroll.value; + v_dmg_time = v_kicktime.value; + } } static cshift_t v_cshift; @@ -314,133 +292,6 @@ static void V_BonusFlash_f (void) cl.cshifts[CSHIFT_BONUS].percent = 50; } -/* -============= -V_UpdateBlends -============= -*/ -void V_UpdateBlends (void) -{ - float r, g, b, a, a2; - int j; - - if (cl.worldmodel == NULL) - { - cl.cshifts[CSHIFT_DAMAGE].percent = 0; - cl.cshifts[CSHIFT_BONUS].percent = 0; - cl.cshifts[CSHIFT_CONTENTS].percent = 0; - cl.cshifts[CSHIFT_POWERUP].percent = 0; - r_refdef.viewblend[0] = 0; - r_refdef.viewblend[1] = 0; - r_refdef.viewblend[2] = 0; - r_refdef.viewblend[3] = 0; - return; - } - - // drop the damage value - cl.cshifts[CSHIFT_DAMAGE].percent -= (cl.time - cl.oldtime)*150; - if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0) - cl.cshifts[CSHIFT_DAMAGE].percent = 0; - - // drop the bonus value - cl.cshifts[CSHIFT_BONUS].percent -= (cl.time - cl.oldtime)*100; - if (cl.cshifts[CSHIFT_BONUS].percent <= 0) - cl.cshifts[CSHIFT_BONUS].percent = 0; - - // set contents color - switch (Mod_PointInLeaf (r_refdef.vieworg, cl.worldmodel)->contents) - { - case CONTENTS_EMPTY: - case CONTENTS_SOLID: - cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = v_cshift.destcolor[0]; - cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = v_cshift.destcolor[1]; - cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = v_cshift.destcolor[2]; - cl.cshifts[CSHIFT_CONTENTS].percent = v_cshift.percent; - break; - case CONTENTS_LAVA: - cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 255; - cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80; - cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0; - cl.cshifts[CSHIFT_CONTENTS].percent = 150 >> 1; - break; - case CONTENTS_SLIME: - cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0; - cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 25; - cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 5; - cl.cshifts[CSHIFT_CONTENTS].percent = 150 >> 1; - break; - default: - cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 130; - cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80; - cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 50; - cl.cshifts[CSHIFT_CONTENTS].percent = 128 >> 1; - } - - if (cl.items & IT_QUAD) - { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; - cl.cshifts[CSHIFT_POWERUP].percent = 30; - } - else if (cl.items & IT_SUIT) - { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; - cl.cshifts[CSHIFT_POWERUP].percent = 20; - } - else if (cl.items & IT_INVISIBILITY) - { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100; - cl.cshifts[CSHIFT_POWERUP].percent = 100; - } - else if (cl.items & IT_INVULNERABILITY) - { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; - cl.cshifts[CSHIFT_POWERUP].percent = 30; - } - else - cl.cshifts[CSHIFT_POWERUP].percent = 0; - - // LordHavoc: fixed V_CalcBlend - r = 0; - g = 0; - b = 0; - a = 0; - - for (j=0 ; j 1) - a2 = 1; - r += (cl.cshifts[j].destcolor[0]-r) * a2; - g += (cl.cshifts[j].destcolor[1]-g) * a2; - b += (cl.cshifts[j].destcolor[2]-b) * a2; - a = 1 - (1 - a) * (1 - a2); // correct alpha multiply... took a while to find it on the web - } - // saturate color (to avoid blending in black) - if (a) - { - a2 = 1 / a; - r *= a2; - g *= a2; - b *= a2; - } - - r_refdef.viewblend[0] = bound(0, r * (1.0/255.0), 1); - r_refdef.viewblend[1] = bound(0, g * (1.0/255.0), 1); - r_refdef.viewblend[2] = bound(0, b * (1.0/255.0), 1); - r_refdef.viewblend[3] = bound(0, a , 1); -} - /* ============================================================================== @@ -449,20 +300,9 @@ void V_UpdateBlends (void) ============================================================================== */ -/* -============== -V_AddIdle - -Idle swaying -============== -*/ -static void V_AddIdle (float idle) -{ - r_refdef.viewangles[ROLL] += idle * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; - r_refdef.viewangles[PITCH] += idle * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; - r_refdef.viewangles[YAW] += idle * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; -} +extern matrix4x4_t viewmodelmatrix; +#include "cl_collision.h" /* ================== @@ -472,92 +312,246 @@ V_CalcRefdef */ void V_CalcRefdef (void) { - entity_t *ent, *view; - vec3_t forward; - vec3_t angles; - float bob; - float side; - - if (cls.state != ca_connected || !cl.worldmodel) - return; - - // ent is the player model (visible when out of body) - ent = &cl_entities[cl.viewentity]; - // view is the weapon model (only visible from inside body) - view = &cl.viewent; - - V_DriftPitch (); - - VectorCopy (cl.viewentorigin, r_refdef.vieworg); - if (!intimerefresh) - VectorCopy (cl.viewangles, r_refdef.viewangles); - - if (cl.intermission) - { - view->render.model = NULL; - VectorCopy (ent->render.angles, r_refdef.viewangles); - V_AddIdle (1); - } - else if (chase_active.value) + static float oldz; + entity_t *ent; + float vieworg[3], viewangles[3]; + trace_t trace; + Matrix4x4_CreateIdentity(&viewmodelmatrix); + Matrix4x4_CreateIdentity(&r_refdef.viewentitymatrix); + if (cls.state == ca_connected && cls.signon == SIGNONS) { - r_refdef.vieworg[2] += cl.viewheight; - Chase_Update (); - V_AddIdle (v_idlescale.value); + // ent is the view entity (visible when out of body) + ent = &cl_entities[cl.viewentity]; + if (cl.intermission) + { + // entity is a fixed camera, just copy the matrix + Matrix4x4_Copy(&r_refdef.viewentitymatrix, &ent->render.matrix); + Matrix4x4_Copy(&viewmodelmatrix, &ent->render.matrix); + r_refdef.viewentitymatrix.m[2][3] += cl.stats[STAT_VIEWHEIGHT]; + viewmodelmatrix.m[2][3] += cl.stats[STAT_VIEWHEIGHT]; + } + else + { + // player can look around, so take the origin from the entity, + // and the angles from the input system + Matrix4x4_OriginFromMatrix(&ent->render.matrix, vieworg); + VectorCopy(cl.viewangles, viewangles); + + // stair smoothing + //Con_Printf("cl.onground %i oldz %f newz %f\n", cl.onground, oldz, vieworg[2]); + if (cl.onground && oldz < vieworg[2]) + { + oldz += (cl.time - cl.oldtime) * cl_stairsmoothspeed.value; + oldz = vieworg[2] = bound(vieworg[2] - 16, oldz, vieworg[2]); + } + else if (cl.onground && oldz > vieworg[2]) + { + oldz -= (cl.time - cl.oldtime) * cl_stairsmoothspeed.value; + oldz = vieworg[2] = bound(vieworg[2], oldz, vieworg[2] + 16); + } + else + oldz = vieworg[2]; + + if (chase_active.value) + { + // observing entity from third person + vec_t camback, camup, dist, forward[3], chase_dest[3]; + + camback = bound(0, chase_back.value, 128); + if (chase_back.value != camback) + Cvar_SetValueQuick(&chase_back, camback); + camup = bound(-48, chase_up.value, 96); + if (chase_up.value != camup) + Cvar_SetValueQuick(&chase_up, camup); + + // this + 22 is to match view_ofs for compatibility with older versions + camup += 22; + + if (gamemode == GAME_GOODVSBAD2 && chase_stevie.integer) + { + // look straight down from high above + viewangles[0] = 90; + camback = 2048; + } + AngleVectors(viewangles, forward, NULL, NULL); + + // trace a little further so it hits a surface more consistently (to avoid 'snapping' on the edge of the range) + dist = -camback - 8; + chase_dest[0] = vieworg[0] + forward[0] * dist; + chase_dest[1] = vieworg[1] + forward[1] * dist; + chase_dest[2] = vieworg[2] + forward[2] * dist + camup; + trace = CL_TraceBox(vieworg, vec3_origin, vec3_origin, chase_dest, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, false); + VectorMAMAM(1, trace.endpos, 8, forward, 4, trace.plane.normal, vieworg); + } + else + { + // first person view from entity + // angles + if (cl.stats[STAT_HEALTH] <= 0 && cl_deathtilt.integer) + viewangles[ROLL] = 80; // dead view angle + VectorAdd(viewangles, cl.punchangle, viewangles); + viewangles[ROLL] += V_CalcRoll(cl.viewangles, cl.movement_velocity); + if (v_dmg_time > 0) + { + viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll; + viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch; + v_dmg_time -= cl.frametime; + } + // origin + VectorAdd(vieworg, cl.punchvector, vieworg); + vieworg[2] += cl.stats[STAT_VIEWHEIGHT]; + if (cl.stats[STAT_HEALTH] > 0 && cl_bob.value && cl_bobcycle.value) + { + double bob, cycle; + // LordHavoc: this code is *weird*, but not replacable (I think it + // should be done in QC on the server, but oh well, quake is quake) + // LordHavoc: figured out bobup: the time at which the sin is at 180 + // degrees (which allows lengthening or squishing the peak or valley) + cycle = cl.time / cl_bobcycle.value; + cycle -= (int) cycle; + if (cycle < cl_bobup.value) + cycle = sin(M_PI * cycle / cl_bobup.value); + else + cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value)); + // bob is proportional to velocity in the xy plane + // (don't count Z, or jumping messes it up) + bob = sqrt(cl.movement_velocity[0]*cl.movement_velocity[0] + cl.movement_velocity[1]*cl.movement_velocity[1]) * cl_bob.value; + bob = bob*0.3 + bob*0.7*cycle; + vieworg[2] += bound(-7, bob, 4); + } + } + // calculate a view matrix for rendering the scene + if (v_idlescale.value) + Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0] + v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value, viewangles[1] + v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value, viewangles[2] + v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 1); + else + Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2] + v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 1); + // calculate a viewmodel matrix for use in view-attached entities + Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2], 0.3); + } } - else +} + +void V_FadeViewFlashs(void) +{ + // drop the damage value + cl.cshifts[CSHIFT_DAMAGE].percent -= (cl.time - cl.oldtime)*150; + if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0) + cl.cshifts[CSHIFT_DAMAGE].percent = 0; + // drop the bonus value + cl.cshifts[CSHIFT_BONUS].percent -= (cl.time - cl.oldtime)*100; + if (cl.cshifts[CSHIFT_BONUS].percent <= 0) + cl.cshifts[CSHIFT_BONUS].percent = 0; +} + +void V_CalcViewBlend(void) +{ + float a2; + int j; + r_refdef.viewblend[0] = 0; + r_refdef.viewblend[1] = 0; + r_refdef.viewblend[2] = 0; + r_refdef.viewblend[3] = 0; + r_refdef.fovscale_x = cl.viewzoom; + r_refdef.fovscale_y = cl.viewzoom; + if (cls.state == ca_connected && cls.signon == SIGNONS && gl_polyblend.value > 0) { - side = V_CalcRoll (cl_entities[cl.viewentity].render.angles, cl.velocity); - r_refdef.viewangles[ROLL] += side; + // set contents color + int supercontents; + vec3_t vieworigin; + Matrix4x4_OriginFromMatrix(&r_refdef.viewentitymatrix, vieworigin); + supercontents = CL_PointSuperContents(vieworigin); + if (supercontents & SUPERCONTENTS_LIQUIDSMASK) + { + r_refdef.fovscale_x *= 1 - (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value); + r_refdef.fovscale_y *= 1 - (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); + if (supercontents & SUPERCONTENTS_LAVA) + { + cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 255; + cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80; + cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0; + } + else if (supercontents & SUPERCONTENTS_SLIME) + { + cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0; + cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 25; + cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 5; + } + else + { + cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 130; + cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80; + cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 50; + } + cl.cshifts[CSHIFT_CONTENTS].percent = 150 >> 1; + } + else + { + cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0; + cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 0; + cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0; + cl.cshifts[CSHIFT_CONTENTS].percent = 0; + } - if (v_dmg_time > 0) + if (gamemode != GAME_TRANSFUSION) { - r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll; - r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch; - v_dmg_time -= cl.frametime; + if (cl.stats[STAT_ITEMS] & IT_QUAD) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; + cl.cshifts[CSHIFT_POWERUP].percent = 30; + } + else if (cl.stats[STAT_ITEMS] & IT_SUIT) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; + cl.cshifts[CSHIFT_POWERUP].percent = 20; + } + else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100; + cl.cshifts[CSHIFT_POWERUP].percent = 100; + } + else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; + cl.cshifts[CSHIFT_POWERUP].percent = 30; + } + else + cl.cshifts[CSHIFT_POWERUP].percent = 0; } - if (cl.stats[STAT_HEALTH] <= 0) - r_refdef.viewangles[ROLL] = 80; // dead view angle - - V_AddIdle (v_idlescale.value); - - // offsets - angles[PITCH] = -ent->render.angles[PITCH]; // because entity pitches are actually backward - angles[YAW] = ent->render.angles[YAW]; - angles[ROLL] = ent->render.angles[ROLL]; - - AngleVectors (angles, forward, NULL, NULL); - - bob = V_CalcBob (); - - r_refdef.vieworg[2] += cl.viewheight + bob; - - // set up gun - view->state_current.modelindex = cl.stats[STAT_WEAPON]; - view->state_current.frame = cl.stats[STAT_WEAPONFRAME]; - VectorCopy(r_refdef.vieworg, view->render.origin); - //view->render.origin[0] = ent->render.origin[0] + bob * 0.4 * forward[0]; - //view->render.origin[1] = ent->render.origin[1] + bob * 0.4 * forward[1]; - //view->render.origin[2] = ent->render.origin[2] + bob * 0.4 * forward[2] + cl.viewheight + bob; - view->render.angles[PITCH] = -r_refdef.viewangles[PITCH] - v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; - view->render.angles[YAW] = r_refdef.viewangles[YAW] - v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; - view->render.angles[ROLL] = r_refdef.viewangles[ROLL] - v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; - // FIXME: this setup code is somewhat evil (CL_LerpUpdate should be private?) - CL_LerpUpdate(view); - view->render.colormap = -1; // no special coloring - view->render.alpha = ent->render.alpha; // LordHavoc: if the player is transparent, so is the gun - view->render.effects = ent->render.effects; - view->render.scale = 1.0 / 3.0; - - // LordHavoc: origin view kick added - if (!intimerefresh) + cl.cshifts[CSHIFT_VCSHIFT].destcolor[0] = v_cshift.destcolor[0]; + cl.cshifts[CSHIFT_VCSHIFT].destcolor[1] = v_cshift.destcolor[1]; + cl.cshifts[CSHIFT_VCSHIFT].destcolor[2] = v_cshift.destcolor[2]; + cl.cshifts[CSHIFT_VCSHIFT].percent = v_cshift.percent; + + // LordHavoc: fixed V_CalcBlend + for (j = 0;j < NUM_CSHIFTS;j++) + { + a2 = bound(0.0f, cl.cshifts[j].percent * (1.0f / 255.0f), 1.0f); + if (a2 > 0) + { + VectorLerp(r_refdef.viewblend, a2, cl.cshifts[j].destcolor, r_refdef.viewblend); + r_refdef.viewblend[3] = (1 - (1 - r_refdef.viewblend[3]) * (1 - a2)); // correct alpha multiply... took a while to find it on the web + } + } + // saturate color (to avoid blending in black) + if (r_refdef.viewblend[3]) { - VectorAdd(r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); - VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg); + a2 = 1 / r_refdef.viewblend[3]; + VectorScale(r_refdef.viewblend, a2, r_refdef.viewblend); } - // copy to refdef - r_refdef.viewent = view->render; + r_refdef.viewblend[0] = bound(0.0f, r_refdef.viewblend[0] * (1.0f/255.0f), 1.0f); + r_refdef.viewblend[1] = bound(0.0f, r_refdef.viewblend[1] * (1.0f/255.0f), 1.0f); + r_refdef.viewblend[2] = bound(0.0f, r_refdef.viewblend[2] * (1.0f/255.0f), 1.0f); + r_refdef.viewblend[3] = bound(0.0f, r_refdef.viewblend[3] * gl_polyblend.value, 1.0f); } } @@ -596,5 +590,15 @@ void V_Init (void) Cvar_RegisterVariable (&v_kicktime); Cvar_RegisterVariable (&v_kickroll); Cvar_RegisterVariable (&v_kickpitch); + + Cvar_RegisterVariable (&cl_stairsmoothspeed); + + Cvar_RegisterVariable (&chase_back); + Cvar_RegisterVariable (&chase_up); + Cvar_RegisterVariable (&chase_active); + if (gamemode == GAME_GOODVSBAD2) + Cvar_RegisterVariable (&chase_stevie); + + Cvar_RegisterVariable (&cl_deathtilt.integer); }