📄 cl_fx.pas
字号:
{100%}
{----------------------------------------------------------------------------}
{ }
{ File(s): cl_fx.c }
{ Content: Quake2\Client - builds an intended movement command to send to the server }
{ }
{ Initial conversion by : Juha Hartikainen - juha@linearteam.org }
{ Initial conversion on : 03-Jun-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. }
{ }
{----------------------------------------------------------------------------}
{ Updates: }
{ }
{ 27-Jun-2002 Steve 'Sly' Williams }
{ - Fix hints and warnings }
{ }
{----------------------------------------------------------------------------}
// cl_fx.c -- entity effects parsing and management
unit cl_fx;
interface
uses
CPas,
Common,
Client,
ref,
q_shared,
m_flash;
procedure CL_LogoutEffect(org: vec3_t; type_: Integer);
procedure CL_ItemRespawnParticles(org: vec3_t);
procedure CL_ParticleEffect(org, dir: vec3_t; color, count: Integer);
procedure CL_EntityEvent(ent: entity_state_p);
procedure CL_TeleporterParticles(ent: entity_state_p);
procedure CL_RocketTrail(start, end_: vec3_t; old: centity_p);
procedure CL_BlasterTrail(start, end_: vec3_t);
procedure CL_DiminishingTrail(start, end_: vec3_t; old: centity_p; flags: integer);
procedure CL_FlyEffect(ent: centity_p; origin: vec3_t);
procedure CL_BfgParticles(ent: entity_p);
procedure CL_TrapParticles(ent: entity_p);
procedure CL_FlagTrail(start, end_: vec3_t; color: single);
procedure CL_IonripperTrail(start, ent: vec3_t);
procedure CL_AddParticles;
procedure CL_AddDLights;
procedure CL_AddLightStyles;
procedure CL_ClearEffects;
procedure CL_RunDLights;
procedure CL_RunLightStyles;
procedure CL_ParticleEffect2 (org, dir: vec3_t; color, count: integer);
procedure CL_RailTrail (start, end_: vec3_t);
procedure CL_BubbleTrail (start, end_: vec3_t);
procedure CL_BigTeleportParticles (org: vec3_t);
procedure CL_ParticleEffect3 (org, dir: vec3_t; color, count: integer);
procedure CL_TeleportParticles (org: vec3_t);
procedure CL_BlasterParticles (org, dir: vec3_t);
procedure CL_ExplosionParticles (org: vec3_t);
procedure CL_BFGExplosionParticles (org: vec3_t);
function CL_AllocDlight (key: Integer): cdlight_p;
procedure CL_SetLightstyle(i: integer);
procedure MakeNormalVectors (forward_, right, up: vec3_t);
procedure CL_ParseMuzzleFlash;
procedure CL_ParseMuzzleFlash2;
var
avelocities: array [0..NUMVERTEXNORMALS-1] of vec3_t;
active_particles,
free_particles: cparticle_p;
particles: array[0..MAX_PARTICLES-1] of cparticle_t;
cl_numparticles: integer = MAX_PARTICLES;
(*
==============================================================
LIGHT STYLE MANAGEMENT
==============================================================
*)
type
clightstyle_p = ^clightstyle_t;
clightstyle_t = record
length: integer;
value: array[0..2] of single;
map: array[0..MAX_QPATH - 1] of single;
end;
pclightstyle_t = ^clightstyle_t;
var
cl_lightstyle: array[0..MAX_LIGHTSTYLES - 1] of clightstyle_t;
lastofs: integer;
implementation
uses
cl_main,
cl_view,
net_chan,
cl_tent,
snd_dma,
g_local;
(*
================
CL_ClearLightStyles
================
*)
procedure CL_ClearLightStyles;
begin
FillChar(cl_lightstyle, sizeof(cl_lightstyle), 0);
lastofs := -1;
end;
(*
================
CL_RunLightStyles
================
*)
procedure CL_RunLightStyles;
var
ofs: integer;
i: integer;
ls: clightstyle_p;
label
cont;
begin
ofs := round(cl.time / 100);
if (ofs = lastofs) then
exit;
lastofs := ofs;
ls := @cl_lightstyle;
i := 0;
while (i < MAX_LIGHTSTYLES) do
begin
if (ls.length = 0) then
begin
ls.value[0] := 1.0;
ls.value[1] := 1.0;
ls.value[2] := 1.0;
goto cont;
end;
if (ls.length = 1) then
begin
ls.value[0] := ls.map[0];
ls.value[1] := ls.map[0];
ls.value[2] := ls.map[0];
end
else
begin
ls.value[0] := ls.map[ofs mod ls.length];
ls.value[1] := ls.map[ofs mod ls.length];
ls.value[2] := ls.map[ofs mod ls.length];
end;
cont:
Inc(i);
Inc(ls);
end;
end;
procedure CL_SetLightstyle(i: integer);
var
s: pchar;
j, k: integer;
begin
s := cl.configstrings[i + CS_LIGHTS];
j := strlen(s);
if (j >= MAX_QPATH) then
Com_Error(ERR_DROP, 'svc_lightstyle length=%d', [j]);
cl_lightstyle[i].length := j;
for k := 0 to j - 1 do
cl_lightstyle[i].map[k] := (byte(s[k]) - byte('a')) / (byte('m') - byte('a'));
end;
(*
================
CL_AddLightStyles
================
*)
procedure CL_AddLightStyles;
var
i: Integer;
ls: clightstyle_p;
begin
ls := @cl_lightstyle;
for i := 0 to MAX_LIGHTSTYLES - 1 do
begin
V_AddLightStyle(i, ls.value[0], ls.value[1], ls.value[2]);
Inc(ls);
end;
end;
(*
==============================================================
DLIGHT MANAGEMENT
==============================================================
*)
var
cl_dlights: array[0..MAX_DLIGHTS - 1] of cdlight_t;
(*
================
CL_ClearDlights
================
*)
procedure CL_ClearDlights;
begin
FillChar(cl_dlights, sizeof(cl_dlights), 0);
end;
(*
===============
CL_AllocDlight
===============
*)
function CL_AllocDlight(key: Integer): cdlight_p;
var
i: Integer;
dl: cdlight_p;
begin
// first look for an exact key match
if (key <> 0) then
begin
dl := @cl_dlights;
for i := 0 to MAX_DLIGHTS - 1 do
begin
if (dl.key = key) then
begin
FillChar(dl^, sizeof(cdlight_t), 0);
dl.key := key;
Result := dl;
exit;
end;
Inc(dl);
end;
end;
// then look for anything else
dl := @cl_dlights;
for i := 0 to MAX_DLIGHTS - 1 do
begin
if (dl.die < cl.time) then
begin
FillChar(dl^, sizeof(cdlight_t), 0);
dl.key := key;
Result := dl;
exit;
end;
Inc(dl);
end;
dl := @cl_dlights[0];
FillChar(dl^, sizeof(cdlight_t), 0);
dl.key := key;
Result := dl;
end;
(*
===============
CL_NewDlight
===============
*)
procedure CL_NewDlight(key: Integer; x, y, z, radius: Single; time: Single);
var
dl: cdlight_p;
begin
dl := CL_AllocDlight(key);
dl.origin[0] := x;
dl.origin[1] := y;
dl.origin[2] := z;
dl.radius := radius;
dl.die := cl.time + time;
end;
(*
===============
CL_RunDLights
===============
*)
procedure CL_RunDLights;
var
i: Integer;
dl: cdlight_p;
label
continue_;
begin
dl := @cl_dlights;
for i := 0 to MAX_DLIGHTS - 1 do
begin
if (dl.radius = 0) then
goto continue_;
if (dl.die < cl.time) then
begin
dl.radius := 0;
exit;
end;
dl.radius := dl.radius - cls.frametime * dl.decay;
if (dl.radius < 0) then
dl.radius := 0;
continue_:
Inc(dl);
end;
end;
(*
==============
CL_ParseMuzzleFlash
==============
*)
procedure CL_ParseMuzzleFlash;
var
fv, rv: vec3_t;
dl: cdlight_p;
i, weapon: Integer;
pl: centity_p;
silenced: Integer;
volume: single;
soundname: array[0..64 - 1] of char;
begin
i := MSG_ReadShort(net_message);
if (i < 1) or (i >= MAX_EDICTS) then
Com_Error(ERR_DROP, 'CL_ParseMuzzleFlash: bad entity', []);
weapon := MSG_ReadByte(net_message);
silenced := weapon and MZ_SILENCED;
weapon := weapon and not MZ_SILENCED;
pl := @cl_entities[i];
dl := CL_AllocDlight(i);
VectorCopy(pl.current.origin, dl.origin);
AngleVectors(pl.current.angles, @fv, @rv, nil);
VectorMA(dl.origin, 18, fv, dl.origin);
VectorMA(dl.origin, 16, rv, dl.origin);
if (silenced <> 0) then
dl.radius := 100 + (rand() and 31)
else
dl.radius := 200 + (rand() and 31);
dl.minlight := 32;
dl.die := cl.time; // + 0.1;
if (silenced <> 0) then
volume := 0.2
else
volume := 1;
case weapon of
MZ_BLASTER:
begin
dl.color[0] := 1;
dl.color[1] := 1;
dl.color[2] := 0;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/blastf1a.wav'), volume, ATTN_NORM, 0);
end;
MZ_BLUEHYPERBLASTER:
begin
dl.color[0] := 0;
dl.color[1] := 0;
dl.color[2] := 1;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/hyprbf1a.wav'), volume, ATTN_NORM, 0);
end;
MZ_HYPERBLASTER:
begin
dl.color[0] := 1;
dl.color[1] := 1;
dl.color[2] := 0;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/hyprbf1a.wav'), volume, ATTN_NORM, 0);
end;
MZ_MACHINEGUN:
begin
dl.color[0] := 1;
dl.color[1] := 1;
dl.color[2] := 0;
Com_sprintf(soundname, sizeof(soundname), 'weapons/machgf%db.wav', [(rand() mod 5) + 1]);
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
end;
MZ_SHOTGUN:
begin
dl.color[0] := 1;
dl.color[1] := 1;
dl.color[2] := 0;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/shotgf1b.wav'), volume, ATTN_NORM, 0);
S_StartSound(nil, i, CHAN_AUTO, S_RegisterSound('weapons/shotgr1b.wav'), volume, ATTN_NORM, 0.1);
end;
MZ_SSHOTGUN:
begin
dl.color[0] := 1;
dl.color[1] := 1;
dl.color[2] := 0;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/sshotf1b.wav'), volume, ATTN_NORM, 0);
end;
MZ_CHAINGUN1:
begin
dl.radius := 200 + (rand() and 31);
dl.color[0] := 1;
dl.color[1] := 0.25;
dl.color[2] := 0;
Com_sprintf(soundname, sizeof(soundname), 'weapons/machgf%db.wav', [(rand() mod 5) + 1]);
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
end;
MZ_CHAINGUN2:
begin
dl.radius := 225 + (rand() and 31);
dl.color[0] := 1;
dl.color[1] := 0.5;
dl.color[2] := 0;
dl.die := cl.time + 0.1; // long delay
Com_sprintf(soundname, sizeof(soundname), 'weapons/machgf%db.wav', [(rand() mod 5) + 1]);
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
Com_sprintf(soundname, sizeof(soundname), 'weapons/machgf%db.wav', [(rand() mod 5) + 1]);
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.05);
end;
MZ_CHAINGUN3:
begin
dl.radius := 250 + (rand() and 31);
dl.color[0] := 1;
dl.color[1] := 1;
dl.color[2] := 0;
dl.die := cl.time + 0.1; // long delay
Com_sprintf(soundname, sizeof(soundname), 'weapons/machgf%db.wav', [(rand() mod 5) + 1]);
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
Com_sprintf(soundname, sizeof(soundname), 'weapons/machgf%db.wav', [(rand() mod 5) + 1]);
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.033);
Com_sprintf(soundname, sizeof(soundname), 'weapons/machgf%db.wav', [(rand() mod 5) + 1]);
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.066);
end;
MZ_RAILGUN:
begin
dl.color[0] := 0.5;
dl.color[1] := 0.5;
dl.color[2] := 1.0;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/railgf1a.wav'), volume, ATTN_NORM, 0);
end;
MZ_ROCKET:
begin
dl.color[0] := 1;
dl.color[1] := 0.5;
dl.color[2] := 0.2;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/rocklf1a.wav'), volume, ATTN_NORM, 0);
S_StartSound(nil, i, CHAN_AUTO, S_RegisterSound('weapons/rocklr1b.wav'), volume, ATTN_NORM, 0.1);
end;
MZ_GRENADE:
begin
dl.color[0] := 1;
dl.color[1] := 0.5;
dl.color[2] := 0;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/grenlf1a.wav'), volume, ATTN_NORM, 0);
S_StartSound(nil, i, CHAN_AUTO, S_RegisterSound('weapons/grenlr1b.wav'), volume, ATTN_NORM, 0.1);
end;
MZ_BFG:
begin
dl.color[0] := 0;
dl.color[1] := 1;
dl.color[2] := 0;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/bfg__f1y.wav'), volume, ATTN_NORM, 0);
end;
MZ_LOGIN:
begin
dl.color[0] := 0;
dl.color[1] := 1;
dl.color[2] := 0;
dl.die := cl.time + 1.0;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/grenlf1a.wav'), 1, ATTN_NORM, 0);
CL_LogoutEffect(pl.current.origin, weapon);
end;
MZ_LOGOUT:
begin
dl.color[0] := 1;
dl.color[1] := 0;
dl.color[2] := 0;
dl.die := cl.time + 1.0;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/grenlf1a.wav'), 1, ATTN_NORM, 0);
CL_LogoutEffect(pl.current.origin, weapon);
end;
MZ_RESPAWN:
begin
dl.color[0] := 1;
dl.color[1] := 1;
dl.color[2] := 0;
dl.die := cl.time + 1.0;
S_StartSound(nil, i, CHAN_WEAPON, S_RegisterSound('weapons/grenlf1a.wav'), 1, ATTN_NORM, 0);
CL_LogoutEffect(pl.current.origin, weapon);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -