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

📄 cl_newfx.pas

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

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*)
// cl_newfx.c -- MORE entity effects parsing and management

unit cl_newfx;

interface

uses
  ref,
  g_local,
  Client;

procedure CL_Flashlight(ent: Integer; pos: vec3_t);
procedure CL_ColorFlash(pos: vec3_t; ent, intensity: Integer; r, g, b: Single);
procedure CL_DebugTrail(start, end_: vec3_t);
procedure CL_SmokeTrail(start, end_: vec3_t; colorStart, colorRun, spacing: Integer);
procedure CL_ForceWall (start, end_: vec3_t; color: Integer);
procedure CL_FlameEffects (ent: centity_p; origin: vec3_t);
procedure CL_GenericParticleEffect (org, dir: vec3_t; color, count, numcolors, dirspread: Integer; alphavel: Single);
procedure CL_BubbleTrail2 (start, end_: vec3_t; dist: Integer);
procedure CL_Heatbeam (start, forward_: vec3_t);
procedure CL_ParticleSteamEffect (org, dir: vec3_t; color, count, magnitude: Integer);
procedure CL_ParticleSteamEffect2 (self: pcl_sustain_t); cdecl;
procedure CL_TrackerTrail (start, end_: vec3_t; particleColor: Integer);
procedure CL_Tracker_Shell(origin: vec3_t);
procedure CL_MonsterPlasma_Shell(origin: vec3_t);
procedure CL_Widowbeamout (self: pcl_sustain_t); cdecl;
procedure CL_Nukeblast (self: pcl_sustain_t); cdecl;
procedure CL_WidowSplash (org: vec3_t);
procedure CL_Tracker_Explode(origin: vec3_t);
procedure CL_TagTrail (start, end_: vec3_t; color: Single);
procedure CL_ColorExplosionParticles (org: vec3_t; color, run: Integer);
procedure CL_ParticleSmokeEffect (org, dir: vec3_t; color, count, magnitude: Integer);
procedure CL_BlasterParticles2 (org, dir: vec3_t; color: Cardinal);
procedure CL_BlasterTrail2 (start, end_: vec3_t);

implementation

uses
  q_shared,
  cl_fx,
  cl_main,
  Common,
  Math;

function rand(): integer;
begin
  Result := Random($ffff);
end;

function fmod(a,b:single):single;
begin
  result := a-(b*int(a/b));
end;

(*
======
vectoangles2 - this is duplicated in the game DLL, but I need it here.
======
*)
procedure vectoangles2(var value1, angles: vec3_t);
var
  forward_: Single;
  yaw_, pitch_: Single;
begin
	if (value1[1] = 0.0) and (value1[0] = 0.0) then
	begin
		yaw_ := 0.0;
		if (value1[2] > 0.0) then
			pitch_ := 90.0
		else
			pitch_ := 270.0;
	end
	else
	begin
	// PMM - fixed to correct for pitch of 0
		if (value1[0] <> 0.0) then
			yaw_ := (ArcTan2(value1[1], value1[0]) * 180.0 / M_PI)
		else if (value1[1] > 0.0) then
			yaw_ := 90
		else
			yaw_ := 270;

		if (yaw_ < 0.0) then
			yaw_ := yaw_ + 360.0;

		forward_ := Sqrt(value1[0] * value1[0] + value1[1] * value1[1]);
		pitch_ := (ArcTan2(value1[2], forward_) * 180.0 / M_PI);
		if (pitch_ < 0.0) then
			pitch_ := pitch_ + 360;
	end;

	angles[PITCH] := -pitch_;
	angles[YAW] := yaw_;
	angles[ROLL] := 0.0;
end;

//=============
//=============
procedure CL_Flashlight(ent: Integer; pos: vec3_t);
var
  dl: pcdlight_t;
begin
	dl := CL_AllocDlight(ent);
	VectorCopy(pos, dl^.origin);
	dl^.radius := 400;
	dl^.minlight := 250;
	dl^.die := cl.time + 100;
	dl^.color[0] := 1;
	dl^.color[1] := 1;
	dl^.color[2] := 1;
end;

(*
======
CL_ColorFlash - flash of light
======
*)
procedure CL_ColorFlash(pos: vec3_t; ent, intensity: Integer; r, g, b: Single);
var
  dl: pcdlight_t;
begin
	if ((vidref_val = VIDREF_SOFT) and ((r < 0) or (g < 0) or (b < 0))) then
	begin
		intensity := -intensity;
		r := -r;
		g := -g;
		b := -b;
	end;

	dl := CL_AllocDlight(ent);
	VectorCopy(pos, dl^.origin);
	dl^.radius := intensity;
	dl^.minlight := 250;
	dl^.die := cl.time + 100;
	dl^.color[0] := r;
	dl^.color[1] := g;
	dl^.color[2] := b;
end;


(*
======
CL_DebugTrail
======
*)
procedure CL_DebugTrail(start, end_: vec3_t);
var
  move, vec: vec3_t;
	len: Single;
//  j: Integer;
	p: cparticle_p;
	dec: Single;
	right, up: vec3_t;
begin
	VectorCopy (start, move);
	VectorSubtract (end_, start, vec);
	len := VectorNormalize (vec);

	MakeNormalVectors (vec, right, up);

//	VectorScale(vec, RT2_SKIP, vec);

//	dec = 1.0;
//	dec = 0.75;
	dec := 3;
	VectorScale (vec, dec, vec);
	VectorCopy (start, move);

	while (len > 0) do
	begin
		len := len - dec;

		if (free_particles = nil) then
			Exit;
		p := free_particles;
		free_particles := p^.next;
		p^.next := active_particles;
		active_particles := p;

		p^.time := cl.time;
		VectorClear (p^.accel);
		VectorClear (p^.vel);
		p^.alpha := 1.0;
		p^.alphavel := -0.1;
//		p^.alphavel := 0;
		p^.color := $74 + (rand() and 7);
		VectorCopy (move, p^.org);
(*
		for j := 0 to 2 do
		begin
			p^.org[j] := move[j] + crand()*2;
			p^.vel[j] := crand()*3;
			p^.accel[j] := 0;
		end;
*)
		VectorAdd (move, vec, move);
	end;
end;

(*
===============
CL_SmokeTrail
===============
*)
procedure CL_SmokeTrail(start, end_: vec3_t; colorStart, colorRun, spacing: Integer);
var
  move, vec: vec3_t;
  len: Single;
  j: Integer;
	p: cparticle_p;
begin
	VectorCopy (start, move);
	VectorSubtract (end_, start, vec);
	len := VectorNormalize (vec);

	VectorScale (vec, spacing, vec);

	// FIXME: this is a really silly way to have a loop
	while (len > 0) do
	begin
		len := len - spacing;

		if (free_particles = nil) then
			Exit;
		p := free_particles;
		free_particles := p^.next;
		p^.next := active_particles;
		active_particles := p;
		VectorClear (p^.accel);

		p^.time := cl.time;

		p^.alpha := 1.0;
		p^.alphavel := -1.0 / (1 + frand() * 0.5);
		p^.color := colorStart + (rand() mod colorRun);
		for j := 0 to 2 do
		begin
			p^.org[j] := move[j] + crand() * 3;
			p^.accel[j] := 0;
		end;
		p^.vel[2] := 20 + crand() * 5;

		VectorAdd (move, vec, move);
	end;
end;

procedure CL_ForceWall (start, end_: vec3_t; color: Integer);
var
	move, vec: vec3_t;
	len: Single;
	j: Integer;
	p: cparticle_p;
begin
	VectorCopy (start, move);
	VectorSubtract (end_, start, vec);
	len := VectorNormalize (vec);

	VectorScale (vec, 4, vec);

	// FIXME: this is a really silly way to have a loop
	while (len > 0) do
	begin
		len := len - 4;

		if (free_particles = nil) then
			Exit;

		if (frand() > 0.3) then
		begin
			p := free_particles;
			free_particles := p^.next;
			p^.next := active_particles;
			active_particles := p;
			VectorClear (p^.accel);

			p^.time := cl.time;

			p^.alpha := 1.0;
			p^.alphavel :=  -1.0 / (3.0 + frand() * 0.5);
			p^.color := color;
			for j := 0 to 2 do
			begin
				p^.org[j] := move[j] + crand() * 3;
				p^.accel[j] := 0;
			end;
			p^.vel[0] := 0;
			p^.vel[1] := 0;
			p^.vel[2] := -40 - (crand() * 10);
		end;

		VectorAdd (move, vec, move);
	end;
end;

procedure CL_FlameEffects (ent: centity_p; origin: vec3_t);
var
	n, count, j: Integer;
	p: cparticle_p;
begin
	count := rand() and $F;

	for n := 0 to count - 1 do
	begin
		if (free_particles = nil) then
			Exit;

		p := free_particles;
		free_particles := p^.next;
		p^.next := active_particles;
		active_particles := p;

		VectorClear (p^.accel);
		p^.time := cl.time;

		p^.alpha := 1.0;
		p^.alphavel := -1.0 / (1 + frand() * 0.2);
		p^.color := 226 + (rand() mod 4);
		for j := 0 to 2 do
		begin
			p^.org[j] := origin[j] + crand() * 5;
			p^.vel[j] := crand() * 5;
		end;
		p^.vel[2] := crand() * -10;
		p^.accel[2] := -PARTICLE_GRAVITY;
	end;

	count := rand() and $7;

	for n := 0 to count - 1 do
	begin
		if (free_particles = nil) then
			Exit;
		p := free_particles;
		free_particles := p^.next;
		p^.next := active_particles;
		active_particles := p;
		VectorClear (p^.accel);

		p^.time := cl.time;

		p^.alpha := 1.0;
		p^.alphavel := -1.0 / (1 + frand() * 0.5);
		p^.color := 0 + (rand() mod 4);
		for j := 0 to 2 do
		begin
			p^.org[j] := origin[j] + crand() * 3;
		end;
		p^.vel[2] := 20 + crand() * 5;
	end;
end;


(*
===============
CL_GenericParticleEffect
===============
*)
procedure CL_GenericParticleEffect (org, dir: vec3_t; color, count, numcolors, dirspread: Integer; alphavel: Single);
var
	i, j: Integer;
	p: cparticle_p;
	d: Single;
begin
	for i := 0 to count - 1 do
	begin
		if (free_particles = nil) then
			Exit;
		p := free_particles;
		free_particles := p^.next;
		p^.next := active_particles;
		active_particles := p;

		p^.time := cl.time;
		if (numcolors > 1) then
			p^.color := color + (rand() and numcolors)
		else
			p^.color := color;

		d := rand() and dirspread;
		for j := 0 to 2 do
		begin
			p^.org[j] := org[j] + ((rand() and 7) - 4) + d * dir[j];
			p^.vel[j] := crand() * 20;
		end;

		p^.accel[0] := 0.0;
    p^.accel[1] := 0.0;
		p^.accel[2] := -PARTICLE_GRAVITY;
//		VectorCopy (accel, p^.accel);
		p^.alpha := 1.0;

		p^.alphavel := -1.0 / (0.5 + frand() * alphavel);
//		p^.alphavel := alphavel;
	end;
end;

(*
===============
CL_BubbleTrail2 (lets you control the # of bubbles by setting the distance between the spawns)

===============
*)
procedure CL_BubbleTrail2 (start, end_: vec3_t; dist: Integer);
var
	move, vec: vec3_t;
  len: Single;
	i: Single;
  j: Integer;
	p: cparticle_p;
	dec: Single;
begin
	VectorCopy (start, move);
	VectorSubtract (end_, start, vec);
	len := VectorNormalize (vec);

	dec := dist;
	VectorScale (vec, dec, vec);

  i := 0;
	while (i<len) do
	begin
		if (free_particles = nil) then
			Exit;

		p := free_particles;
		free_particles := p^.next;
		p^.next := active_particles;
		active_particles := p;

		VectorClear (p^.accel);
		p^.time := cl.time;

		p^.alpha := 1.0;
		p^.alphavel := -1.0 / (1+frand()*0.1);
		p^.color := 4 + (rand() and 7);
		for j := 0 to 2 do
		begin
			p^.org[j] := move[j] + crand()*2;
			p^.vel[j] := crand()*10;
		end;
		p^.org[2] := p^.org[2] - 4;
//		p^.vel[2] := p^.vel[2] + 6;
		p^.vel[2] := p^.vel[2] + 20;

		VectorAdd (move, vec, move);

    i := i + dec;
	end;
end;

{.$DEFINE CORKSCREW}
{.$DEFINE DOUBLE_SCREW}
{$DEFINE RINGS}
{.$DEFINE SPRAY}

{$IFDEF CORKSCREW}
procedure CL_Heatbeam (start, end_: vec3_t);
var
  move, vec: vec3_t;
  len: Single;
	j, k: Integer;
	p: cparticle_p;
	right, up: vec3_t;
	i: Integer;
	d, c, s: Single;
	dir: vec3_t;
	ltime: Single;
	step: Integer;
begin
  step := 5;
	VectorCopy (start, move);
	VectorSubtract (end_, start, vec);
	len := VectorNormalize (vec);

//	MakeNormalVectors (vec, right, up);
	VectorCopy (cl.v_right, right);
	VectorCopy (cl.v_up, up);
	VectorMA (move, -1, right, move);
	VectorMA (move, -1, up, move);

	VectorScale (vec, step, vec);
	ltime := cl.time/1000.0;

//	for i := 0 to len - 1 do
  i := 0;
  while (i < len) do
	begin
		d := i * 0.1 - fmod(ltime,16.0)*M_PI;
		c := cos(d)/1.75;
		s := sin(d)/1.75;
{$IFDEF DOUBLE_SCREW}
    k := -1;
    while (k < 2) do
		begin
{$ELSE}
		k := 1;
{$ENDIF}
			if (free_particles = nil) then
				Exit;

			p := free_particles;
			free_particles := p^.next;
			p^.next := active_particles;
			active_particles := p;

			p^.time := cl.time;
			VectorClear (p^.accel);

			p^.alpha := 0.5;
	//		p^.alphavel := -1.0 / (1+frand()*0.2);
			// only last one frame!
			p^.alphavel := INSTANT_PARTICLE;
	//		p^.color := $74 + (rand() and 7);
//			p^.color := 223 - (rand() and 7);
			p^.color := 223;
//			p^.color := 240;

			// trim it so it looks like it's starting at the origin
			if (i < 10) then
			begin
				VectorScale (right, c*(i/10.0)*k, dir);
				VectorMA (dir, s*(i/10.0)*k, up, dir);
			end
			else
			begin
				VectorScale (right, c*k, dir);
				VectorMA (dir, s*k, up, dir);
			end;

			for j := 0 to 2 do
			begin
				p^.org[j] := move[j] + dir[j]*3;
	//			p^.vel[j] := dir[j]*6;
				p^.vel[j] := 0;
			end;
{$IFDEF DOUBLE_SCREW}
      k := k + 2;
		end;
{$ENDIF}
		VectorAdd (move, vec, move);

    i := i + step;
	end;
end;
{$ENDIF}
{$IFDEF RINGS}
//procedure CL_Heatbeam (vec3_t start, vec3_t end)
procedure CL_Heatbeam (start, forward_: vec3_t);
var
  move: vec3_t;
  vec: vec3_t;
	len: Single;
	j: Integer;
	p: cparticle_p;
	right, up: vec3_t;
	i: Single;
	c, s: Single;
	dir: vec3_t;
	ltime: Single;
	step, rstep: Single;
	start_pt: Single;
	rot: Single;
	variance: Single;
	end_: vec3_t;
begin
  step := 32.0;
	VectorMA (start, 4096, forward_, end_);

	VectorCopy (start, move);
	VectorSubtract (end_, start, vec);
	len := VectorNormalize (vec);

	// FIXME - pmm - these might end up using old values?
//	MakeNormalVectors (vec, right, up);
	VectorCopy (cl.v_right, right);
	VectorCopy (cl.v_up, up);
	if (vidref_val = VIDREF_GL) then
	begin // GL mode
		VectorMA (move, -0.5, right, move);
		VectorMA (move, -0.5, up, move);
	end;
	// otherwise assume SOFT

	ltime := cl.time/1000.0;
	start_pt := fmod(ltime*96.0,step);
	VectorMA (move, start_pt, vec, move);

	VectorScale (vec, step, vec);

//	Com_Printf ("%f"#10, ltime);
	rstep := M_PI/10.0;
  i := start_pt;
	while (i < len) do
	begin
		if (i>step*5) then // don't bother after the 5th ring
			break;

    rot := 0.0;
		while (rot < M_PI*2) do
		begin

			if (free_particles = nil) then
				Exit;

			p := free_particles;
			free_particles := p^.next;
			p^.next := active_particles;
			active_particles := p;

			p^.time := cl.time;
			VectorClear (p^.accel);
//			rot := rot + fmod(ltime, 12.0)*M_PI;
//			c := cos(rot)/2.0;
//			s := sin(rot)/2.0;
//			variance := 0.4 + ((float)rand()/(float)RAND_MAX) *0.2;
			variance := 0.5;
			c := cos(rot)*variance;
			s := sin(rot)*variance;

			// trim it so it looks like it's starting at the origin
			if (i < 10) then
			begin
				VectorScale (right, c*(i/10.0), dir);
				VectorMA (dir, s*(i/10.0), up, dir);
			end
			else
			begin
				VectorScale (right, c, dir);
				VectorMA (dir, s, up, dir);
			end;

			p^.alpha := 0.5;
	//		p^.alphavel := -1.0 / (1+frand()*0.2);
			p^.alphavel := -1000.0;
	//		p^.color := 0x74 + (rand()&7);
			p^.color := 223 - (rand() and 7);
			for j := 0 to 2 do
			begin
				p^.org[j] := move[j] + dir[j]*3;
	//			p^.vel[j] := dir[j]*6;
				p^.vel[j] := 0;
			end;

      rot := rot + rstep;
		end;
		VectorAdd (move, vec, move);

    i := i + step;
	end;
end;
{$ENDIF}
{$IFDEF SPRAY}
procedure CL_Heatbeam (start, end_: vec3_t);
var
	move: vec3_t;
	vec: vec3_t;
	len: Single;
	j: Integer;
	p: cparticle_p;
	forward_, right, up: vec3_t;
	i: Integer;
	d, c, s: Single;
	dir: vec3_t;
	ltime: SIngle;
	step, rstep: Single;
	start_pt: Single;
	rot: Single;
begin
  step := 32.0;
	VectorCopy (start, move);
	VectorSubtract (end_, start, vec);
	len := VectorNormalize (vec);

//	MakeNormalVectors (vec, right, up);
	VectorCopy (cl.v_forward, forward_);

⌨️ 快捷键说明

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