📄 g_items.pas
字号:
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 gi.sound(other, CHAN_ITEM, gi.soundindex('items/s_health.wav'), 1, ATTN_NORM, 0)
else if (ent.count = 10)
then gi.sound(other, CHAN_ITEM, gi.soundindex('items/n_health.wav'), 1, ATTN_NORM, 0)
else if (ent.count = 25)
then gi.sound(other, CHAN_ITEM, gi.soundindex('items/l_health.wav'), 1, ATTN_NORM, 0)
else // (ent.count = 100)
gi.sound(other, CHAN_ITEM, gi.soundindex('items/m_health.wav'), 1, ATTN_NORM, 0);
end
else if (ent.item.pickup_sound<>nil) then
begin
gi.sound(other, CHAN_ITEM, gi.soundindex(ent.item.pickup_sound), 1, ATTN_NORM, 0);
end;
end;
if (ent.spawnflags and ITEM_TARGETS_USED<>0) then
begin
G_UseTargets (ent, other);
ent.spawnflags :=ent.spawnflags or ITEM_TARGETS_USED;
end;
if not(taken) then
exit;
if ((coop.value=0) and (ent.item.flags and IT_STAY_COOP=0)) or (ent.spawnflags and (DROPPED_ITEM or DROPPED_PLAYER_ITEM)=0) then
begin
if (ent.flags and FL_RESPAWN<>0)
then ent.flags :=ent.flags and not (FL_RESPAWN)
else G_FreeEdict (ent);
end;
end;
//===================================
procedure drop_temp_touch (ent:pedict_t;other:pedict_t;plane: pcplane_t;surf:pcsurface_t);
begin
if (other = ent.owner) then exit;
Touch_Item (ent, other, plane, surf);
end;
procedure drop_make_touchable (ent:pedict_t);
begin
ent.touch := @Touch_Item;
if (deathmatch.value<>0) then
begin
ent.nextthink := level.time + 29;
ent.think := G_FreeEdict;
end;
end;
function Drop_Item (ent:pedict_t;item:pgitem_t):pedict_t;
var
dropped : pedict_t;
forwardd, right : vec3_t; {forward has been changed to forwardd}
offset : vec3_t;
trace : trace_t;
begin
dropped := G_Spawn;
dropped.classname := item.classname;
dropped.item := item;
dropped.spawnflags := DROPPED_ITEM;
dropped.s.effects := item.world_model_flags;
dropped.s.renderfx := RF_GLOW;
VectorSet (dropped.mins, -15, -15, -15);
VectorSet (dropped.maxs, 15, 15, 15);
gi.setmodel (dropped, dropped.item.world_model);
dropped.solid := SOLID_TRIGGER;
dropped.movetype := MOVETYPE_TOSS;
dropped.touch := @drop_temp_touch;
dropped.owner := ent;
if (ent.client<>nil) then
begin
AngleVectors (ent.client.v_angle, @forwardd, @right, nil);
VectorSet(offset, 24, 0, -16);
G_ProjectSource (ent.s.origin, offset, forwardd, right, dropped.s.origin);
trace := gi.trace (ent.s.origin, dropped.mins, dropped.maxs,
dropped.s.origin, ent, CONTENTS_SOLID);
VectorCopy (trace.endpos, dropped.s.origin);
end
else
begin
AngleVectors (ent.s.angles, @forwardd, @right, nil);
VectorCopy (ent.s.origin, dropped.s.origin);
end;
VectorScale (forwardd, 100, dropped.velocity);
dropped.velocity[2] := 300;
dropped.think := drop_make_touchable;
dropped.nextthink := level.time + 1;
gi.linkentity (dropped);
result:= dropped;
end;
procedure Use_Item (ent:pedict_t;other:pedict_t;activator:pedict_t);
begin
ent.svflags :=ent.svflags and not(SVF_NOCLIENT);
ent.use := nil;
if (ent.spawnflags and ITEM_NO_TOUCH<>0) then
begin
ent.solid := SOLID_BBOX;
ent.touch := nil;
end
else
begin
ent.solid := SOLID_TRIGGER;
ent.touch := @Touch_Item;
end;
gi.linkentity (ent);
end;
//===================================
{
========
droptofloor
========
}
procedure droptofloor (ent:pedict_t);
var
tr : trace_t;
dest,temp : vec3_t;
v : PSingle; // this is ment to be a float but his doesn't make any sense to me
begin
v := tv(-15,-15,-15);
VectorCopy (v, ent.mins);
v := tv(15,15,15);
VectorCopy (v, ent.maxs);
if (ent.model<>nil)
then gi.setmodel (ent, ent.model)
else gi.setmodel (ent, ent.item.world_model);
ent.solid := SOLID_TRIGGER;
ent.movetype := MOVETYPE_TOSS;
ent.touch := @Touch_Item;
v := tv(0,0,-128);
VectorAdd (ent.s.origin, v, dest);
tr := gi.trace (ent.s.origin, ent.mins, ent.maxs, dest, ent, MASK_SOLID);
if (tr.startsolid) then
begin
gi_dprintf ('droptofloor: %s startsolid at %s'#10,[ent.classname, vtos(ent.s.origin)]);
G_FreeEdict (ent);
exit;
end;
VectorCopy (tr.endpos, ent.s.origin);
if (ent.team<>nil) then
begin
ent.flags :=ent.flags and not(FL_TEAMSLAVE);
ent.chain := ent.teamchain;
ent.teamchain := nil;
ent.svflags :=ent.svflags or SVF_NOCLIENT;
ent.solid := SOLID_NOT;
if (ent = ent.teammaster) then
begin
ent.nextthink := level.time + FRAMETIME;
ent.think := DoRespawn;
end;
end;
if (ent.spawnflags and ITEM_NO_TOUCH<>0) then
begin
ent.solid := SOLID_BBOX;
ent.touch := nil;
ent.s.effects :=ent.s.effects and not(EF_ROTATE);
ent.s.renderfx :=ent.s.renderfx and not(RF_GLOW);
end;
if (ent.spawnflags and ITEM_TRIGGER_SPAWN<>0) then
begin
ent.svflags :=ent.svflags or SVF_NOCLIENT;
ent.solid := SOLID_NOT;
ent.use := @Use_Item;
end;
gi.linkentity (ent);
end;
{
========
PrecacheItem
Precaches all data needed for a given item.
This will be called for each item spawned in a level,
and for each item in each client's inventory.
========
}
procedure PrecacheItem (it:pgitem_t);
var
s,start : pchar;
data : array[0..MAX_QPATH-1] of char;
len : integer;
ammo : pgitem_t; /////////////////
begin
if (it = nil) then exit; // bail if no item has been given
if (it.pickup_sound <> nil) then gi.soundindex(it.pickup_sound);
if (it.world_model <> nil) then gi.modelindex(it.world_model);
if (it.view_model <> nil) then gi.modelindex(it.view_model);
if (it.icon <> nil) then gi.imageindex(it.icon);
// parse everything for its ammo
if (it.ammo<>nil) and (it.ammo[0]<>'') then
begin
ammo := FindItem (it.ammo);
if (ammo <> it) then PrecacheItem (ammo);
end;
// parse the space seperated precache string for other items
s := it.precaches;
if (s=nil) or (s[0]<>'') then exit;
while ( s=nil) do
begin
start := s;
while ( s=nil) and (s <>' ') do
inc(s);
len := s-start;
if (len >= MAX_QPATH) or( len < 5) then
gi_error ('PrecacheItem: %s has bad precache string', [it.classname]);
memcpy (@data, start, len);
data[len] := #0;
if ( s<>nil) then inc(s);
// determine type based on extension
if (strcmp(data+len-3, 'md2')=0)
then gi.modelindex (data)
else if (strcmp(data+len-3, 'sp2')=0)
then gi.modelindex (data)
else if (strcmp(data+len-3, 'wav')=0)
then gi.soundindex (data);
else if (strcmp(data+len-3, 'pcx')=0)
then gi.imageindex (data);
end;
end;
{
======
SpawnItem
Sets the clipping size and plants the object on the floor.
Items can't be immediately dropped to floor, because they might
be on an entity that hasn't spawned yet.
======
}
procedure SpawnItem (ent:pedict_t;item: pgitem_t);
begin
PrecacheItem (item);
if (ent.spawnflags<>0) then
begin
if (strcmp(ent.classname, 'key_power_cube') <> 0) then
begin
ent.spawnflags := 0;
gi_dprintf('%s at %s has invalid spawnflags set'#10, [ent.classname, vtos(ent.s.origin)]);
end;
end;
// some items will be prevented in deathmatch
if (deathmatch.value<>0) then
begin
if ( round(dmflags.value) and DF_NO_ARMOR <>0) then
begin
if (@item.pickup = @Pickup_Armor) or (@item.pickup = @Pickup_PowerArmor) then
begin
G_FreeEdict (ent);
exit;
end;
end;
if ( round(dmflags.value) and DF_NO_ITEMS <>0) then
begin
if (@item.pickup = @Pickup_Powerup) then
begin
G_FreeEdict (ent);
exit;
end;
end;
if ( round(dmflags.value) and DF_NO_HEALTH <>0) then
begin
if (@item.pickup = @Pickup_Health) or (@item.pickup = @Pickup_Adrenaline )or (@item.pickup = @Pickup_AncientHead) then
begin
G_FreeEdict (ent);
exit;
end;
end;
if ( round(dmflags.value) and DF_INFINITE_AMMO <>0) then
begin
if ( item.flags = IT_AMMO) or (strcmp(ent.classname, 'weapon_bfg') = 0 ) then
begin
G_FreeEdict (ent);
exit;
end;
end;
end;
if (coop.value <> 0) and (strcmp(ent.classname, 'key_power_cube') = 0) then
begin
ent.spawnflags :=ent.spawnflags or (1 shl (8 + level.power_cubes));
inc(level.power_cubes);
end;
// don't let them drop items that stay in a coop game
if (coop.value<>0) and (item.flags and IT_STAY_COOP<>0) then
begin
item.drop := nil;
end;
//ZOID
//Don't spawn the flags unless enabled
if ((ctf.value = 0)
and ((strcmp(ent.classname, 'item_flag_team1') = 0) or
(strcmp(ent.classname, 'item_flag_team2') = 0)) then
begin
G_FreeEdict(ent);
exit;
end;
//ZOID
ent.item := item;
ent.nextthink := level.time + 2 * FRAMETIME; // items start after other solids
ent.think := droptofloor;
ent.s.effects := item.world_model_flags;
ent.s.renderfx := RF_GLOW;
if (ent.model<>nil) then gi.modelindex (ent.model);
//ZOID
//flags are server animated and have special handling
if ((strcmp(ent.classname, 'item_flag_team1') = 0) or
(strcmp(ent.classname, 'item_flag_team2') = 0))
then ent.think := CTFFlagSetup;
//ZOID
end;
const itemlist:array[0..50]of gitem_s = (
(
// nil
), // leave index 0 alone
//
// ARMOR
//
{QUAKED item_armor_body (.3 .3 1) (-16 -16 -16) (16 16 16)
}
(
classname : 'item_armor_body';
pickup : Pickup_Armor;
use : nil;
drop : nil;
weaponthink : nil;
pickup_sound : 'misc/ar1_pkup.wav';
world_model : 'models/items/armor/body/tris.md2';
world_model_flags: EF_ROTATE;
view_model : nil;
{ icon } icon : 'i_bodyarmor';
{ pickup} pickup_name :'Body Armor';
{ width } count_width : 3;
quantity : 0;
ammo : nil;
flags : IT_ARMOR;
weapmodel : 0;
info : @bodyarmor_info;
tag : ARMOR_BODY;
{ precache } precaches : '';
),
{QUAKED item_armor_combat (.3 .3 1) (-16 -16 -16) (16 16 16)
}
(
classname : 'item_armor_combat';
pickup : Pickup_Armor;
use : nil;
drop : nil;
weaponthink : nil;
pickup_sound : 'misc/ar1_pkup.wav';
world_model : 'models/items/armor/body/tris.md2';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -