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

📄 g_items.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 5 页
字号:
unit g_items;

(*
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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*)

{******************************************************************************
Initial Conversion Author    :    Bob Janova (bob@redcorona.com)
Updated for CTF rules        :    Neil White (malice@paradise.net.nz)

Initially Conversion Created :    29-July-2002
Language                     :    Object Pascal
Compiler Version             :    Delphi 6.0 (UK)

VERSION  AUTHOR                DATE/TIME
===============================================================================
0.01     Neil                29-July-2002
         whole thing is converted, it should (fingers crossed) work
===============================================================================
NOTES:
 - based mostly on the 'g_items.pas' file submitted for the standard game
 - Needs other files to be completed to really test it
 - the orginal file by bob used 'edict_p' in many places, i have changed this to
   'pedict_t' as per the conversion notes.
 - Most of the changes between the standard game and CTF  have '//ZOID' around
   them
===============================================================================
TODO:
 - Check it! i am kind of new to this sort of thing so it might be wise for
   someone else to have a chech over it!
******************************************************************************}

interface
uses    g_local,
        q_shared,
        gameunit,
        g_cmds,
        cpas,
        g_utils,
        p_weapon;

function  Pickup_Weapon (Ent,Other:Pedict_t): QBoolean;
procedure Use_Weapon (Ent: Pedict_t; Inv: Pgitem_t);
procedure Drop_Weapon (Ent: Pedict_t; Inv: Pgitem_t);

procedure Weapon_Blaster (Ent: Pedict_t);
procedure Weapon_Shotgun (Ent: Pedict_t);
procedure Weapon_SuperShotgun (Ent: Pedict_t);
procedure Weapon_Machinegun (Ent: Pedict_t);
procedure Weapon_Chaingun (Ent: Pedict_t);
procedure Weapon_GrenadeLauncher (Ent: Pedict_t);
procedure Weapon_RocketLauncher (Ent: Pedict_t);
procedure Weapon_Hyperblaster (Ent: Pedict_t);
procedure Weapon_Railgun (Ent: Pedict_t);
procedure Weapon_BFG(Ent: Pedict_t);
procedure Weapon_Grenade (Ent: Pedict_t);

const   JacketArmor_Info: GItem_Armor_t = (Base_Count     :25;
                                        Max_Count         :50;
                                        Normal_Protection :0.30;
                                        Energy_Protection :0.00;
                                        Armor             :ARMOR_JACKET);
        CombatArmor_Info: GItem_Armor_t = (Base_Count     :50;
                                        Max_Count         :100;
                                        Normal_Protection :0.60;
                                        Energy_Protection :0.30;
                                        Armor             :ARMOR_COMBAT);
        BodyArmor_Info: GItem_Armor_t = (Base_Count       :100;
                                        Max_Count         :200;
                                        Normal_Protection :0.80;
                                        Energy_Protection :0.60;
                                        Armor             :ARMOR_BODY);

var jacket_armor_index  : Integer;
    combat_armor_index  : Integer;
    body_armor_index    : Integer;
    power_screen_index  : Integer;
    power_shield_index  : Integer;

const   HEALTH_IGNORE_MAX = 1;
        HEALTH_TIMED = 2;

procedure Use_Quad (Ent: Pedict_t; Item: Pgitem_t);
var Quad_drop_timeout_hack: Integer;

implementation

{-------------------------------------------------------------------------------
  GetItemByIndex
-------------------------------------------------------------------------------}

function GetItemByIndex(index : Integer):PGItem_t;
begin
  if (index = 0) or (index >= game.num_items)
    then  Result = nil
    else  Result = @itemlist[index];
end;

{-------------------------------------------------------------------------------
  FindItemByClassName
-------------------------------------------------------------------------------}

function FindItemByClassName(classname: pchar):PGItem_t;
var
  i     :Integer;
  It    : PGItem_t;
begin
  for i := 0 to game.num_items - 1 do
  begin
    it := @itemlist[i];
    if it.classname = '' then continue;
    if Q_stricmp(it.classname, classname) = 0 then
    begin
      Result := it;
      exit;
    end;
  end;
  result := nil;
end;

{-------------------------------------------------------------------------------
  FindItem
-------------------------------------------------------------------------------}

function FindItem(pickup_name: pchar):PGItem_t;
var
  i     :Integer;
  It    : PGItem_t;
begin
  for i := 0 to game.num_items - 1 do
  begin
    it := @itemlist[i];
    if it.pickup_name = '' then continue;
    if (Q_stricmp(it.pickup_name, pickup_name)) = 0   then
    begin
      Result := it;
      exit;
    end;
  end;
end;


{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}
procedure DoRespawn(ent : PEdict_t);
var
  master        : PEdict_t;
  count, choice : Integer;
begin
  if (ent.team <> nil) then
  begin   // pick a random team member
    master := ent.teammaster;
    count := 0;
    ent := master;

//  CTF MODIFICATION
//  in ctf, when we are weapons stay, only the master of a team of weapons
//  is spawned
    if (ctf.value and (dmflags.value and DF_WEAPONS_STAY)
      and master.item and (master.item.flags and IT_WEAPON))
    then ent := master

    else do
    begin
      while ent <> nil do
      begin
        ent := ent.chain;
        Inc(count);
      end;
      choice := random(count);

      count := 0; ent := master;
      while count < choice do
      begin
        ent := ent.chain;
        Inc(count);
      end;
    end;
  end;
  ent.svflags := ent.svflags and not(SVF_NOCLIENT);
  ent.solid := SOLID_TRIGGER;
  gi.linkentity (ent);

  // send an effect
  ent.s.event := EV_ITEM_RESPAWN;
end;

procedure SetRespawn(ent : PEdict_t; delay : Single);
begin
  ent.flags := ent.flags or FL_RESPAWN;
  ent.svflags := ent.svflags or SVF_NOCLIENT;
  ent.solid := SOLID_NOT;
  ent.nextthink := level.time + delay;
  ent.think := DoRespawn;
  gi.linkentity (ent);
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}
function Pickup_Powerup (Ent, Other:PEdict_t): QBoolean;
var
  Quantity: Integer;
begin
  Quantity := other.client.pers.inventory[ITEM_INDEX(ent.item)];

  if ( (skill.value = 1) and (quantity >= 2) ) or ( (skill.value >= 2) and (quantity >= 1) ) then Result := false
  else if
     (coop.value <> 0) and ((ent.item.flags and IT_STAY_COOP) > 0) and (quantity > 0) then Result := false
  else
  begin
    Inc(other.client.pers.inventory[ITEM_INDEX(ent.item)]);

    if (deathmatch.value <> 0) then
    begin
      if (ent.spawnflags and DROPPED_ITEM) = 0 then SetRespawn (ent, ent.item.quantity);
      if ((round(dmflags.value) and DF_INSTANT_ITEMS) > 0) or (@ent.item.use = @Use_Quad) and
         ((ent.spawnflags and DROPPED_PLAYER_ITEM) > 0) then
      begin
        if (@ent.item.use = @Use_Quad) and ((ent.spawnflags and DROPPED_PLAYER_ITEM) > 0)
          then quad_drop_timeout_hack := round((ent.nextthink - level.time) / FRAMETIME);
        // use it immediately
        ent.item.use (other, ent.item);
      end;
    end;
  end;
  Result := true;
end;

procedure Drop_General(Ent:PEdict_t;Item: PGItem_t);
begin
  Drop_Item(ent, item);
  Dec(ent.client.pers.inventory[ITEM_INDEX(item)]);
  ValidateSelectedItem (ent);
end;

//===================================

function Pickup_Adrenaline (Ent, Other:PEdict_t): QBoolean;
begin
  if (deathmatch.value=0) then Inc(other.max_health);
  if (other.health < other.max_health) then other.health := other.max_health;

  if (ent.spawnflags and DROPPED_ITEM= 0) and (deathmatch.value<>0)
    then SetRespawn (ent, ent.item.quantity);

  Result := True;
end;

function Pickup_AncientHead (Ent, Other:PEdict_t): QBoolean;
begin
  Inc(other.max_health, 2);

  if (ent.spawnflags and DROPPED_ITEM = 0) and (deathmatch.value<>0)
    then SetRespawn (ent, ent.item.quantity);

  Result := True;
end;

function Pickup_Bandolier (Ent, Other:PEdict_t): QBoolean;
var
  item: PGItem_t;
  Index:Integer;
begin
  if (other.client.pers.max_bullets < 250) then other.client.pers.max_bullets := 250;
  if (other.client.pers.max_shells < 150) then other.client.pers.max_shells := 150;
  if (other.client.pers.max_cells < 250) then other.client.pers.max_cells := 250;
  if (other.client.pers.max_slugs < 75) then other.client.pers.max_slugs := 75;

  item := FindItem('Bullets');
  if item <> nil then
  begin
    index := ITEM_INDEX(item);
    Inc(other.client.pers.inventory[index], item.quantity);
    if (other.client.pers.inventory[index] > other.client.pers.max_bullets)
      then other.client.pers.inventory[index] := other.client.pers.max_bullets;
  end;

  item := FindItem('Shells');
  if item <> nil then begin
    index := ITEM_INDEX(item);
    Inc(other.client.pers.inventory[index], item.quantity);
    if (other.client.pers.inventory[index] > other.client.pers.max_shells) then
    other.client.pers.inventory[index] := other.client.pers.max_shells;
  end;

  if (ent.spawnflags and DROPPED_ITEM=0) and (deathmatch.value<>0)
    then SetRespawn (ent, ent.item.quantity);

  Result := True;
end;

function Pickup_Pack (Ent, Other:PEdict_t): QBoolean;
var
  item: PGItem_t;
  Index:Integer;
begin
  if (other.client.pers.max_bullets < 300) then other.client.pers.max_bullets := 300;
  if (other.client.pers.max_shells < 200) then other.client.pers.max_shells := 200;
  if (other.client.pers.max_rockets < 100) then other.client.pers.max_rockets := 100;
  if (other.client.pers.max_grenades < 100) then other.client.pers.max_grenades := 100;
  if (other.client.pers.max_cells < 300) then other.client.pers.max_cells := 300;
  if (other.client.pers.max_slugs < 100) then other.client.pers.max_slugs := 100;

  item := FindItem('Bullets');
  if item <> nil then
  begin
    index := ITEM_INDEX(item);
    Inc(other.client.pers.inventory[index], item.quantity);
    if (other.client.pers.inventory[index] > other.client.pers.max_bullets)
      then other.client.pers.inventory[index] := other.client.pers.max_bullets;
  end;

  item := FindItem('Shells');
  if item <> nil then
  begin
    index := ITEM_INDEX(item);
    Inc(other.client.pers.inventory[index], item.quantity);
    if (other.client.pers.inventory[index] > other.client.pers.max_shells)
      then other.client.pers.inventory[index] := other.client.pers.max_shells;
  end;

  item := FindItem('Cells');
  if item <> nil then
  begin
    index := ITEM_INDEX(item);
    Inc(other.client.pers.inventory[index], item.quantity);
    if (other.client.pers.inventory[index] > other.client.pers.max_cells)
      then other.client.pers.inventory[index] := other.client.pers.max_cells;
  end;

  item := FindItem('Grenades');
  if item <> nil then
  begin
    index := ITEM_INDEX(item);
    Inc(other.client.pers.inventory[index], item.quantity);
    if (other.client.pers.inventory[index] > other.client.pers.max_grenades)
      then other.client.pers.inventory[index] := other.client.pers.max_grenades;
  end;

  item := FindItem('Rockets');
  if item <> nil then
  begin
    index := ITEM_INDEX(item);
    Inc(other.client.pers.inventory[index], item.quantity);
    if (other.client.pers.inventory[index] > other.client.pers.max_rockets)
      then other.client.pers.inventory[index] := other.client.pers.max_rockets;
  end;

  item := FindItem('Slugs');
  if item <> nil then
  begin
    index := ITEM_INDEX(item);
    Inc(other.client.pers.inventory[index], item.quantity);
    if (other.client.pers.inventory[index] > other.client.pers.max_slugs)
      then other.client.pers.inventory[index] := other.client.pers.max_slugs;
  end;

  if (ent.spawnflags and DROPPED_ITEM = 0) and (deathmatch.value<>0)
  then SetRespawn (ent, ent.item.quantity);

  Result := True;
end;

//===================================

procedure Use_Quad (ent:PEdict_t; item:PGItem_t);
var
  timeout:integer;
begin
  dec(ent.client.pers.inventory[ITEM_INDEX(item)]);
  ValidateSelectedItem (ent);

  if (quad_drop_timeout_hack<>0) then
  begin
    timeout := quad_drop_timeout_hack;
    quad_drop_timeout_hack := 0;
  end
  else timeout := 300;

  if (ent.client.quad_framenum > level.framenum)
  then ent.client.quad_framenum := ent.client.quad_framenum + timeout
  else ent.client.quad_framenum := level.framenum + timeout;

  gi.sound(ent, CHAN_ITEM, gi.soundindex('items/damage.wav'), 1, ATTN_NORM, 0);
end;

//===================================

procedure Use_Breather (ent:pedict_t; item:pgitem_t);
begin

⌨️ 快捷键说明

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