📄 cl_ents.pas
字号:
//
if (flags and PS_VIEWOFFSET<>0) then
begin state.viewoffset[0] := MSG_ReadChar (net_message) * 0.25;
state.viewoffset[1] := MSG_ReadChar (net_message) * 0.25;
state.viewoffset[2] := MSG_ReadChar (net_message) * 0.25;
end;
if (flags and PS_VIEWANGLES<>0) then
begin state.viewangles[0] := MSG_ReadAngle16 (net_message);
state.viewangles[1] := MSG_ReadAngle16 (net_message);
state.viewangles[2] := MSG_ReadAngle16 (net_message);
end;
if (flags and PS_KICKANGLES<>0) then
begin
state.kick_angles[0] := MSG_ReadChar (net_message) * 0.25;
state.kick_angles[1] := MSG_ReadChar (net_message) * 0.25;
state.kick_angles[2] := MSG_ReadChar (net_message) * 0.25;
end;
if (flags and PS_WEAPONINDEX<>0) then
begin
state.gunindex := MSG_ReadByte (net_message);
end;
if (flags and PS_WEAPONFRAME<>0) then
begin
state.gunframe := MSG_ReadByte (net_message);
state.gunoffset[0] := MSG_ReadChar (net_message)*0.25;
state.gunoffset[1] := MSG_ReadChar (net_message)*0.25;
state.gunoffset[2] := MSG_ReadChar (net_message)*0.25;
state.gunangles[0] := MSG_ReadChar (net_message)*0.25;
state.gunangles[1] := MSG_ReadChar (net_message)*0.25;
state.gunangles[2] := MSG_ReadChar (net_message)*0.25;
end;
if (flags and PS_BLEND<>0) then
begin state.blend[0] := MSG_ReadByte (net_message)/255.0;
state.blend[1] := MSG_ReadByte (net_message)/255.0;
state.blend[2] := MSG_ReadByte (net_message)/255.0;
state.blend[3] := MSG_ReadByte (net_message)/255.0;
end;
if (flags and PS_FOV<>0) then
state.fov := MSG_ReadByte (net_message);
if (flags and PS_RDFLAGS<>0) then
state.rdflags := MSG_ReadByte (net_message);
// parse stats
statbits := MSG_ReadLong (net_message);
for i:= 0 to MAX_STATS-1 do
if (statbits and (1 shl i) <>0) then
state.stats[i] := MSG_ReadShort(net_message);
end;
(*
==================
CL_FireEntityEvents
==================
*)
procedure CL_FireEntityEvents (frame: frame_p);
var
s1: entity_state_p;
pnum, num: integer;
begin for pnum:=0 to frame.num_entities-1 do
begin num := (frame.parse_entities + pnum)and(MAX_PARSE_ENTITIES-1);
s1 := @cl_parse_entities[num];
if (Integer(s1.event) <> 0) then
CL_EntityEvent (s1);
// EF_TELEPORTER acts like an event, but is not cleared each frame
if (s1.effects and EF_TELEPORTER <> 0) then
CL_TeleporterParticles (s1);
end;
end;
(*
================
CL_ParseFrame
================
*)
procedure CL_ParseFrame;
var
cmd: integer;
len: integer;
old: frame_p;
begin
fillchar(cl.frame, sizeof(cl.frame),0);
{$ifdef 0}
CL_ClearProjectiles(); // clear projectiles for new frame
{$endif}
cl.frame.serverframe := MSG_ReadLong (net_message);
cl.frame.deltaframe := MSG_ReadLong (net_message);
cl.frame.servertime := cl.frame.serverframe*100;
// BIG HACK to let old demos continue to work
if (cls.serverProtocol <> 26) then
cl.surpressCount := MSG_ReadByte (net_message);
if (cl_shownet.value = 3) then
Com_Printf (' frame:%d delta:%d'#10, [cl.frame.serverframe,
cl.frame.deltaframe]);
// If the frame is delta compressed from data that we
// no longer have available, we must suck up the rest of
// the frame, but not use it, then ask for a non-compressed
// message
if (cl.frame.deltaframe <= 0) then
begin cl.frame.valid := true; // uncompressed frame
old := nil;
cls.demowaiting:= false; // we can start recording now
end
else
begin old := @cl.frames[cl.frame.deltaframe and UPDATE_MASK];
if (not old.valid) then
begin // should never happen
Com_Printf ('Delta from invalid frame (not supposed to happen!).'#10, []);
end;
if (old.serverframe <> cl.frame.deltaframe) then
begin // The frame that the server did the delta from
// is too old, so we can't reconstruct it properly.
Com_Printf ('Delta frame too old.'#10, []);
end
else if (cl.parse_entities - old.parse_entities > MAX_PARSE_ENTITIES-128) then
begin
Com_Printf ('Delta parse_entities too old.'#10, []);
end
else
cl.frame.valid := true; // valid delta parse
end;
// clamp time
if (cl.time > cl.frame.servertime) then
cl.time := cl.frame.servertime
else if (cl.time < cl.frame.servertime - 100) then
cl.time := cl.frame.servertime - 100;
// read areabits
len := MSG_ReadByte (net_message);
MSG_ReadData (net_message, @cl.frame.areabits, len);
// read playerinfo
cmd := MSG_ReadByte (net_message);
SHOWNET(svc_strings[cmd]);
if (cmd <> Integer(svc_playerinfo)) then
Com_Error (ERR_DROP, 'CL_ParseFrame: not playerinfo', []);
CL_ParsePlayerstate (old, @cl.frame);
// read packet entities
cmd := MSG_ReadByte (net_message);
SHOWNET(svc_strings[cmd]);
if (cmd <> Integer(svc_packetentities)) then
Com_Error (ERR_DROP, 'CL_ParseFrame: not packetentities', []);
CL_ParsePacketEntities (old, @cl.frame);
{$IFDEF NEVEREVER}
if (cmd = svc_packetentities2) then
CL_ParseProjectiles();
{$ENDIF}
// save the frame off in the backup array for later delta comparisons
cl.frames[cl.frame.serverframe and UPDATE_MASK] := cl.frame;
if (cl.frame.valid) then
begin // getting a valid frame message ends the connection process
if (cls.state <> ca_active) then
begin cls.state := ca_active;
cl.force_refdef := true;
cl.predicted_origin[0] := cl.frame.playerstate.pmove.origin[0]*0.125;
cl.predicted_origin[1] := cl.frame.playerstate.pmove.origin[1]*0.125;
cl.predicted_origin[2] := cl.frame.playerstate.pmove.origin[2]*0.125;
VectorCopy (cl.frame.playerstate.viewangles, cl.predicted_angles);
if (cls.disable_servercount <> cl.servercount) and
(cl.refresh_prepped) then
SCR_EndLoadingPlaque (); // get rid of loading plaque
end;
cl.sound_prepped := true; // can start mixing ambient sounds
// fire entity events
CL_FireEntityEvents (@cl.frame);
CL_CheckPredictionError ();
end;
end;
(*
==========================================================================
INTERPOLATE BETWEEN FRAMES TO GET RENDERING PARMS
==========================================================================
*)
function S_RegisterSexedModel (ent: entity_state_p; base: pchar): pmodel_s;
var
n: integer;
p: pchar;
mdl: pmodel_s;
model: array[0..MAX_QPATH-1] of char;
buffer: array[0..MAX_QPATH-1] of char;
begin
// determine what model the client is using
model[0] := #0;
n := CS_PLAYERSKINS + ent.number - 1;
if (cl.configstrings[n][0] <> #0) then begin
p := strchr(cl.configstrings[n], Byte('\'));
if (p <> nil) then begin
p := p + 1;
strcpy(model, p);
p := strchr(model, Byte('/'));
if (p <> nil) then
p^ := #0;
end;
end;
// if we can't figure it out, they're male
if (model[0] = #0) then
strcpy(model, 'male');
Com_sprintf (buffer, sizeof(buffer), 'players/%s/%s', [model, base+1]);
mdl := re.RegisterModel(buffer);
if (mdl = nil) then begin
// not found, try default weapon model
Com_sprintf (buffer, sizeof(buffer), 'players/%s/weapon.md2', [model]);
mdl := re.RegisterModel(buffer);
if (mdl = nil) then begin
// no, revert to the male model
Com_sprintf (buffer, sizeof(buffer), 'players/%s/%s', ['male', base+1]);
mdl := re.RegisterModel(buffer);
if (mdl = nil) then begin
// last try, default male weapon.md2
Com_sprintf (buffer, sizeof(buffer), 'players/male/weapon.md2', []);
mdl := re.RegisterModel(buffer);
end;
end;
end;
Result := mdl;
end;
// PMM - used in shell code
//extern int Developer_searchpath (int who);
// pmm
(*
===============
CL_AddPacketEntities
===============
*)
var
bfg_lightramp: array[0..5] of integer = (300, 400, 600, 300, 150, 75);
procedure CL_AddPacketEntities (frame: frame_p);
var
ent: entity_t;
s1: entity_state_p;
autorotate: single;
i: integer;
pnum: integer;
cent: centity_p;
autoanim: integer;
ci: clientinfo_p;
effects, renderfx: LongWord;
forward_, start: vec3_t;
a1, a2: single;
intensity: single;
begin
// bonus items rotate at a fixed rate
autorotate := anglemod(cl.time/10);
// brush models can auto animate their frames
autoanim := Round(2*cl.time/1000);
FillChar (ent, sizeof(ent), #0);
for pnum := 0 to frame.num_entities-1 do begin
s1 := @cl_parse_entities[(frame.parse_entities+pnum) and (MAX_PARSE_ENTITIES-1)];
cent := @cl_entities[s1.number];
effects := s1.effects;
renderfx := s1.renderfx;
// set frame
if (effects and EF_ANIM01 <> 0) then
ent.frame := autoanim and 1
else if (effects and EF_ANIM23 <> 0) then
ent.frame := 2 + (autoanim and 1)
else if (effects and EF_ANIM_ALL <> 0) then
ent.frame := autoanim
else if (effects and EF_ANIM_ALLFAST <> 0) then
ent.frame := Round(cl.time / 100)
else
ent.frame := s1.frame;
// quad and pent can do different things on client
if (effects and EF_PENT<>0) then begin
effects := effects and (not EF_PENT);
effects := effects or EF_COLOR_SHELL;
renderfx := renderfx or RF_SHELL_RED;
end;
if (effects and EF_QUAD <> 0) then begin
effects := effects and (not EF_QUAD);
effects := effects or EF_COLOR_SHELL;
renderfx := renderfx or RF_SHELL_BLUE;
end;
//======
// PMM
if (effects and EF_DOUBLE <> 0) then begin
effects := effects and (not EF_DOUBLE);
effects := effects or EF_COLOR_SHELL;
renderfx := renderfx or RF_SHELL_DOUBLE;
end;
if (effects and EF_HALF_DAMAGE <> 0) then begin
effects := effects and (not EF_HALF_DAMAGE);
effects := effects or EF_COLOR_SHELL;
renderfx := effects or RF_SHELL_HALF_DAM;
end;
// pmm
//======
ent.oldframe := cent.prev.frame;
ent.backlerp := 1.0 - cl.lerpfrac;
if ((renderfx and (RF_FRAMELERP or RF_BEAM)) <> 0) then begin
// step origin discretely, because the frames
// do the animation properly
VectorCopy (cent.current.origin, vec3_t(ent.origin));
VectorCopy (cent.current.old_origin, vec3_t(ent.oldorigin));
end
else
begin // interpolate origin
for i := 0 to 2 do begin
ent.origin[i] := cent.prev.origin[i] + cl.lerpfrac *
(cent.current.origin[i] - cent.prev.origin[i]);
ent.oldorigin[i] := ent.origin[i];
end;
end;
// create a new entity
// tweak the color of beams
if ((renderfx and RF_BEAM) <> 0) then begin
// the four beam colors are encoded in 32 bits of skinnum (hack)
ent.alpha := 0.30;
ent.skinnum := (s1.skinnum shr ((rand() mod 4)*8)) and $ff;
ent.model := nil;
end
else
begin
// set skin
if (s1.modelindex = 255) then begin
// use custom player skin
ent.skinnum := 0;
ci := @cl.clientinfo[s1.skinnum and $ff];
ent.skin := ci.skin;
ent.model := ci.model;
if (ent.skin = nil) or (ent.model = nil) then begin
ent.skin := cl.baseclientinfo.skin;
ent.model := cl.baseclientinfo.model;
end;
//============
//PGM
if ((renderfx and RF_USE_DISGUISE) <> 0) then begin
if (strncmp(ent.skin, 'players/male', 12) = 0) then begin
ent.skin := re.RegisterSkin ('players/male/disguise.pcx');
ent.model := re.RegisterModel ('players/male/tris.md2');
end
else if(strncmp(ent.skin, 'players/female', 14) = 0) then
begin
ent.skin := re.RegisterSkin ('players/female/disguise.pcx');
ent.model := re.RegisterModel ('players/female/tris.md2');
end
else if(strncmp(ent.skin, 'players/cyborg', 14) = 0) then
begin
ent.skin := re.RegisterSkin ('players/cyborg/disguise.pcx');
ent.model := re.RegisterModel ('players/cyborg/tris.md2');
end;
end;
//PGM
//============
end
else
begin
ent.skinnum := s1.skinnum;
ent.skin := nil;
ent.model := cl.model_draw[s1.modelindex];
end;
end;
// only used for black hole model right now, FIXME: do better
if (renderfx = RF_TRANSLUCENT) then
ent.alpha := 0.70;
// render effects (fullbright, translucent, etc)
if ((effects and EF_COLOR_SHELL) <> 0) then
ent.flags := 0 // renderfx go on color shell entity
else
ent.flags := renderfx;
// calculate angles
if ((effects and EF_ROTATE) <> 0) then begin
// some bonus items auto-rotate
ent.angles[0] := 0;
ent.angles[1] := autorotate;
ent.angles[2] := 0;
end
// RAFAEL
else if ((effects and EF_SPINNINGLIGHTS) <> 0) then begin
ent.angles[0] := 0;
ent.angles[1] := anglemod(cl.time/2) + s1.angles[1];
ent.angles[2] := 180;
begin
AngleVectors (vec3_t(ent.angles), @forward_, nil, nil);
VectorMA (vec3_t(ent.origin), 64, forward_, start);
V_AddLight (start, 100, 1, 0, 0);
end;
end
else
begin // interpolate angles
for i := 0 to 2 do begin
a1 := cent.current.angles[i];
a2 := cent.prev.angles[i];
ent.angles[i] := LerpAngle (a2, a1, cl.lerpfrac);
end;
end;
if (s1.number = cl.playernum+1) then begin
ent.flags := ent.flags or RF_VIEWERMODEL; // only draw from mirrors
// FIXME: still pass to refresh
if (effects and EF_FLAG1<>0) then
V_AddLight (vec3_t(ent.origin), 225, 1.0, 0.1, 0.1)
else if (effects and EF_FLAG2<>0) then
V_AddLight (vec3_t(ent.origin), 225, 0.1, 0.1, 1.0)
else if (effects and EF_TAGTRAIL<>0) then //PGM
V_AddLight (vec3_t(ent.origin), 225, 1.0, 1.0, 0.0) //PGM
else if (effects and EF_TRACKERTRAIL<>0) then //PGM
V_AddLight (vec3_t(ent.origin), 225, -1.0, -1.0, -1.0); //PGM
continue;
end;
// if set to invisible, skip
if (s1.modelindex = 0) then
continue;
if ((effects and EF_BFG) <> 0) then begin
ent.flags := ent.flags or RF_TRANSLUCENT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -