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

📄 g_items.pas

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

{----------------------------------------------------------------------------}
{                                                                            }
{ 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 + -