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

📄 p_weapon.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 4 页
字号:
//This is "COMMON" file for \GAME\p_weapon.pas & \CTF\p_weapon.pas
{$DEFINE CTF}
{$IFDEF CTF}
{$ELSE}
{$ENDIF}

// PLEASE, don't modify this file
// 70% complete

{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): p_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                                                       }
{ 2) ???../m_player.inc                                                      }
{                                                                            }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{ 1) Do more tests                                                           }
{                                                                            }
{----------------------------------------------------------------------------}

// g_weapon.c

#include "g_local.h"
#include "m_player.h"


static qboolean	is_quad;
static byte		is_silenced;


void weapon_grenade_fire (edict_t *ent, qboolean held);

{ (GAME <> CTF): 
  GAME: static void P_ProjectSource
  CTF:  void P_ProjectSource }
procedure static void P_ProjectSource (gclient_t *client,
                                       vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result);
var
  _distance : vec3_t;
begin
  VectorCopy (distance, _distance);
  if (client.pers.hand = LEFT_HANDED)
//  then _distance[1] *= -1;
  then _distance[1] := - _distance[1]
  else
    if (client.pers.hand = CENTER_HANDED) then
      _distance[1] := 0;
  G_ProjectSource (point, _distance, forward, right, result);
end;//procedure (GAME <> CTF) ???


{*
===============
PlayerNoise

Each player can have two noise objects associated with it:
a personal noise (jumping, pain, weapon firing), and a weapon
target noise (bullet wall impacts)

Monsters that don't directly see the player can move
to a noise in hopes of seeing the player from there.
===============
*}
// (GAME=CTF)
procedure PlayerNoise(edict_t *who, vec3_t where, int type);
var
	edict_t		*noise;
begin
  if (type = PNOISE_WEAPON) then
    if (who.client.silencer_shots) then
      begin
        who.client.silencer_shots--;
        Exit;
      end;

  if (deathmatch.value) then
    Exit;

//  if (who.flags & FL_NOTARGET) then
  if (who.flags AND FL_NOTARGET) <> 0 then
    Exit;

  if (!who.mynoise) then
  begin
    noise := G_Spawn();
    noise.classname := 'player_noise';
    VectorSet (noise.mins, -8, -8, -8);
    VectorSet (noise.maxs, 8, 8, 8);
    noise.owner := who;
    noise.svflags := SVF_NOCLIENT;
    who.mynoise := noise;

    noise := G_Spawn();
    noise.classname := 'player_noise';
    VectorSet (noise.mins, -8, -8, -8);
    VectorSet (noise.maxs, 8, 8, 8);
    noise.owner := who;
    noise.svflags := SVF_NOCLIENT;
    who.mynoise2 := noise;
  end;

  if (type = PNOISE_SELF) OR (type = PNOISE_WEAPON)
  then begin
    noise := who.mynoise;
    level.sound_entity := noise;
    level.sound_entity_framenum := level.framenum;
  end
  else begin// type == PNOISE_IMPACT
    noise := who.mynoise2;
    level.sound2_entity := noise;
    level.sound2_entity_framenum := level.framenum;
  end;

  VectorCopy (where, noise.s.origin);
  VectorSubtract (where, noise.maxs, noise.absmin);
  VectorAdd (where, noise.maxs, noise.absmax);
  noise.teleport_time := level.time;
  gi.linkentity (noise);
end;//procedure (GAME=CTF)

// (GAME=CTF)
function Pickup_Weapon (edict_t *ent, edict_t *other) : qboolean;
var
  index : integer;
	gitem_t		*ammo;
begin
  index := ITEM_INDEX(ent.item);

(*  if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value)
          && other->client->pers.inventory[index])
    if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) )
       return false;   // leave the weapon for others to pickup*)
{Y: NB! need test}
  if ( ( ((Trunc(dmflags.value) AND DF_WEAPONS_STAY) <> 0) OR coop.value ) AND
       other.client.pers.inventory[index] ) then
    if (ent.spawnflags AND (DROPPED_ITEM OR DROPPED_PLAYER_ITEM) = 0) then
    begin
      Result := false;   // leave the weapon for others to pickup
      Exit;
    end;

  other.client.pers.inventory[index]++;

//  if (!(ent.spawnflags & DROPPED_ITEM) ) then
  if ((ent.spawnflags AND DROPPED_ITEM) = 0) then
  begin
    // give them some ammo with it
    ammo := FindItem (ent.item.ammo);
//    if ( (int)dmflags.value & DF_INFINITE_AMMO )
{Y: NB! need test}
    if ((Trunc(dmflags.value) AND DF_INFINITE_AMMO) <> 0)
    then Add_Ammo (other, ammo, 1000)
    else Add_Ammo (other, ammo, ammo.quantity);

//    if (! (ent.spawnflags & DROPPED_PLAYER_ITEM) ) then
    if ((ent.spawnflags AND DROPPED_PLAYER_ITEM) =0) then
    begin
      if (deathmatch.value) then
//        if ((int)(dmflags.value) & DF_WEAPONS_STAY)
{Y: NB! need test}
        if ((Trunc(dmflags.value) AND DF_WEAPONS_STAY) < 0)
        then ent.flags := ent.flags OR FL_RESPAWN
        else SetRespawn (ent, 30);

      if (coop.value) then
        ent.flags := ent.flags OR FL_RESPAWN;
    end;
  end;//if

  if (other.client.pers.weapon <> ent.item) AND
     (other.client.pers.inventory[index] = 1) AND
     (!deathmatch.value OR other.client.pers.weapon = FindItem('blaster')) then
    other.client.newweapon := ent.item;

  Result := true;
end;//function (GAME=CTF)


{*
===============
ChangeWeapon

The old weapon has been dropped all the way, so make the new one
current
===============
*}
// (GAME=CTF)
procedure ChangeWeapon (edict_t *ent);
var
  i : integer;
begin
  if (ent.client.grenade_time) then
  begin
    ent.client.grenade_time := level.time;
    ent.client.weapon_sound := 0;
    weapon_grenade_fire (ent, false);
    ent.client.grenade_time := 0;
  end;

  ent.client.pers.lastweapon  := ent.client.pers.weapon;
  ent.client.pers.weapon      := ent.client.newweapon;
  ent.client.newweapon        := NULL;
  ent.client.machinegun_shots := 0;

  // set visible model
  if (ent.s.modelindex = 255) then
  begin
    if (ent.client.pers.weapon)
    then i := ((ent.client.pers.weapon.weapmodel AND $FF) SHL 8)
    else i := 0;
    ent.s.skinnum := (ent - g_edicts - 1) OR i;
  end;

  if (ent.client.pers.weapon AND ent.client.pers.weapon.ammo)
  then ent.client.ammo_index := ITEM_INDEX(FindItem(ent.client.pers.weapon.ammo));
  else ent.client.ammo_index := 0;

  if (!ent.client.pers.weapon) then
  begin
    // dead
    ent.client.ps.gunindex := 0;
    Exit;
  end;

  ent.client.weaponstate := WEAPON_ACTIVATING;
  ent.client.ps.gunframe := 0;
  ent.client.ps.gunindex := gi.modelindex(ent.client.pers.weapon.view_model);

  ent.client.anim_priority := ANIM_PAIN;
  if (ent.client.ps.pmove.pm_flags AND PMF_DUCKED) <> 0
  then begin
    ent.s.frame := FRAME_crpain1;
    ent.client.anim_end := FRAME_crpain4;
  end
  else begin
    ent.s.frame := FRAME_pain301;
    ent.client.anim_end := FRAME_pain304;
  end;
end;//procedure (GAME=CTF)

{*
=================
NoAmmoWeaponChange
=================
*}
// (GAME=CTF)
procedure NoAmmoWeaponChange (edict_t *ent);
begin
  if (ent.client.pers.inventory[ITEM_INDEX(FindItem('slugs'))]) AND
     (ent.client.pers.inventory[ITEM_INDEX(FindItem('railgun'))]) then
  begin
    ent.client.newweapon := FindItem ('railgun');
    Exit;
  end;

  if (ent.client.pers.inventory[ITEM_INDEX(FindItem('cells'))]) AND
     (ent.client.pers.inventory[ITEM_INDEX(FindItem('hyperblaster'))]) then
  begin
    ent.client.newweapon := FindItem ('hyperblaster');
    Exit;
  end;

  if (ent.client.pers.inventory[ITEM_INDEX(FindItem('bullets'))]) AND
     (ent.client.pers.inventory[ITEM_INDEX(FindItem('chaingun'))]) then
  begin
    ent.client.newweapon := FindItem ('chaingun');
    Exit;
  end;

  if (ent.client.pers.inventory[ITEM_INDEX(FindItem('bullets'))]) AND
     (ent.client.pers.inventory[ITEM_INDEX(FindItem('machinegun'))]) then
  begin
    ent.client.newweapon = FindItem ('machinegun');
    Exit;
  end;

  if (ent.client.pers.inventory[ITEM_INDEX(FindItem('shells'))] > 1) AND
     (ent.client.pers.inventory[ITEM_INDEX(FindItem('super shotgun'))]) then
  begin
    ent.client.newweapon := FindItem ('super shotgun');
    Exit;
  end;

  if (ent.client.pers.inventory[ITEM_INDEX(FindItem('shells'))]) AND
     (ent.client.pers.inventory[ITEM_INDEX(FindItem('shotgun'))]) then
  begin
    ent.client.newweapon := FindItem ('shotgun');
    Exit;
  end;

  ent.client.newweapon := FindItem ('blaster');
end;//procedure (GAME=CTF)

{*
=================
Think_Weapon

Called by ClientBeginServerFrame and ClientThink
=================
*}
// (GAME=CTF)
procedure Think_Weapon (edict_t *ent);
begin
  // if just died, put the weapon away
  if (ent.health < 1) then
  begin
    ent.client.newweapon := NULL;
    ChangeWeapon (ent);
  end;

  // call active weapon think routine
  if (ent.client.pers.weapon) AND (ent.client.pers.weapon.weaponthink) then
  begin
    is_quad := (ent.client.quad_framenum > level.framenum);
    if (ent.client.silencer_shots)
    then is_silenced := MZ_SILENCED
    else is_silenced := 0;
    ent.client.pers.weapon.weaponthink (ent);
  end;
end;//procedure (GAME=CTF)


{*
================
Use_Weapon

Make the weapon ready if there is ammo
================
*}
// (GAME=CTF)
procedure Use_Weapon (edict_t *ent, gitem_t *item);
var
  ammo_index : integer;
	gitem_t		*ammo_item;
begin
  // see if we're already using it
  if (item = ent.client.pers.weapon) then
    Exit;

//  if (item.ammo) AND (!g_select_empty.value) AND (!(item.flags & IT_AMMO)) then
  if (item.ammo) AND (!g_select_empty.value) AND ((item.flags AND IT_AMMO) = 0) then
  begin
    ammo_item  := FindItem(item.ammo);
    ammo_index := ITEM_INDEX(ammo_item);

    if (!ent.client.pers.inventory[ammo_index]) then
    begin
      gi.cprintf (ent, PRINT_HIGH, 'No %s for %s.\n', ammo_item.pickup_name, item.pickup_name);
      Exit;
    end;

    if (ent.client.pers.inventory[ammo_index] < item.quantity) then
    begin
      gi.cprintf (ent, PRINT_HIGH, 'Not enough %s for %s.\n', ammo_item.pickup_name, item.pickup_name);
      Exit;
    end;
  end;

  // change to this weapon when down
  ent.client.newweapon := item;
end;//procedure (GAME=CTF)


{*
================
Drop_Weapon
================
*}
// (GAME=CTF)
procedure Drop_Weapon (edict_t *ent, gitem_t *item);
var
  index : integer;
begin
//  if ((int)(dmflags.value) & DF_WEAPONS_STAY) then
{Y: NB! need test}
  if ((Trunc(dmflags.value) AND DF_WEAPONS_STAY) <> 0) then
    Exit;

  index := ITEM_INDEX(item);
  // see if we're already using it
  if ( ((item = ent.client.pers.weapon) OR (item = ent.client.newweapon)) AND
       (ent.client.pers.inventory[index] = 1) ) then
  begin
    gi.cprintf (ent, PRINT_HIGH, 'Can"t drop current weapon\n');
    Exit;
  end;//if

  Drop_Item (ent, item);
  ent.client.pers.inventory[index]--;
end;//procedure (GAME=CTF)


{*
================
Weapon_Generic

⌨️ 快捷键说明

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