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

📄 g_items.pas

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

procedure Use_Silencer (ent:edict_p;item: gitem_p);
begin
	dec(ent^.client^.pers.inventory[ITEM_INDEX(item)]);
	ValidateSelectedItem (ent);
	ent^.client^.silencer_shots := ent^.client^.silencer_shots + 30;

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

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

function Pickup_Key (ent:edict_p;other:edict_p):qboolean;
begin
     	result:= true;
	if (coop^.value<>0)then
	begin
		if (strcmp(ent^.classname, 'key_power_cube') = 0) then
		begin
	   if (other^.client^.pers.power_cubes<>0) and( ent^.spawnflags and $0000ff00 shr 8<>0) then
           // begin
             result:= false;
           //  exit;
          //  end;
	  inc(other^.client^.pers.inventory[ITEM_INDEX(ent^.item)]);
	  other^.client^.pers.power_cubes :=other^.client^.pers.power_cubes or (ent^.spawnflags and $0000ff00 shr 8);
		end
		else
		begin
			if (other^.client^.pers.inventory[ITEM_INDEX(ent^.item)]<>0)then
				result:= false;
			other^.client^.pers.inventory[ITEM_INDEX(ent^.item)] := 1;
		end;
               // begin
		result:= true;
	end;
	inc(other^.client^.pers.inventory[ITEM_INDEX(ent^.item)]);

end;

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

function Add_Ammo (ent:edict_p;item: gitem_p; count:integer):qboolean;
var
  index:integer;
  max:integer;
begin
     result:= true;

	if (ent^.client=nil)  then
        begin
	  result:= false;
          exit;
        end;
	if (item^.tag = ord(AMMO_BULLETS)) then
		max := ent^.client^.pers.max_bullets
	else if (item^.tag = ord(AMMO_SHELLS)) then
		max := ent^.client^.pers.max_shells
	else if (item^.tag = ord(AMMO_ROCKETS))  then
		max := ent^.client^.pers.max_rockets
	else if (item^.tag = ord(AMMO_GRENADES)) then
		max := ent^.client^.pers.max_grenades
	else if (item^.tag = ord(AMMO_CELLS))  then
		max := ent^.client^.pers.max_cells
	else if (item^.tag = ord(AMMO_SLUGS))  then
		max := ent^.client^.pers.max_slugs
	else
              begin
		result:= false;
                exit;
              end;

	index := ITEM_INDEX(item);

	if (ent^.client^.pers.inventory[index] = max) then
                begin
	         result:= false;
                 exit;
                end;

	ent^.client^.pers.inventory[index] :=ent^.client^.pers.inventory[index]+  count;

	if (ent^.client^.pers.inventory[index] > max) then
		ent^.client^.pers.inventory[index] := max;


end;

function Pickup_Ammo (ent:edict_p;other:edict_p): qboolean;
var
  oldcount:integer;
  count:integer;
  weapon:qboolean;

begin
    weapon := (ent^.item^.flags and IT_WEAPON<>0);
	if ( weapon) and (round(dmflags^.value) and DF_INFINITE_AMMO <>0 ) then
		count := 1000
	else if (ent^.count<>0)  then
		count := ent^.count
	else
		count := ent^.item^.quantity;

	oldcount := other^.client^.pers.inventory[ITEM_INDEX(ent^.item)];

	if not(Add_Ammo (other, ent^.item, count)) then
             begin
		result:= false;
                exit;
                end;
	if (weapon )and (oldcount<>0) then
	begin
  if (other^.client^.pers.weapon <> ent^.item) and
  ( deathmatch^.value=0) or (other^.client^.pers.weapon = FindItem('blaster') ) then
	  other^.client^.newweapon := ent^.item;
	end;

	if (ent^.spawnflags and (DROPPED_ITEM or DROPPED_PLAYER_ITEM)=0) and (deathmatch^.value<>0)  then
		SetRespawn (ent, 30);

   result:= true;
end;

procedure Drop_Ammo(ent:edict_p;item: gitem_p);
var
  dropped:edict_p;
  index:integer;
begin


	index := ITEM_INDEX(item);
	dropped := Drop_Item (ent, item);
	if (ent^.client^.pers.inventory[index] >= item^.quantity)   then
		dropped^.count := item^.quantity
	else
		dropped^.count := ent^.client^.pers.inventory[index];

	if (ent^.client^.pers.weapon<>nil) and
		(ent^.client^.pers.weapon^.tag = ord(AMMO_GRENADES)) and
	       (item^.tag = ord(AMMO_GRENADES)) and
		(ent^.client^.pers.inventory[index] - dropped^.count <= 0) then
               begin
		 gi.cprintf (ent, PRINT_HIGH, 'Can t drop current weapon'#10);
	         G_FreeEdict(dropped);
	         exit;
         	end;

	ent^.client^.pers.inventory[index] :=ent^.client^.pers.inventory[index] - dropped^.count;
	ValidateSelectedItem (ent);
end;


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

procedure MegaHealth_think (self:edict_p);
begin
	if (self^.owner^.health > self^.owner^.max_health) then
	begin
		self^.nextthink := level.time + 1;
		self^.owner^.health :=self^.owner^.health - 1;
		exit;
	end;

	if (self^.spawnflags and DROPPED_ITEM=0) and (deathmatch^.value<>0)  then
		SetRespawn (self, 20)
	else
	    G_FreeEdict (self);
end;

function Pickup_Health (ent:edict_p;other:edict_p):qboolean;
begin
	if (ent^.style and HEALTH_IGNORE_MAX=0)   then
		if (other^.health >= other^.max_health)  then
                       begin
		          result:= false;
                          exit;
                        end;
	other^.health:=other^.health + ent^.count;

	if (ent^.style and HEALTH_IGNORE_MAX=0)  then
	begin
		if (other^.health > other^.max_health)then
			other^.health := other^.max_health;
	end;

	if (ent^.style and HEALTH_TIMED<>0)   then
	begin
		ent^.think := @MegaHealth_think;
		ent^.nextthink := level.time + 5;
		ent^.owner := other;
		ent^.flags :=ent^.flags or FL_RESPAWN;
		ent^.svflags :=ent^.svflags or SVF_NOCLIENT;
		ent^.solid := SOLID_NOT;
	end
	else
	begin
		if (ent^.spawnflags and DROPPED_ITEM=0) and (deathmatch^.value<>0) then
			SetRespawn (ent, 30);
	end;

   result:=true;
end;

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

function ArmorIndex (ent:edict_p):integer;
begin
      	result:= 0;
	if (ent^.client=nil) then
		exit;

	if (ent^.client^.pers.inventory[jacket_armor_index] > 0) then
              begin
	         result:= jacket_armor_index;
                 exit;
                end;
	if (ent^.client^.pers.inventory[combat_armor_index] > 0) then
                begin
		 result:= combat_armor_index;
                 exit;
                end;
	if (ent^.client^.pers.inventory[body_armor_index] > 0) then
               begin
		 result:= body_armor_index;
                 exit;
                end;

end;

function Pickup_Armor (ent:edict_p;other: edict_p):qboolean;
var
  old_armor_index:integer;
  oldinfo:gitem_armor_p;
  newinfo:gitem_armor_p;
  newcount:integer;
  salvage:single;
  salvagecount:integer;
begin
   result:=true;
	// get info on new armor
	newinfo := gitem_armor_p(ent^.item^.info);

	old_armor_index := ArmorIndex (other);

	// handle armor shards specially
	if (ent^.item^.tag = ARMOR_SHARD) then
	begin
		if (old_armor_index=0)  then
			other^.client^.pers.inventory[jacket_armor_index] := 2
		else
			other^.client^.pers.inventory[old_armor_index] :=other^.client^.pers.inventory[old_armor_index] + 2;
	end

	// if player has no armor, just use it
	else if (old_armor_index=0) then
	begin
		other^.client^.pers.inventory[ITEM_INDEX(ent^.item)] := newinfo^.base_count;
	end

	// use the better armor
	else
	begin
		// get info on old armor
		if (old_armor_index = jacket_armor_index)  then
			oldinfo := @jacketarmor_info
		else if (old_armor_index = combat_armor_index)  then
			oldinfo := @combatarmor_info
		else // (old_armor_index = body_armor_index)
			oldinfo := @bodyarmor_info;

		if (newinfo^.normal_protection > oldinfo^.normal_protection) then
		begin
			// calc new armor values
			salvage := oldinfo^.normal_protection / newinfo^.normal_protection;
			salvagecount := round(salvage) * other^.client^.pers.inventory[old_armor_index];
			newcount := newinfo^.base_count + salvagecount;
			if (newcount > newinfo^.max_count)   then
				newcount := newinfo^.max_count;

			// zero count of old armor so it goes away
			other^.client^.pers.inventory[old_armor_index] := 0;

			// change armor to new item with computed value
			other^.client^.pers.inventory[ITEM_INDEX(ent^.item)] := newcount;
		end
		else
		begin
			// calc new armor values
			salvage := newinfo^.normal_protection / oldinfo^.normal_protection;
			salvagecount := round(salvage )* newinfo^.base_count;
			newcount := other^.client^.pers.inventory[old_armor_index] + salvagecount;
			if (newcount > oldinfo^.max_count)  then
				newcount := oldinfo^.max_count;

			// if we're already maxed out then we don't need the new armor
			if (other^.client^.pers.inventory[old_armor_index] >= newcount)  then
                             // begin
				 result:= false;
                              //   exit;
                             //   end;
			// update current armor value
			other^.client^.pers.inventory[old_armor_index] := newcount;
		end;
	end;

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

	result:=true;
end;

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

function PowerArmorType(ent:edict_p):integer;
begin
  result:= POWER_ARMOR_NONE;
	if (ent^.client=nil)   then
		result:= POWER_ARMOR_NONE;

	if (ent^.flags and FL_POWER_ARMOR=0) then
	      	result:= POWER_ARMOR_NONE;

	if (ent^.client^.pers.inventory[power_shield_index] > 0) then
		result:= POWER_ARMOR_SHIELD;

	if (ent^.client^.pers.inventory[power_screen_index] > 0)  then
		result:= POWER_ARMOR_SCREEN;


end;

procedure Use_PowerArmor(ent:edict_p;item: gitem_p);
var
   index:integer;
begin


	if (ent^.flags and FL_POWER_ARMOR<>0) then
	begin
		ent^.flags :=ent^.flags and not(FL_POWER_ARMOR);
		gi.sound(ent, CHAN_AUTO, gi.soundindex('misc/power2.wav'), 1, ATTN_NORM, 0);
	end
	else
	begin
		index := ITEM_INDEX(FindItem('cells'));
		if (ent^.client^.pers.inventory[index]=0)  then
		begin
			gi.cprintf (ent, PRINT_HIGH, 'No cells for power armor.'#10);
			exit;
		end;
		ent^.flags :=ent^.flags or FL_POWER_ARMOR;
		gi.sound(ent, CHAN_AUTO, gi.soundindex('misc/power1.wav'), 1, ATTN_NORM, 0);
	end;
end;

function Pickup_PowerArmor (ent:edict_p;other:edict_p):qboolean;
var
  quantity:integer;
begin


	quantity := other^.client^.pers.inventory[ITEM_INDEX(ent^.item)];

	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);
		// auto-use for DM only if we didn't already have one
		if (quantity<>0) then
			ent^.item^.use (other, ent^.item);
	end;

   result:= true;
end;

procedure Drop_PowerArmor(ent:edict_p;item: gitem_p);
begin
  if (ent^.flags and FL_POWER_ARMOR<>0) and (ent^.client^.pers.inventory[ITEM_INDEX(item)] = 1) then
		Use_PowerArmor (ent, item);
	Drop_General (ent, item);
end;

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

{
========
Touch_Item
========
}
procedure Touch_Item (ent:edict_p;other:edict_p;plane: cplane_p;surf: csurface_p);
var
  taken:qboolean;
begin


	if (other^.client=nil) then
	       exit;
	if (other^.health < 1) then
		exit;		// dead people can't pickup
	if (@ent^.item^.pickup<>nil)  then
		exit;		// not a grabbable item?

	taken := ent^.item^.pickup(ent, other);

	if (taken) then
	begin
		// flash the screen
		other^.client^.bonus_alpha := 0.25;	

		// show icon and name on status bar
		other^.client^.ps.stats[STAT_PICKUP_ICON] := gi.imageindex(ent^.item^.icon);
		other^.client^.ps.stats[STAT_PICKUP_STRING] := CS_ITEMS+ITEM_INDEX(ent^.item);
		other^.client^.pickup_msg_time := level.time + 3.0;

		// change selected item
		if (@ent^.item^.use<>nil) then
		 other^.client^.pers.selected_item := ITEM_INDEX(ent^.item);
                 other^.client^.ps.stats[STAT_SELECTED_ITEM] := ITEM_INDEX(ent^.item);

		if (@ent^.item^.pickup = @Pickup_Health)  then
		begin
			if (ent^.count = 2)  then

⌨️ 快捷键说明

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