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

📄 cl_pred.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
字号:
{100%}
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): cl_pred.c                                                         }
{ Content:                                                                   }
{                                                                            }
{ Initial conversion by : Skybuck Flying  (skybuck2000@hotmail.com)          }
{ Initial conversion on : 5-march-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.                       }
{                                                                            }
{----------------------------------------------------------------------------}
{ Changes:                                                                   }
{ 08-Jun-2002 Juha Hartikainen:                                              }
{ - Completed conversion.                                                    }
{                                                                            }
{----------------------------------------------------------------------------}
// cl_pred.c
unit cl_pred;

interface

uses
  Client,
  q_shared;

procedure CL_CheckPredictionError;
procedure CL_ClipMoveToEntities ( start, mins, maxs, end_ : vec3_t; tr : ptrace_t );
procedure CL_PredictMovement;

implementation

uses
  SysUtils,
  CPas,
  Common,
  CModel,
  PMoveUnit,
  g_local,
  cl_main;

{
===================
CL_CheckPredictionError
===================
}

procedure CL_CheckPredictionError;
var
	frame : integer;
	delta : array[0..2] of integer;
	i : integer;
	len : integer;
begin

	if (not (cl_predict^.value<>0)) or
     (cl.frame.playerstate.pmove.pm_flags and PMF_NO_PREDICTION <> 0) then
		exit;

	// calculate the last usercmd_t we sent that the server has processed
	frame := cls.netchan.incoming_acknowledged;

	frame := frame and (CMD_BACKUP-1);

	// compare what the server returned with what we had predicted it to be
	VectorSubtract (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame], delta);

	// save the prediction error for interpolation
	len := abs(delta[0]) + abs(delta[1]) + abs(delta[2]);
	if (len > 640) then	// 80 world units
	begin
	// a teleport or something
		VectorClear (cl.prediction_error);
	end else
	begin
		if (cl_showmiss^.value<>0) and ((delta[0]<>0) or (delta[1]<>0) or (delta[2]<>0) ) then
		begin
			Com_Printf ('prediction miss on %d: %d'#10, [cl.frame.serverframe,
			delta[0] + delta[1] + delta[2]]);
		end;

		VectorCopy (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame]);

		// save for error itnerpolation
		for i:=0 to 2 do
		begin
			cl.prediction_error[i] := delta[i]*0.125;
		end;
	end;
end;


{
====================
CL_ClipMoveToEntities

====================
}

procedure CL_ClipMoveToEntities ( start, mins, maxs, end_ : vec3_t; tr : ptrace_t );
var
	i, x, zd, zu: integer;
	trace: trace_t;
	headnode: integer;
	angles: psingle;
	ent: entity_state_p;
	num: integer;
	cmodel: pcmodel_t;
	bmins, bmaxs: vec3_t;
begin
	if cl.frame.num_entities > 0 then
	for i:=0 to cl.frame.num_entities-1 do
	begin
		num := (cl.frame.parse_entities + i) and (MAX_PARSE_ENTITIES-1);
		ent := @cl_parse_entities[num];

		if (not ent^.solid<>0)	then continue;

		if (ent^.number = cl.playernum+1) then continue;

		if (ent^.solid = 31) then
		begin
			// special value for bmodel
			cmodel := cl.model_clip[ent^.modelindex];
			if (cmodel = nil) then continue;
			headnode := cmodel^.headnode;
			angles := @ent^.angles;
		end	else
		begin
			// encoded bbox
			x := 8*(ent^.solid and 31);
			zd := 8*((ent^.solid shr 5) and 31);
			zu := 8*((ent^.solid shr 10) and 63) - 32;

			bmins[0] := -x;
      bmins[1] := -x;
			bmaxs[0] := x;
      bmaxs[1] := x;
			bmins[2] := -zd;
			bmaxs[2] := zu;

			headnode := CM_HeadnodeForBox (bmins, bmaxs);
			angles := @vec3_origin;	// boxes don't rotate
		end;

		if (tr^.allsolid) then
			exit;

		trace := CM_TransformedBoxTrace (start, end_,
			mins, maxs, headnode,  MASK_PLAYERSOLID, ent^.origin, vec3_p(angles)^);

		if (trace.allsolid or trace.startsolid or (trace.fraction < tr^.fraction) ) then
		begin
			trace.ent := @ent;
		 	if (tr^.startsolid) then
			begin
				tr^ := trace;
				tr^.startsolid := true;
			end	else
			begin
				tr^ := trace;
			end;
		end else
		begin
			if (trace.startsolid) then
			begin
				tr^.startsolid := true;
			end;
		end;
	end;
end;


{
================
CL_PMTrace
================
}

function CL_PMTrace ( start, mins, maxs, _end : vec3_t ) : trace_t; cdecl;
var
	t : trace_t;
begin

	// check against world
	t := CM_BoxTrace (start, _end, mins, maxs, 0, MASK_PLAYERSOLID);
	if (t.fraction < 1.0) then
	begin
		t.ent := edict_p(1);
	end;

	// check all other solid models
	CL_ClipMoveToEntities (start, mins, maxs, _end, @t);

	result := t;
end;

function CL_PMpointcontents ( _point : vec3_t ) : integer; cdecl;
var
	i : integer;
	ent : entity_state_p;
	num : integer;
	cmodel : cmodel_p;
	contents : integer;
begin

	contents := CM_PointContents (_point, 0);

	//if cl.frame.num_entities > 0 then
	for i:=0 to cl.frame.num_entities-1 do
	begin

		num := (cl.frame.parse_entities + i) and (MAX_PARSE_ENTITIES-1);
		ent := @cl_parse_entities[num];

		if (ent^.solid <> 31) then // special value for bmodel
			continue;

		cmodel := cl.model_clip[ent^.modelindex];
		if (cmodel = nil) then
			continue;

		contents := contents or CM_TransformedPointContents (_point, cmodel^.headnode, ent^.origin, ent^.angles);
	end;

	result := contents;
end;


{
=================
CL_PredictMovement

Sets cl.predicted_origin and cl.predicted_angles
=================
}

procedure CL_PredictMovement;
var
	ack, current : integer;
	frame : integer;
	oldframe : integer;
	cmd : usercmd_p;
	pm : pmove_t;
	i : integer;
	step : integer;
	oldz : integer;
begin

	if (cls.state <> ca_active) then
		exit;

	if (cl_paused^.value <> 0) then
		exit;

	if (cl_predict.value=0) or (cl.frame.playerstate.pmove.pm_flags and PMF_NO_PREDICTION<>0) then
	begin
		// just set angles
		for i:=0 to 2 do
		begin
			cl.predicted_angles[i] := cl.viewangles[i] + SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[i]);
		end;
		exit;
	end;

	ack := cls.netchan.incoming_acknowledged;
	current := cls.netchan.outgoing_sequence;

	// if we are too far out of date, just freeze
	if (current - ack >= CMD_BACKUP) then
	begin
		if (cl_showmiss.value <> 0) then
			Com_Printf ('exceeded CMD_BACKUP'#10, []);
		exit;
	end;

	// copy current state to pmove
	FillChar (pm, sizeof(pm), #0);

	pm.trace := @CL_PMTrace;
	pm.pointcontents := @CL_PMpointcontents;

	pm_airaccelerate := atof(cl.configstrings[CS_AIRACCEL]);

	pm.s := cl.frame.playerstate.pmove;

//	SCR_DebugGraph (current - ack - 1, 0);

	// run frames
  Inc(ack);
	while (ack < current) do 
	begin
		frame := ack and (CMD_BACKUP-1);
		cmd := @cl.cmds[frame];

		pm.cmd := cmd^;
		Pmove (@pm);

		// save for debug checking
		VectorCopy (pm.s.origin, cl.predicted_origins[frame]);
    Inc(ack);
	end;

	oldframe := (ack-2) and (CMD_BACKUP-1);
	oldz := cl.predicted_origins[oldframe][2];
	step := pm.s.origin[2] - oldz;
	if (step > 63) and (step < 160) and (pm.s.pm_flags and PMF_ON_GROUND<>0) then
	begin
		cl.predicted_step := step * 0.125;
		cl.predicted_step_time := Round(cls.realtime - cls.frametime * 500);
	end;


	// copy results out for rendering
	cl.predicted_origin[0] := pm.s.origin[0]*0.125;
	cl.predicted_origin[1] := pm.s.origin[1]*0.125;
	cl.predicted_origin[2] := pm.s.origin[2]*0.125;

	VectorCopy (pm.viewangles, cl.predicted_angles);
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -