📄 g_items.pas
字号:
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 + -