📄 g_items.pas
字号:
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:edict_p;other:edict_p;plane: cplane_p;surf:csurface_p);
begin
if (other = ent^.owner) then
exit;
Touch_Item (ent, other, plane, surf);
end;
procedure drop_make_touchable (ent:edict_p);
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:edict_p;item:gitem_p):edict_p;
var
dropped: edict_p;
forwardd, right:vec3_t;
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:edict_p;other:edict_p;activator:edict_p);
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:edict_p);
var
tr:trace_t;
dest,temp:vec3_t;
v:vec3_t;//pSingle;
begin
// v := tv(-15,-15,-15);
v := tv2(-15,-15,-15);
VectorCopy (v, ent^.mins);
v := tv2(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 := tv2(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:gitem_p);
var
s,start:pchar;
data:array[0..MAX_QPATH-1] of char;
len:integer;
ammo: gitem_p;
begin
if (it=nil) then
exit;
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);
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:edict_p;item: gitem_p);
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;
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);
end;
(*
//===================================
type gitem_p =record
classname: PChar; // spawning name
pickup: BoolFunc_2edict_s;
use: Proc_edit_s__gitem_s;
drop: Proc_edit_s__gitem_s;
weaponthink: Proc_edit_s;
pickup_sound: PChar;
world_model: PChar;
world_model_flags: integer;
view_model: PChar;
// client side info
icon: PChar;
pickup_name: PChar; // for printing on pickup
count_width: integer; // number of digits to display by icon
quantity: integer; // for ammo how much, for weapons how much is used per shot
ammo: PChar; // for weapons
flags: integer; // IT_* flags
weapmodel: integer; // weapon model index (for weapons)
info: Pointer;
tag: integer;
precaches: PChar; // string of all models, sounds, and images this item will use *)
const itemlist:array[0..42]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';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -