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

📄 g_weapon.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 3 页
字号:
{----------------------------------------------------------------------------}
{                                                                            }
{ 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 : 20 Sept 2002                                                  }
{ Updated by : Fabrizio Rossini (FAB)                                        }
{ Completed translation                                                      }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on:                               }
{                                                                            }
{                                                                            }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{ 1) Do more tests and check for error                                       }
{                                                                            }
{----------------------------------------------------------------------------}

unit g_weapon;

interface

//...
uses
  q_shared,
  g_local,
  g_local_add;

procedure fire_grenade (self : edict_p; const start, aimdir : vec3_t; damage, speed : integer; timer, damage_radius : Single);
procedure fire_grenade2 (self : edict_p; const start, aimdir : vec3_t; damage, speed : integer; timer, damage_radius : Single; held : qboolean);
procedure fire_rocket (self : edict_p; const start, dir : vec3_t; damage, speed : integer; damage_radius : Single; radius_damage: Integer);
procedure fire_blaster (self : edict_p; var start, dir : vec3_t; damage, speed, effect : integer; hyper : qboolean);
procedure fire_bullet (self : edict_p; var start, aimdir : vec3_t; damage, kick, hspread, vspread, mod_ : integer);
procedure fire_shotgun (self : edict_p; var start, aimdir : vec3_t; damage, kick, hspread, vspread, count, mod_ : integer);
procedure fire_rail (self : edict_p; var start, aimdir : vec3_t; damage, kick : integer);
procedure fire_bfg (self : edict_p; const start, dir : vec3_t; damage, speed : integer; damage_radius : Single);
function fire_hit (self : edict_p; var aim : vec3_t; damage, kick : integer) : qboolean;



implementation

uses
  g_main,
  GameUnit,
  g_ai,
  g_combat,
  g_utils,
  p_weapon,
  g_misc,
  q_shared_add,
  game_add,
  CPas;


{*
=================
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.
=================
*}
procedure check_dodge (self : edict_p; const start, dir : vec3_t; speed : integer);
var
  end_,
  v    : vec3_t;
  tr   : trace_t;
  eta  : Single;

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, Nil, Nil, @end_, self, MASK_SHOT);
  if ( (tr.ent <> Nil) AND ((edict_p(tr.ent)^.svflags AND SVF_MONSTER) <> 0) AND
       (edict_p(tr.ent)^.health > 0) AND (@edict_p(tr.ent)^.monsterinfo.dodge <> Nil) AND (not infront(tr.ent, self)) ) then
  begin
    VectorSubtract (tr.endpos, start, v);
    eta := (VectorLength(v) - edict_p(tr.ent)^.maxs[0]) / speed;
    edict_p(tr.ent)^.monsterinfo.dodge (tr.ent, self, eta);
  end;
end;


{*
=================
fire_hit

Used for all impact (hit/punch/slash) attacks
=================
*}
//function fire_hit (edict_t *self, vec3_t aim, int damage, int kick) : qboolean;
function fire_hit (self : edict_p; var aim : vec3_t; damage, kick : integer) : qboolean;
var
  tr        : trace_t;
  forward_,
  right, up,
  v,
  point,
  dir       : vec3_t;
  range     : Single;
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, Nil, Nil, @point, self, MASK_SHOT);
  if (tr.fraction < 1) then
  begin
    if (edict_p(tr.ent)^.takedamage = DAMAGE_NO ) then
    begin
      Result := false;
      Exit;
    end;
    // if it will hit any client/monster then hit the one we wanted to hit
    if ( ((edict_p(tr.ent)^.svflags AND SVF_MONSTER) <> 0) OR (edict_p(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
  T_Damage (tr.ent, @self, @self, dir, point, vec3_origin, damage, kick div 2, DAMAGE_NO_KNOCKBACK, MOD_HIT);

  { if (!(tr.ent.svflags & SVF_MONSTER) and (!tr.ent.client)) then }
  if ( ((edict_p(tr.ent).svflags AND SVF_MONSTER) = 0) AND (edict_p(tr.ent).client = nil) ) 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;

{*
=================
fire_lead

This is an internal support routine used for bullet/pellet based weapons.
=================
*}
procedure fire_lead (self : edict_p; var 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         : Single;
  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;

  tr := gi.trace (@self.s.origin, Nil, Nil, @start, self, MASK_SHOT);
  if ((tr.fraction < 1.0) = False) 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 := content_mask AND (NOT MASK_WATER);
      end;

      tr := gi.trace (@start, Nil, Nil, @end_, self, content_mask);

      // see if we hit water
      if (tr.contents AND MASK_WATER) <> 0 then
      begin
        water := true;
        VectorCopy (tr.endpos, water_start);

        if (VectorCompare (start, tr.endpos) = 0) then
        begin
          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 (integer(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;

        // re-trace ignoring water this time
        tr := gi.trace(@water_start, Nil, Nil, @end_, self, MASK_SHOT);
      end;
  end;

  // send gun puff / flash
  if NOT ( (tr.surface <> Nil) AND ((tr.surface^.flags AND SURF_SKY) <> 0) ) then
  begin
    if (tr.fraction < 1.0) then
      if (edict_p(tr.ent)^.takedamage <> DAMAGE_NO) 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 <> nil) then
            PlayerNoise (self, tr.endpos, PNOISE_IMPACT);
        end;
  end;

  // 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) AND MASK_WATER) <> 0) then
      VectorCopy(pos, tr.endpos)
    else
      tr := gi.trace(@pos, Nil, Nil, @water_start, tr.ent, MASK_WATER);

    VectorAdd (water_start, tr.endpos, pos);
    VectorScale (pos, 0.5, pos);

    gi.WriteByte (svc_temp_entity);
    gi.WriteByte (integer(TE_BUBBLETRAIL));  
    gi.WritePosition (water_start);
    gi.WritePosition (tr.endpos);
    gi.multicast (@pos, MULTICAST_PVS);
  end;
end;


{*
=================
fire_bullet

⌨️ 快捷键说明

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