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

📄 cl_ents.pas

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