📄 cl_ents.pas
字号:
{100%}
{----------------------------------------------------------------------------}
{ }
{ File(s): cl_ents.c }
{ Content: Quake2\Client - builds an intended movement command to send to the server }
{ }
{ Initial conversion by : Dart - hanhpham@web.de }
{ Initial conversion on : 04-April-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: }
{ 03-Jun-2002 Juha Hartikainen (juha@linearteam.org) }
{ - MANY language fixes }
{ }
{ 08-Jun-2002 Juha Hartikainen (juha@linearteam.org) }
{ - Finished conversion. }
{ }
{ * ToDo: }
{ - All places with TODO define }
{----------------------------------------------------------------------------}
{.$DEFINE TODO}
unit cl_ents;
interface
uses
client,
q_shared;
procedure CL_AddEntities;
procedure CL_GetEntitySoundOrigin (ent: integer; org: vec3_t);
function CL_ParseEntityBits (bits: PCardinal):integer;
procedure CL_ParseDelta (pfrom: entity_state_p; pto: entity_state_p; number:integer;bits:integer);
procedure CL_ParseFrame;
var
cl_mod_powerscreen: model_p; // *model_s
//PGM
vidref_val:integer;
//PGM
implementation
uses
Common,
CPas,
net_chan,
cl_scrn,
cl_pred,
cl_main,
cl_view,
Files,
ref,
cl_parse,
cl_newfx,
cl_tent,
g_local,
vid_dll,
cl_fx;
function rand(): integer;
begin
Result := Random($ffff);
end;
(*
=========================================================================
FRAME PARSING
=========================================================================
*)
(*
=================
CL_ParseEntityBits
Returns the entity number and the header bits
=================
*)
var
bitcounts: array[0..32-1] of integer; /// just for protocol profiling
function CL_ParseEntityBits (bits: PCardinal):integer;
var
b, total: Cardinal;
i: integer;
number: integer;
begin
total := MSG_ReadByte (net_message);
if (total and U_MOREBITS1 <> 0) then
begin b := MSG_ReadByte (net_message);
total := total or (b shl 8);
end;
if (total and U_MOREBITS2 <> 0) then
begin b := MSG_ReadByte (net_message);
total :=total or (b shl 16);
end;
if (total and U_MOREBITS3 <> 0) then
begin b := MSG_ReadByte (net_message);
total :=total or (b shl 24);
end;
// count the bits for net profiling
for i:=0 to 32-1 do
if (total and (1 shl i))>0 then
inc(bitcounts[i]);
if (total and U_NUMBER16 <> 0) then
number := MSG_ReadShort (net_message)
else
number := MSG_ReadByte (net_message);
bits^ := total;
result:= number;
end;
(*
==================
CL_ParseDelta
Can go from either a baseline or a previous packet_entity
==================
*)
procedure CL_ParseDelta (pfrom: entity_state_p; pto: entity_state_p; number:integer;bits:integer);
begin // set everything to the state we are delta'ing from
pto^ := pfrom^;
VectorCopy (pfrom.origin, pto.old_origin);
pto.number := number;
if (bits and U_MODEL <>0) then
pto.modelindex := MSG_ReadByte (net_message);
if (bits and U_MODEL2<>0) then
pto.modelindex2 := MSG_ReadByte (net_message);
if (bits and U_MODEL3<>0) then
pto.modelindex3 := MSG_ReadByte (net_message);
if (bits and U_MODEL4<>0) then
pto.modelindex4 := MSG_ReadByte (net_message);
if (bits and U_FRAME8<>0) then
pto.frame := MSG_ReadByte (net_message);
if (bits and U_FRAME16<>0) then
pto.frame := MSG_ReadShort (net_message);
if (bits and U_SKIN8<>0) and
(bits and U_SKIN16<>0) then //used for laser colors
pto.skinnum := MSG_ReadLong(net_message)
else if (bits and U_SKIN8<>0) then
pto.skinnum := MSG_ReadByte(net_message)
else if (bits and U_SKIN16<>0) then
pto.skinnum := MSG_ReadShort(net_message);
if ( (bits and (U_EFFECTS8 or U_EFFECTS16)) = (U_EFFECTS8 or U_EFFECTS16) ) then
pto.effects := MSG_ReadLong(net_message)
else if (bits and U_EFFECTS8<>0) then
pto.effects := MSG_ReadByte(net_message)
else if (bits and U_EFFECTS16<>0) then
pto.effects := MSG_ReadShort(net_message);
if ( (bits and (U_RENDERFX8 or U_RENDERFX16)) = (U_RENDERFX8 or U_RENDERFX16) ) then
pto.renderfx := MSG_ReadLong(net_message)
else if (bits and U_RENDERFX8<>0) then
pto.renderfx := MSG_ReadByte(net_message)
else if (bits and U_RENDERFX16<>0) then
pto.renderfx := MSG_ReadShort(net_message);
if (bits and U_ORIGIN1<>0) then
pto.origin[0] := MSG_ReadCoord (net_message);
if (bits and U_ORIGIN2<>0) then
pto.origin[1] := MSG_ReadCoord (net_message);
if (bits and U_ORIGIN3<>0) then
pto.origin[2] := MSG_ReadCoord (net_message);
if (bits and U_ANGLE1<>0) then
pto.angles[0] := MSG_ReadAngle(net_message);
if (bits and U_ANGLE2<>0) then
pto.angles[1] := MSG_ReadAngle(net_message);
if (bits and U_ANGLE3<>0) then
pto.angles[2] := MSG_ReadAngle(net_message);
if (bits and U_OLDORIGIN<>0) then
MSG_ReadPos (net_message, pto.old_origin);
if (bits and U_SOUND<>0) then
pto.sound := MSG_ReadByte (net_message);
if (bits and U_EVENT<>0) then
pto.event := entity_event_t(MSG_ReadByte (net_message))
else
pto.event := entity_event_t(0);
if (bits and U_SOLID<>0) then
pto.solid := MSG_ReadShort (net_message);
end;
(*
==================
CL_DeltaEntity
Parses deltas from the given base and adds the resulting entity
to the current frame
==================
*)
procedure CL_DeltaEntity (frame: frame_p; newnum: integer; old: entity_state_p; bits:integer);
var
ent: centity_p;
state: entity_state_p;
begin
ent := @cl_entities[newnum];
state := @cl_parse_entities[cl.parse_entities and (MAX_PARSE_ENTITIES-1)];
inc(cl.parse_entities);
inc(frame.num_entities);
CL_ParseDelta (old, state, newnum, bits);
// some data changes will force no lerping
if (state.modelindex <> ent.current.modelindex)or
(state.modelindex2 <> ent.current.modelindex2)or
(state.modelindex3 <> ent.current.modelindex3)or
(state.modelindex4 <> ent.current.modelindex4)or
(abs(state.origin[0] - ent.current.origin[0]) > 512)or
(abs(state.origin[1] - ent.current.origin[1]) > 512)or
(abs(state.origin[2] - ent.current.origin[2]) > 512)or
(state.event = EV_PLAYER_TELEPORT)or
(state.event = EV_OTHER_TELEPORT)
then ent.serverframe := -99;
if (ent.serverframe <> cl.frame.serverframe - 1) then
begin // wasn't in last update, so initialize some things
ent.trailcount := 1024; // for diminishing rocket / grenade trails
// duplicate the current state so lerping doesn't hurt anything
ent.prev := state^;
if (state.event = EV_OTHER_TELEPORT) then
begin VectorCopy (state.origin, ent.prev.origin);
VectorCopy (state.origin, ent.lerp_origin);
end
else
begin VectorCopy (state.old_origin, ent.prev.origin);
VectorCopy (state.old_origin, ent.lerp_origin);
end;
end
else
begin // shuffle the last state to previous
ent.prev := ent.current;
end;
ent.serverframe := cl.frame.serverframe;
ent.current := state^;
end;
(*
==================
CL_ParsePacketEntities
An svc_packetentities has just been parsed, deal with the
rest of the data stream.
==================
*)
procedure CL_ParsePacketEntities (oldframe: frame_p; newframe: frame_p);
var
newnum: integer;
bits: integer;
oldstate: entity_state_p;
oldindex, oldnum: integer;
begin
newframe.parse_entities := cl.parse_entities;
newframe.num_entities := 0;
// delta from the entities present in oldframe
oldindex := 0;
if (oldframe = nil) then
oldnum := 99999
else
begin if (oldindex >= oldframe.num_entities) then
oldnum := 99999
else
begin
oldstate := @cl_parse_entities[(oldframe.parse_entities+oldindex) and (MAX_PARSE_ENTITIES-1)];
oldnum := oldstate.number;
end;
end;
while (true) do
begin newnum := CL_ParseEntityBits (@bits);
if (newnum >= MAX_EDICTS) then
Com_Error (ERR_DROP,'CL_ParsePacketEntities: bad number:%d', [newnum]);
if (net_message.readcount > net_message.cursize) then
Com_Error (ERR_DROP,'CL_ParsePacketEntities: end of message', []);
if (newnum = 0) then
break;
while (oldnum < newnum) do
begin // one or more entities from the old packet are unchanged
if (cl_shownet.value = 3) then
Com_Printf (' unchanged: %d'#10, [oldnum]);
CL_DeltaEntity (newframe, oldnum, oldstate, 0);
inc(oldindex);
if (oldindex >= oldframe.num_entities) then
oldnum := 99999
else
begin oldstate := @cl_parse_entities[(oldframe.parse_entities+oldindex) and (MAX_PARSE_ENTITIES-1)];
oldnum := oldstate.number;
end;
end;
if (bits and U_REMOVE<>0) then
begin // the entity present in oldframe is not in the current frame
if (cl_shownet.value = 3) then
Com_Printf (' remove: %d'#10, [newnum]);
if (oldnum <> newnum) then
Com_Printf ('U_REMOVE: oldnum != newnum'#10, []);
inc(oldindex);
if (oldindex >= oldframe.num_entities) then
oldnum := 99999
else
begin oldstate := @cl_parse_entities[(oldframe.parse_entities+oldindex) and (MAX_PARSE_ENTITIES-1)];
oldnum := oldstate.number;
end;
continue;
end;
if (oldnum = newnum) then
begin // delta from previous state
if (cl_shownet.value = 3) then
Com_Printf (' delta: %d'#10, [newnum]);
CL_DeltaEntity (newframe, newnum, oldstate, bits);
inc(oldindex);
if (oldindex >= oldframe.num_entities) then
oldnum := 99999
else
begin
oldstate := @cl_parse_entities[(oldframe.parse_entities+oldindex) and (MAX_PARSE_ENTITIES-1)];
oldnum := oldstate.number;
end;
continue;
end;
if (oldnum > newnum) then
begin // delta from baseline
if (cl_shownet.value = 3) then
Com_Printf (' baseline: %d'#10, [newnum]);
CL_DeltaEntity (newframe, newnum, @cl_entities[newnum].baseline, bits);
continue;
end;
end;
// any remaining entities in the old frame are copied over
while (oldnum <> 99999) do
begin // one or more entities from the old packet are unchanged
if (cl_shownet.value = 3) then
Com_Printf (' unchanged: %d'#10, [oldnum]);
CL_DeltaEntity (newframe, oldnum, oldstate, 0);
inc(oldindex);
if (oldindex >= oldframe.num_entities) then
oldnum := 99999
else
begin
oldstate := @cl_parse_entities[(oldframe.parse_entities+oldindex) and (MAX_PARSE_ENTITIES-1)];
oldnum := oldstate.number;
end;
end;
end;
(*
===================
CL_ParsePlayerstate
===================
*)
procedure CL_ParsePlayerstate (oldframe: frame_p; newframe: frame_p);
var
flags : integer;
state : player_state_p;
i : integer;
statbits: integer;
begin
state := @newframe.playerstate;
// clear to old value before delta parsing
if (oldframe <> nil) then
state^ := oldframe.playerstate
else
FillChar(state^, sizeof(player_state_t), 0);
flags := MSG_ReadShort (net_message);
//
// parse the pmove_state_t
//
if (flags and PS_M_TYPE<>0) then
state.pmove.pm_type := pmtype_t(MSG_ReadByte (net_message));
if (flags and PS_M_ORIGIN<>0) then
begin state.pmove.origin[0] := MSG_ReadShort (net_message);
state.pmove.origin[1] := MSG_ReadShort (net_message);
state.pmove.origin[2] := MSG_ReadShort (net_message);
end;
if (flags and PS_M_VELOCITY<>0) then
begin state.pmove.velocity[0] := MSG_ReadShort (net_message);
state.pmove.velocity[1] := MSG_ReadShort (net_message);
state.pmove.velocity[2] := MSG_ReadShort (net_message);
end;
if (flags and PS_M_TIME<>0) then
state.pmove.pm_time := MSG_ReadByte (net_message);
if (flags and PS_M_FLAGS<>0) then
state.pmove.pm_flags:= MSG_ReadByte (net_message);
if (flags and PS_M_GRAVITY<>0) then
state.pmove.gravity := MSG_ReadShort (net_message);
if (flags and PS_M_DELTA_ANGLES<>0) then
begin state.pmove.delta_angles[0] := MSG_ReadShort (net_message);
state.pmove.delta_angles[1] := MSG_ReadShort (net_message);
state.pmove.delta_angles[2] := MSG_ReadShort (net_message);
end;
if (cl.attractloop) then
state.pmove.pm_type := PM_FREEZE; // demo playback
//
// parse the rest of the player_state_t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -