⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cl_ents.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
{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 + -