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

📄 g_weapon.pas

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