📄 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
// 80% 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 }
{ }
{----------------------------------------------------------------------------}
unit g_weapon;
interface
//...
implementation
uses g_local, q_shared, game;
{*
=================
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);
procedure check_dodge (self : edict_p; start, dir : vec3_t; speed : integer);
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_);
(*Y tr := gi.trace (start, Nil, NULL, end_, self, MASK_SHOT);
if ( (tr.ent <> Nil) AND ((tr.ent.svflags AND SVF_MONSTER) <> 0) AND
(tr.ent.health > 0) AND Assigned(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;
function fire_hit (self : edict_t; aim : vec3_t; damage, kick : integer) : 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);
//Y tr := gi.trace (self.s.origin, NULL, NULL, point, self, MASK_SHOT);
if (tr.fraction < 1) then
begin
//Y 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 <> Nil) ) 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
//Y 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
//Y 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 := Nil;
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);
procedure fire_lead (self : edict_p; start, aimdir : vec3_t; damage, kick, te_impact, hspread, vspread, mod_ : integer);
var
tr : trace_t;
dir,
forward_,
right, up,
end_,
water_start,
pos : vec3_t;
r, u : float;
water : qboolean;
color,
content_mask : integer;
begin
{ qboolean water = false;
int content_mask = MASK_SHOT | MASK_WATER;}
water := false;
content_mask := MASK_SHOT OR MASK_WATER;
(*Y tr := gi.trace (self.s.origin, NULL, NULL, start, self, MASK_SHOT);
if (!(tr.fraction < 1.0)) then*)
begin
//Y 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
//Y 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;
//Y 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);
//Y if (!VectorCompare (start, tr.endpos)) then
begin
// if (tr.contents & CONTENTS_WATER)
if (tr.contents AND CONTENTS_WATER) <> 0
then begin
(*Y 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);
//Y 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
//Y 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<>Nil) AND ((tr.surface.flags AND SURF_SKY) <> 0) ) then
begin
if (tr.fraction < 1.0) then
(*Y 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
VectorSubtract (tr.endpos, water_start, dir);
VectorNormalize (dir);
VectorMA (tr.endpos, -2, dir, pos);
// if (gi.pointcontents (pos) & MASK_WATER)
(*Y 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);
(*Y 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);
procedure fire_bullet (self : edict_p; start, aimdir : vec3_t; damage, kick, hspread, vspread, mod_ : integer);
begin
//Y 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -