📄 p_view.pas
字号:
for i := 0 to 2 do
begin
delta := ent^.client^.oldviewangles[i] - ent^.client^.ps.viewangles[i];
if (delta > 180) then
delta := delta - 360;
if (delta < -180) then
delta := delta + 360;
if (delta > 45) then
delta := 45;
if (delta < -45) then
delta := -45;
if (i = YAW) then
ent^.client^.ps.gunangles[ROLL] := ent^.client^.ps.gunangles[ROLL] + 0.1*delta;
ent^.client^.ps.gunangles[i] := ent^.client^.ps.gunangles[i] + 0.2 * delta;
end;
// gun height
VectorClear (ent^.client^.ps.gunoffset);
//idsoft ent->ps->gunorigin[2] += bob;
// gun_x / gun_y / gun_z are development tools
for i := 0 to 2 do
begin
{ NOTE (SP): Whilst this looks the same mathematically, I have adjusted the
commented out code to be compilable, should there be any question
of issues here, such that the new line could be replaced with these
three orignal lines again }
{ent^.client^.ps.gunoffset[i] := ent^.client^.ps.gunoffset[i] + forward_[i]*(gun_y.value);
ent^.client^.ps.gunoffset[i] := ent^.client^.ps.gunoffset[i] + right[i]*gun_x.value;
ent^.client^.ps.gunoffset[i] := ent^.client^.ps.gunoffset[i] + up[i]* (-gun_z.value);}
ent^.client^.ps.gunoffset[i] := ent^.client^.ps.gunoffset[i] + forward_[i]*gun_y.value
+ right[i]*gun_x.value
+ up[i]*(-gun_z.value);
end;
end;
{*
=============
SV_AddBlend
=============
*}
procedure SV_AddBlend (r, g, b, a : single; var v_blend : array of single); //only imp
var
a2, a3 : Single;
begin
if (a <= 0) then
Exit;
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;
end;
{*
=============
SV_CalcBlend
=============
*}
procedure SV_CalcBlend (ent : edict_p); //only imp
var
vieworg : vec3_t;
contents,
remaining : integer;
begin
ent^.client^.ps.blend[0] := 0;
ent^.client^.ps.blend[1] := 0;
ent^.client^.ps.blend[2] := 0;
ent^.client^.ps.blend[3] := 0;
// add for contents
VectorAdd (ent^.s.origin, ent^.client^.ps.viewoffset, vieworg);
contents := gi.pointcontents (vieworg);
if (contents AND (CONTENTS_LAVA OR CONTENTS_SLIME OR CONTENTS_WATER)) <> 0 then
ent^.client^.ps.rdflags := ent^.client^.ps.rdflags OR RDF_UNDERWATER
else
ent^.client^.ps.rdflags := ent^.client^.ps.rdflags AND (NOT RDF_UNDERWATER);
if (contents AND (CONTENTS_SOLID OR CONTENTS_LAVA)) <> 0 then
SV_AddBlend (1.0, 0.3, 0.0, 0.6, ent^.client^.ps.blend)
else if (contents AND CONTENTS_SLIME) <> 0 then
SV_AddBlend (0.0, 0.1, 0.05, 0.6, ent^.client^.ps.blend)
else if (contents AND CONTENTS_WATER) <> 0 then
SV_AddBlend (0.5, 0.3, 0.2, 0.4, ent^.client^.ps.blend);
// add for powerups
if (ent^.client^.quad_framenum > level.framenum) then
begin
remaining := trunc(ent^.client^.quad_framenum - level.framenum);
if (remaining = 30) then // beginning to fade
gi.sound(ent, CHAN_ITEM, gi.soundindex('items/damage2.wav'), 1, ATTN_NORM, 0);
if (remaining > 30) OR ((remaining and 4) <> 0) then
SV_AddBlend (0, 0, 1, 0.08, ent^.client^.ps.blend);
end
else if (ent^.client^.invincible_framenum > level.framenum) then
begin
remaining := trunc(ent^.client^.invincible_framenum - level.framenum);
if (remaining = 30) then // beginning to fade
gi.sound(ent, CHAN_ITEM, gi.soundindex('items/protect2.wav'), 1, ATTN_NORM, 0);
if (remaining > 30) OR ((remaining and 4) <> 0) then
SV_AddBlend (1, 1, 0, 0.08, ent^.client^.ps.blend);
end
else if (ent^.client^.enviro_framenum > level.framenum) then
begin
remaining := trunc(ent^.client^.enviro_framenum - level.framenum);
if (remaining = 30) then // beginning to fade
gi.sound(ent, CHAN_ITEM, gi.soundindex('items/airout.wav'), 1, ATTN_NORM, 0);
if (remaining > 30) OR ((remaining and 4) <> 0) then
SV_AddBlend (0, 1, 0, 0.08, ent.client.ps.blend);
end
else if (ent^.client^.breather_framenum > level.framenum) then
begin
remaining := trunc(ent^.client^.breather_framenum - level.framenum);
if (remaining = 30) then // beginning to fade
gi.sound(ent, CHAN_ITEM, gi.soundindex('items/airout.wav'), 1, ATTN_NORM, 0);
if (remaining > 30) OR ((remaining and 4) <> 0) then
SV_AddBlend (0.4, 1, 0.4, 0.04, ent^.client^.ps.blend);
end;
// add for damage
if (ent^.client^.damage_alpha > 0) then
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) then
SV_AddBlend (0.85, 0.7, 0.3, ent^.client^.bonus_alpha, ent^.client^.ps.blend);
// drop the damage value
ent^.client^.damage_alpha := ent^.client^.damage_alpha - 0.06;
if (ent^.client^.damage_alpha < 0) then
ent^.client^.damage_alpha := 0;
// drop the bonus value
ent^.client^.bonus_alpha := ent^.client^.bonus_alpha - 0.1;
if (ent^.client^.bonus_alpha < 0) then
ent^.client^.bonus_alpha := 0;
end;
{*
=================
P_FallingDamage
=================
*}
procedure P_FallingDamage (ent : edict_p); //only imp
var
delta : Single;
damage : integer;
dir : vec3_t;
begin
if (ent^.s.modelindex <> 255) then
Exit; // not in the player model
if (ent^.movetype = MOVETYPE_NOCLIP) then
Exit;
if ( (ent^.client^.oldvelocity[2] < 0) AND
(ent^.velocity[2] > ent^.client^.oldvelocity[2]) AND
(ent^.groundentity = Nil) ) then
delta := ent^.client^.oldvelocity[2]
else
begin
if (ent^.groundentity = Nil) then
Exit;
delta := ent^.velocity[2] - ent^.client^.oldvelocity[2];
end;
delta := delta*delta * 0.0001;
{$IFDEF CTF} //onlyCTF
//ZOID
(*Y // never take damage if just release grapple or on grapple
if ( (level.time - ent.client.ctf_grapplereleasetime <= FRAMETIME * 2) OR
(ent.client.ctf_grapple AND ent.client.ctf_grapplestate > CTF_GRAPPLE_STATE_FLY) ) then
Exit;*)
//ZOID
{$ENDIF}
// never take falling damage if completely underwater
if (ent^.waterlevel = 3) then
Exit;
if (ent^.waterlevel = 2) then
delta := delta * 0.25;
if (ent^.waterlevel = 1) then
delta := delta * 0.5;
if (delta < 1) then
Exit;
if (delta < 15) then
begin
ent^.s.event := EV_FOOTSTEP;
Exit;
end;
ent^.client^.fall_value := delta*0.5;
if (ent^.client^.fall_value > 40) then
ent^.client^.fall_value := 40;
ent^.client^.fall_time := level.time + FALL_TIME;
if (delta > 30) then
begin
if (ent^.health > 0) then
begin
if (delta >= 55) then
ent^.s.event := EV_FALLFAR
else
ent^.s.event := EV_FALL;
end;
ent^.pain_debounce_time := level.time; // no normal pain sound
damage := trunc((delta-30) / 2);
if (damage < 1) then
damage := 1;
VectorSet (dir, 0, 0, 1);
if ((deathmatch^.value = 0) or ((trunc(dmflags^.Value) and DF_NO_FALLING) = 0) ) then
T_Damage (ent, world, world, dir, ent^.s.origin, vec3_origin, damage, 0, 0, MOD_FALLING);
end
else begin
ent^.s.event := EV_FALLSHORT;
Exit;
end;
end;
{*
=============
P_WorldEffects
=============
*}
procedure P_WorldEffects; //only imp
var
breather,
envirosuit : qboolean;
waterlevel,
old_waterlevel : integer;
begin
if (current_player^.movetype = MOVETYPE_NOCLIP) then
begin
current_player^.air_finished := level.time + 12; // don't need air
Exit;
end;
waterlevel := current_player^.waterlevel;
old_waterlevel := current_client^.old_waterlevel;
current_client^.old_waterlevel := waterlevel;
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 = 0) AND (waterlevel <> 0) then
begin
PlayerNoise (current_player, current_player^.s.origin, PNOISE_SELF);
if (current_player^.watertype AND CONTENTS_LAVA) <> 0 then
gi.sound (current_player, CHAN_BODY, gi.soundindex('player/lava_in.wav'), 1, ATTN_NORM, 0)
else if (current_player^.watertype AND CONTENTS_SLIME) <> 0 then
gi.sound (current_player, CHAN_BODY, gi.soundindex('player/watr_in.wav'), 1, ATTN_NORM, 0)
else if (current_player^.watertype AND CONTENTS_WATER) <> 0 then
gi.sound (current_player, CHAN_BODY, gi.soundindex('player/watr_in.wav'), 1, ATTN_NORM, 0);
current_player^.flags := current_player^.flags OR FL_INWATER;
// clear damage_debounce, so the pain sound will play immediately
current_player^.damage_debounce_time := level.time - 1;
end;
//
// if just completely exited a water volume, play a sound
//
if (old_waterlevel <> 0) AND (waterlevel = 0) then
begin
PlayerNoise (current_player, current_player^.s.origin, PNOISE_SELF);
gi.sound (current_player, CHAN_BODY, gi.soundindex('player/watr_out.wav'), 1, ATTN_NORM, 0);
current_player^.flags := current_player^.flags AND (NOT FL_INWATER);
end;
//
// check for head just going under water
//
if (old_waterlevel <> 3) AND (waterlevel = 3) then
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) AND (waterlevel <> 3) then
begin
if (current_player^.air_finished < level.time) then
begin
// 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);
end
else if (current_player^.air_finished < level.time + 11) then
// just break surface
gi.sound (current_player, CHAN_VOICE, gi.soundindex('player/gasp2.wav'), 1, ATTN_NORM, 0);
end;
//
// check for drowning
//
if (waterlevel = 3) then
begin
// breather or envirosuit give air
if (breather OR envirosuit) then
begin
current_player^.air_finished := level.time + 10;
if ((trunc(current_client^.breather_framenum - level.framenum) mod 25) = 0) then
begin
if (current_client^.breather_sound = 0) then
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 := current_client^.breather_sound XOR 1;
PlayerNoise (current_player, current_player^.s.origin, PNOISE_SELF);
//FIXME: release a bubble?
end;
end;
// if out of air, start drowning
if (current_player^.air_finished < level.time) then
begin
// drown!
if (current_player^.client^.next_drown_time < level.time) AND (current_player^.health > 0) then
begin
current_player^.client^.next_drown_time := level.time + 1;
// take more damage the longer underwater
Inc(current_player^.dmg, 2);
if (current_player^.dmg > 15) then
current_player^.dmg := 15;
// play a gurp sound instead of a normal pain sound
if (current_player^.health <= current_player^.dmg) then
gi.sound (current_player, CHAN_VOICE, gi.soundindex('player/drown1.wav'), 1, ATTN_NORM, 0)
else if ((rand() and 1) <> 0) then
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);
end;
end;
end
else begin
current_player^.air_finished := level.time + 12;
current_player^.dmg := 2;
end;
//
// check for sizzle damage
//
if (waterlevel <> 0) AND ((current_player^.watertype AND (CONTENTS_LAVA OR CONTENTS_SLIME)) <> 0) then
begin
if (current_player^.watertype AND CONTENTS_LAVA) <> 0 then
begin
if (current_player^.health > 0) AND
(current_player^.pain_debounce_time <= level.time) AND
(current_client^.invincible_framenum < level.framenum) then
begin
if (rand() and 1) <> 0 then
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;
end;
// take 1/3 damage with envirosuit
if (envirosuit) then
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);
end;
if (current_player^.watertype AND CONTENTS_SLIME) <> 0 then
if (NOT envirosuit) then
// 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);
end;
end;
{*
===============
G_SetClientEffects
===============
*}
procedure G_SetClientEffects (ent : edict_p); //only imp
var
pa_type,
remaining : integer;
begin
ent^.s.effects := 0;
ent^.s.renderfx := 0;
if (ent^.health <= 0) OR (level.intermissiontime <> 0) then
Exit;
if (ent^.powerarmor_time > level.time) then
begin
pa_type := PowerArmorType (ent);
if (pa_type = POWER_ARMOR_SCREEN) then
ent^.s.effects := ent^.s.effects OR EF_POWERSCREEN
else if (pa_type = POWER_ARMOR_SHIELD) then
begin
ent^.s.effects := ent^.s.effects OR EF_COLOR_SHELL;
ent^.s.renderfx := ent^.s.renderfx OR RF_SHELL_GREEN;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -