📄 g_items.pas
字号:
{----------------------------------------------------------------------------}
{ }
{ File(s): g_items.c }
{ }
{ Initial conversion by : Bob Janova (bob@redcorona.com) }
{ Initial conversion on : 30-Apr-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) }
{ 2) }
{----------------------------------------------------------------------------}
{ * TODO: }
{ }
{----------------------------------------------------------------------------}
unit g_items;
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);
function Drop_Item (ent:edict_p;item:gitem_p):edict_p;
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,combat_armor_index,body_armor_index,power_screen_index,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
//#define ITEM_INDEX(x) ((x)-itemlist)
function ITEM_INDEX(x:PGItem_t):integer;
begin
result:=(integer(x)-integer(@itemlist));
end;
//===================================
{
========
GetItemByIndex
========
}
function GetItemByIndex(index: Integer):PGItem_t;
begin
Result := nil;
if (index = 0) or (index >= game.num_items) then exit;
result := @itemlist[index];
end;
{
========
FindItemByClassname
========
}
function FindItemByClassame(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 (CompareText(it^.classname, classname)) = 0 then begin
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;
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;
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:Double);
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
// Check quantity: 3.20
Result := false;
Quantity := other^.client^.pers.inventory[ITEM_INDEX(ent^.item)];
if ((skill^.value = 1) and (quantity >= 2)) or ((skill^.value >= 2) and (quantity >= 1)) then Exit;
if (coop^.value <> 0) and ((ent^.item^.flags and IT_STAY_COOP) > 0)
and (quantity > 0) then exit;
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;
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;
if item <> nil then
begin
item := FindItem('Grenades');
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:edict_p; item:gitem_p);
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
begin
timeout := 300;
end;
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:edict_p; item:gitem_p);
begin
dec(ent^.client^.pers.inventory[ITEM_INDEX(item)]);
ValidateSelectedItem (ent);
if (ent^.client^.breather_framenum > level.framenum) then
ent^.client^.breather_framenum:=ent^.client^.breather_framenum + 300
else
ent^.client^.breather_framenum := level.framenum + 300;
// gi.sound(ent, CHAN_ITEM, gi.soundindex('items/damage.wav'), 1, ATTN_NORM, 0);
end;
//===================================
procedure Use_Envirosuit(ent:edict_p;item:gitem_p);
begin
dec(ent^.client^.pers.inventory[ITEM_INDEX(item)]);
ValidateSelectedItem (ent);
if (ent^.client^.enviro_framenum > level.framenum) then
ent^.client^.enviro_framenum := ent^.client^.enviro_framenum + 300
else
ent^.client^.enviro_framenum := level.framenum + 300;
// gi.sound(ent, CHAN_ITEM, gi.soundindex('items/damage.wav'), 1, ATTN_NORM, 0);
end;
//===================================
procedure Use_Invulnerability(ent:edict_p;item: gitem_p);
begin
dec(ent^.client^.pers.inventory[ITEM_INDEX(item)]);
ValidateSelectedItem (ent);
if (ent^.client^.invincible_framenum > level.framenum) then
ent^.client^.invincible_framenum :=ent^.client^.invincible_framenum + 300
else
ent^.client^.invincible_framenum := level.framenum + 300;
gi.sound(ent, CHAN_ITEM, gi.soundindex('items/protect.wav'), 1, ATTN_NORM, 0);
end;
//===================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -