📄 p_view.pas
字号:
// 99%
{----------------------------------------------------------------------------}
{ }
{ File(s): p_view.c }
{ }
{ Initial conversion by : YgriK (Igor Karpov) - glYgriK@hotbox.ru }
{ Initial conversion on : 04-Feb-2002 }
{ }
{ This File contains part of convertion of Quake2 source to ObjectPascal. }
{ More information about this project can be found at: }
{ http://www.sulaco.co.za/quake2/ }
{ }
{ Copyright (C) 1997-2001 Id Software, Inc. }
{ }
{ This program is free software; you can redistribute it and/or }
{ modify it under the terms of the GNU General Public License }
{ as published by the Free Software Foundation; either version 2 }
{ of the License, or (at your option) any later version. }
{ }
{ This program is distributed in the hope that it will be useful, }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. }
{ }
{ See the GNU General Public License for more details. }
{ }
{----------------------------------------------------------------------------}
{ Updated on : 2003-03-24 }
{ Updated by : Scott Price }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ 1) unit g_local }
{ 2) unit p_hud }
{ }
{----------------------------------------------------------------------------}
{ NOTES: }
{ - Unit completely compared to original Game unit. CTF defined code NOT }
{ checked! }
{----------------------------------------------------------------------------}
{ * TODO: }
{ 1) Do more tests }
{ }
{----------------------------------------------------------------------------}
unit p_view;
interface
uses g_local;
procedure ClientEndServerFrame (ent : edict_p); //for p_client
implementation
uses
p_hud,
q_shared,
q_shared_add,
g_main,
g_local_add,
p_weapon,
g_combat,
g_items,
gameunit, m_player, CPas;
{#include "g_local.h"
#include "m_player.h"}
var
current_player : edict_p;
current_client : gclient_p;
forward_, right, up : vec3_t;
bobcycle : integer; // odd cycles are right foot going forward
xyspeed,
bobmove,
bobfracsin : Single; // sin(bobfrac*M_PI)
{*
===============
SV_CalcRoll
===============
*}
function SV_CalcRoll (const angles, velocity : vec3_t) : Single; //only imp
var
sign,
side,
value : Single;
begin
side := DotProduct (velocity, right);
{ ???: sign = side < 0 ? -1 : 1; }
if side < 0 then
sign := -1
else
sign := 1;
side := abs(side);
value := sv_rollangle^.value;
if (side < sv_rollspeed^.value) then
side := side * value / sv_rollspeed^.value
else
side := value;
Result := side*sign;
end;
{*
===============
P_DamageFeedback
Handles color blends and view kicks
===============
*}
var
i : Integer =0;
procedure P_DamageFeedback (player : edict_p); //only imp
var
client : gclient_p;
side,
realcount, count, kick : Single;
v : vec3_t;
r, l : integer;
const
power_color : vec3_t = (0.0, 1.0, 0.0);
acolor : vec3_t = (1.0, 1.0, 1.0);
bcolor : vec3_t = (1.0, 0.0, 0.0);
begin
client := player^.client;
// flash the backgrounds behind the status numbers
client^.ps.stats[STAT_FLASHES] := 0;
if (client^.damage_blood <> 0) then
client^.ps.stats[STAT_FLASHES] := client^.ps.stats[STAT_FLASHES] OR 1;
if ((client^.damage_armor <> 0) and ((player^.flags and FL_GODMODE) = 0) AND (client^.invincible_framenum <= level.framenum)) then
client^.ps.stats[STAT_FLASHES] := client^.ps.stats[STAT_FLASHES] OR 2;
// total points of damage shot at the player this frame
count := (client^.damage_blood + client^.damage_armor + client^.damage_parmor);
if (count = 0) then
Exit; // didn't take any damage
// start a pain animation if still in the player model
if (client^.anim_priority < ANIM_PAIN) AND (player^.s.modelindex = 255) then
begin
client^.anim_priority := ANIM_PAIN;
if (client^.ps.pmove.pm_flags AND PMF_DUCKED) <> 0 then
begin
player^.s.frame := FRAME_crpain1-1;
client^.anim_end := FRAME_crpain4;
end
else begin
i := (i+1) MOD 3;
Case i of
0: begin
player^.s.frame := FRAME_pain101-1;
client^.anim_end := FRAME_pain104;
end;
1: begin
player^.s.frame := FRAME_pain201-1;
client^.anim_end := FRAME_pain204;
end;
2: begin
player^.s.frame := FRAME_pain301-1;
client^.anim_end := FRAME_pain304;
end;
end;
end;
end;
realcount := count;
if (count < 10) then
count := 10; // allways make a visible effect
// play an apropriate pain sound
if ( (level.time > player^.pain_debounce_time) and
((player^.flags and FL_GODMODE) = 0) and
(client^.invincible_framenum <= level.framenum) ) then
begin
r := 1 + (rand() and 1);
player^.pain_debounce_time := level.time + 0.7;
if (player^.health < 25) then
l := 25
else if (player^.health < 50) then
l := 50
else if (player^.health < 75) then
l := 75
else
l := 100;
gi.sound (player, CHAN_VOICE, gi.soundindex(va('*pain%i_%i.wav', [l, r])), 1, ATTN_NORM, 0);
end;
// the total alpha of the blend is allways proportional to count
if (client^.damage_alpha < 0) then
client^.damage_alpha := 0;
client^.damage_alpha := client^.damage_alpha + (count*0.01);
if (client^.damage_alpha < 0.2) then
client^.damage_alpha := 0.2;
if (client^.damage_alpha > 0.6) then
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 <> 0) then
VectorMA (v, client^.damage_parmor/realcount, power_color, v);
if (client^.damage_armor <> 0) then
VectorMA (v, client^.damage_armor/realcount, acolor, v);
if (client^.damage_blood <> 0) then
VectorMA (v, client^.damage_blood/realcount, bcolor, v);
VectorCopy (v, client^.damage_blend);
//
// calculate view angle kicks
//
kick := abs(client^.damage_knockback);
if (kick <> 0) AND (player^.health > 0) then // kick of 0 means no view adjust at all
begin
kick := kick * 100 / player^.health;
if (kick < count*0.5) then
kick := count*0.5;
if (kick > 50) then
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;
end;
//
// clear totals
//
client^.damage_blood := 0;
client^.damage_armor := 0;
client^.damage_parmor := 0;
client^.damage_knockback := 0;
end;
{*
===============
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
===============
*}
procedure SV_CalcViewOffset (ent : edict_p); //only imp
var
bob,
ratio,
delta : Single;
angles: vec3_p;
v : vec3_t;
begin
//===================================
// base angles
angles := @ent^.client^.ps.kick_angles;
// if dead, fix the angle and don't add any kick
if (ent^.deadflag <> 0) then
begin
VectorClear (angles^);
ent^.client^.ps.viewangles[ROLL] := 40;
ent^.client^.ps.viewangles[PITCH] := -15;
ent^.client^.ps.viewangles[YAW] := ent^.client^.killer_yaw;
end
else begin
// 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) then
begin
ratio := 0;
ent^.client^.v_dmg_pitch := 0;
ent^.client^.v_dmg_roll := 0;
end;
angles^[PITCH] := angles^[PITCH] + ratio * ent^.client^.v_dmg_pitch;
angles^[ROLL] := angles^[ROLL] + ratio * ent^.client^.v_dmg_roll;
// add pitch based on fall kick
ratio := (ent^.client^.fall_time - level.time) / FALL_TIME;
if (ratio < 0) then
ratio := 0;
angles^[PITCH] := angles^[PITCH] + ratio * ent^.client^.fall_value;
// add angles based on velocity
delta := DotProduct (ent^.velocity, forward_);
angles^[PITCH] := angles^[PITCH] + delta*run_pitch^.value;
delta := DotProduct (ent^.velocity, right);
angles^[ROLL] := angles^[ROLL] + delta*run_roll^.value;
// add angles based on bob
delta := bobfracsin * bob_pitch^.value * xyspeed;
if ((ent^.client^.ps.pmove.pm_flags AND PMF_DUCKED) <> 0) then
delta := delta * 6; // crouching
angles^[PITCH] := angles^[PITCH] + delta;
delta := bobfracsin * bob_roll^.value * xyspeed;
if ((ent^.client^.ps.pmove.pm_flags AND PMF_DUCKED) <> 0) then
delta := delta * 6; // crouching
if (bobcycle and 1) <> 0 then
delta := -delta;
angles^[ROLL] := angles^[ROLL] + delta;
end;
//===================================
// base origin
VectorClear (v);
// add view height
v[2] := v[2] + ent^.viewheight;
// add fall height
ratio := (ent^.client^.fall_time - level.time) / FALL_TIME;
if (ratio < 0) then
ratio := 0;
v[2] := v[2] - ratio * ent^.client^.fall_value * 0.4;
// add bob height
bob := bobfracsin * xyspeed * bob_up^.value;
if (bob > 6) then
bob := 6;
//idsoft gi.DebugGraph (bob *2, 255);
v[2] := v[2] + bob;
// add kick offset
VectorAdd (v, ent^.client^.kick_origin, v);
// absolutely bound offsets
// so the view can never be outside the player box
if (v[0] < -14) then
v[0] := -14
else if (v[0] > 14) then
v[0] := 14;
if (v[1] < -14) then
v[1] := -14
else if (v[1] > 14) then
v[1] := 14;
if (v[2] < -22) then
v[2] := -22
else if (v[2] > 30) then
v[2] := 30;
VectorCopy (v, ent^.client^.ps.viewoffset);
end;
{*
==============
SV_CalcGunOffset
==============
*}
procedure SV_CalcGunOffset (ent : edict_p); //only imp
var
i : integer;
delta : Single;
begin
// gun angles from bobbing
ent^.client^.ps.gunangles[ROLL] := xyspeed * bobfracsin * 0.005;
ent^.client^.ps.gunangles[YAW] := xyspeed * bobfracsin * 0.01;
if (bobcycle and 1) <> 0 then
begin
ent^.client^.ps.gunangles[ROLL] := -ent^.client^.ps.gunangles[ROLL];
ent^.client^.ps.gunangles[YAW] := -ent^.client^.ps.gunangles[YAW];
end;
ent^.client^.ps.gunangles[PITCH] := xyspeed * bobfracsin * 0.005;
// gun angles from delta movement
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -