📄 g_weapon.pas
字号:
//This is "COMMON" file for \GAME\g_weapon.pas & \CTF\g_weapon.pas
{$DEFINE CTF}
{$IFDEF CTF}
{$ELSE}
{$ENDIF}
// PLEASE, don't modify this file
// 70% complete
{----------------------------------------------------------------------------}
{ }
{ File(s): g_weapon.c }
{ }
{ Initial conversion by : YgriK (Igor Karpov) - glYgriK@hotbox.ru }
{ Initial conversion on : 24-Jan-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 on : }
{ Updated by : }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ 1) ???../g_local.inc }
{ }
{----------------------------------------------------------------------------}
{ * TODO: }
{ 1) Do more tests }
{ }
{----------------------------------------------------------------------------}
#include "g_local.h"
{*
=================
check_dodge
This is a support routine used when a client is firing
a non-instant attack weapon. It checks to see if a
monster's dodge function should be called.
=================
*}
// (GAME=CTF)
procedure static void check_dodge (edict_t *self, vec3_t start, vec3_t dir, int speed);
var
end_,
v : vec3_t;
tr : trace_t;
eta : float;
begin
// easy mode only ducks one quarter the time
if (skill.value = 0) then
if (random() > 0.25) then
Exit;
VectorMA (start, 8192, dir, end_);
tr := gi.trace (start, NULL, NULL, end_, self, MASK_SHOT);
if ( (tr.ent) AND ((tr.ent.svflags AND SVF_MONSTER) <> 0) AND
(tr.ent.health > 0) AND (tr.ent.monsterinfo.dodge) AND infront(tr.ent, self) ) then
begin
VectorSubtract (tr.endpos, start, v);
eta := (VectorLength(v) - tr.ent.maxs[0]) / speed;
tr.ent.monsterinfo.dodge (tr.ent, self, eta);
end;
end;//procedure (GAME=CTF)
{*
=================
fire_hit
Used for all impact (hit/punch/slash) attacks
=================
*}
// (GAME=CTF)
function fire_hit (edict_t *self, vec3_t aim, int damage, int kick) : qboolean;
var
tr : trace_t;
forward_, right, up;
v;
point,
dir : vec3_t;
range : float;
begin
//see if enemy is in range
VectorSubtract (self.enemy.s.origin, self.s.origin, dir);
range := VectorLength(dir);
if (range > aim[0]) then
begin
Result := false;
Exit;
end;
if (aim[1] > self.mins[0]) AND (aim[1] < self.maxs[0])
then begin
// the hit is straight on so back the range up to the edge of their bbox
range := range -self.enemy.maxs[0];
end
else begin
// this is a side hit so adjust the "right" value out to the edge of their bbox
if (aim[1] < 0)
then aim[1] := self.enemy.mins[0]
else aim[1] := self.enemy.maxs[0];
end;
VectorMA (self.s.origin, range, dir, point);
tr := gi.trace (self.s.origin, NULL, NULL, point, self, MASK_SHOT);
if (tr.fraction < 1) then
begin
if (!tr.ent.takedamage) then
begin
Result := false;
Exit;
end;
// if it will hit any client/monster then hit the one we wanted to hit
// if ((tr.ent.svflags & SVF_MONSTER) or (tr.ent.client)) then
if ( ((tr.ent.svflags AND SVF_MONSTER) <> 0) OR tr.ent.client ) then
tr.ent := self.enemy;
end;
AngleVectors(self.s.angles, forward_, right, up);
VectorMA (self.s.origin, range, forward_, point);
VectorMA (point, aim[1], right, point);
VectorMA (point, aim[2], up, point);
VectorSubtract (point, self.enemy.s.origin, dir);
// do the damage
T_Damage (tr.ent, self, self, dir, point, vec3_origin, damage, kick/2, DAMAGE_NO_KNOCKBACK, MOD_HIT);
// if (!(tr.ent.svflags & SVF_MONSTER) and (!tr.ent.client)) then
if ( ((tr.ent.svflags AND SVF_MONSTER) = 0) AND (!tr.ent.client) ) then
begin
Result := false;
Exit;
end;
// do our special form of knockback here
VectorMA (self.enemy.absmin, 0.5, self.enemy.size, v);
VectorSubtract (v, point, v);
VectorNormalize (v);
VectorMA (self.enemy.velocity, kick, v, self.enemy.velocity);
if (self.enemy.velocity[2] > 0) then
self.enemy.groundentity := NULL;
Result := true;
end;//function (GAME=CTF)
{*
=================
fire_lead
This is an internal support routine used for bullet/pellet based weapons.
=================
*}
// (GAME=CTF)
procedure static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread, int mod);
var
tr : trace_t;
dir,
forward_, right, up;
end_,
water_start : vec3_t;
r, u : float;
int color;
begin
qboolean water = false;
int content_mask = MASK_SHOT | MASK_WATER;
tr := gi.trace (self.s.origin, NULL, NULL, start, self, MASK_SHOT);
if (!(tr.fraction < 1.0)) then
begin
vectoangles (aimdir, dir);
AngleVectors (dir, forward_, right, up);
r := crandom()*hspread;
u := crandom()*vspread;
VectorMA (start, 8192, forward_, end_);
VectorMA (end_, r, right, end_);
VectorMA (end_, u, up, end_);
// if (gi.pointcontents (start) & MASK_WATER) then
if (gi.pointcontents (start) AND MASK_WATER) <> 0 then
begin
water := true;
VectorCopy (start, water_start);
// content_mask &= ~MASK_WATER;
content_mask := content_mask AND (NOT MASK_WATER);
end;
tr := gi.trace (start, NULL, NULL, end, self, content_mask);
// see if we hit water
// if (tr.contents & MASK_WATER) then
if (tr.contents AND MASK_WATER) <> 0 then
begin
water := true;
VectorCopy (tr.endpos, water_start);
if (!VectorCompare (start, tr.endpos)) then
begin
// if (tr.contents & CONTENTS_WATER)
if (tr.contents AND CONTENTS_WATER) <> 0
then begin
if (strcmp(tr.surface.name, '*brwater') = 0)
then color := SPLASH_BROWN_WATER
else color := SPLASH_BLUE_WATER;
end
else
if (tr.contents AND CONTENTS_SLIME) <> 0
then color := SPLASH_SLIME
else
if (tr.contents AND CONTENTS_LAVA) <> 0
then color := SPLASH_LAVA
else color := SPLASH_UNKNOWN;
if (color <> SPLASH_UNKNOWN) then
begin
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_SPLASH);
gi.WriteByte (8);
gi.WritePosition (tr.endpos);
gi.WriteDir (tr.plane.normal);
gi.WriteByte (color);
gi.multicast (tr.endpos, MULTICAST_PVS);
end;
// change bullet's course when it enters water
VectorSubtract (end_, start, dir);
vectoangles (dir, dir);
AngleVectors (dir, forward_, right, up);
r := crandom()*hspread*2;
u := crandom()*vspread*2;
VectorMA (water_start, 8192, forward_, end_);
VectorMA (end_, r, right, end_);
VectorMA (end_, u, up, end_);
end;//if
// re-trace ignoring water this time
tr := gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT);
end;//if
end;//if
// send gun puff / flash
// if (!((tr.surface) and (tr.surface.flags & SURF_SKY))) then
if NOT ( tr.surface AND ((tr.surface.flags AND SURF_SKY) <> 0)) ) then
begin
if (tr.fraction < 1.0) then
if (tr.ent.takedamage)
then T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, mod)
else
if (strncmp (tr.surface.name, 'sky', 3) <> 0) then
begin
gi.WriteByte (svc_temp_entity);
gi.WriteByte (te_impact);
gi.WritePosition (tr.endpos);
gi.WriteDir (tr.plane.normal);
gi.multicast (tr.endpos, MULTICAST_PVS);
if (self.client) then
PlayerNoise(self, tr.endpos, PNOISE_IMPACT);
end;
end;//if
// if went through water, determine where the end and make a bubble trail
if (water) then
begin
vec3_t pos;
VectorSubtract (tr.endpos, water_start, dir);
VectorNormalize (dir);
VectorMA (tr.endpos, -2, dir, pos);
// if (gi.pointcontents (pos) & MASK_WATER)
if ((gi.pointcontents (pos) AND MASK_WATER) <> 0)
then VectorCopy (pos, tr.endpos)
else tr := gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER);
VectorAdd (water_start, tr.endpos, pos);
VectorScale (pos, 0.5, pos);
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_BUBBLETRAIL);
gi.WritePosition (water_start);
gi.WritePosition (tr.endpos);
gi.multicast (pos, MULTICAST_PVS);
end;
end;//procedure (GAME=CTF)
{*
=================
fire_bullet
Fires a single round. Used for machinegun and chaingun. Would be fine for
pistols, rifles, etc....
=================
*}
// (GAME=CTF)
procedure fire_bullet (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod);
begin
fire_lead (self, start, aimdir, damage, kick, TE_GUNSHOT, hspread, vspread, mod);
end;//procedure (GAME=CTF)
{*
=================
fire_shotgun
Shoots shotgun pellets. Used by shotgun and super shotgun.
=================
*}
// (GAME=CTF)
procedure fire_shotgun (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int mod);
var
i : integer;
begin
for i:=0 to count-1 do
fire_lead (self, start, aimdir, damage, kick, TE_SHOTGUN, hspread, vspread, mod);
end;//procedure (GAME=CTF)
{*
=================
fire_blaster
Fires a single blaster bolt. Used by the blaster and hyper blaster.
=================
*}
// (GAME=CTF)
procedure blaster_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf);
var
mod : integer;
begin
if (other = self.owner) then
Exit;
// if (surf && (surf.flags & SURF_SKY)) then
if (surf AND ((surf.flags AND SURF_SKY) <> 0)) then
begin
G_FreeEdict (self);
Exit;
end;
if (self.owner.client) then
PlayerNoise(self.owner, self.s.origin, PNOISE_IMPACT);
if (other.takedamage)
then begin
// if (self.spawnflags & 1)
if ((self.spawnflags AND 1) <> 0)
then mod := MOD_HYPERBLASTER
else mod := MOD_BLASTER;
T_Damage (other, self, self.owner, self.velocity, self.s.origin, plane.normal, self.dmg, 1, DAMAGE_ENERGY, mod);
end
else begin
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_BLASTER);
gi.WritePosition (self.s.origin);
if (!plane)
then gi.WriteDir (vec3_origin)
else gi.WriteDir (plane.normal);
gi.multicast (self.s.origin, MULTICAST_PVS);
end;
G_FreeEdict (self);
end;//procedure (GAME=CTF)
// (GAME <> CTF)
procedure fire_blaster (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int effect, qboolean hyper);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -