#include <common/mutators/mutator/buffs/sv_buffs.qh>
#include <common/mutators/mutator/powerups/_mod.qh>
#include <common/mutators/mutator/status_effects/_mod.qh>
+#include <common/net_linked.qh>
#include <common/notifications/all.qh>
#include <common/resources/resources.qh>
#include <common/util.qh>
else
sf &= ~ISF_DROP;
+ // if this item is being spawned (in CSQC's perspective)
+ // reuse ISF_SIZE and ISF_SIZE2 to also tell CSQC its bbox size
+ if(sf & ISF_SIZE)
+ {
+ if(this.maxs == ITEM_S_MAXS) // Small
+ {
+ sf |= ISF_SIZE;
+ sf &= ~ISF_SIZE2;
+ }
+ else if(this.maxs == ITEM_L_MAXS) // Large
+ {
+ sf &= ~ISF_SIZE;
+ sf |= ISF_SIZE2;
+ }
+ else // Default
+ sf |= ISF_SIZE | ISF_SIZE2;
+ }
+
WriteHeader(MSG_ENTITY, ENT_CLIENT_ITEM);
WriteByte(MSG_ENTITY, sf);
WriteAngleVector(MSG_ENTITY, this.angles);
}
- // sets size on the client, unused on server
- //if(sf & ISF_SIZE)
-
if(sf & ISF_STATUS)
WriteByte(MSG_ENTITY, this.ItemStatus);
- if(sf & ISF_MODEL)
+ if(sf & ISF_SIZE || sf & ISF_SIZE2) // always true when it's spawned (in CSQC's perspective)
{
WriteShort(MSG_ENTITY, bound(0, this.fade_end, 32767));
- WriteShort(MSG_ENTITY, bound(0, this.fade_start, 32767));
if(this.mdl == "")
LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "expect a crash just about now");
bool have_pickup_item(entity this)
{
- if(this.itemdef.instanceOfPowerup)
- {
- if(autocvar_g_powerups > 0)
- return true;
- if(autocvar_g_powerups == 0)
- return false;
- }
- else
+ if (this.itemdef.spawnflags & ITEM_FLAG_MUTATORBLOCKED)
+ return false;
+
+ if(!this.itemdef.instanceOfPowerup)
{
if(autocvar_g_pickup_items > 0)
return true;
}
else
{
- //setmodel(e, "null");
e.solid = SOLID_NOT;
- e.colormod = '0 0 0';
- //e.glowmod = e.colormod;
e.spawnshieldtime = 1;
e.ItemStatus &= ~ITS_AVAILABLE;
}
void Item_Think(entity this)
{
- this.nextthink = time;
- if(this.origin != this.oldorigin)
+ if (ITEM_IS_LOOT(this))
+ {
+ if (time < this.wait - IT_DESPAWNFX_TIME)
+ this.nextthink = min(time + IT_UPDATE_INTERVAL, this.wait - IT_DESPAWNFX_TIME); // ensuring full time for effects
+ else
+ {
+ // despawning soon, start effects
+ this.ItemStatus |= ITS_EXPIRING;
+ this.SendFlags |= ISF_STATUS;
+ if (time < this.wait - IT_UPDATE_INTERVAL)
+ this.nextthink = time + IT_UPDATE_INTERVAL;
+ else
+ {
+ setthink(this, RemoveItem);
+ this.nextthink = this.wait;
+ }
+ }
+
+ if (this.itemdef.instanceOfPowerup)
+ powerups_DropItem_Think(this);
+
+ // caution: kludge FIXME (with sv_legacy_bbox_expand)
+ // this works around prediction errors caused by bbox discrepancy between SVQC and CSQC
+ if (this.velocity == '0 0 0' && IS_ONGROUND(this))
+ this.gravity = 0; // don't send ISF_DROP anymore
+
+ // send slow updates even if the item didn't move
+ // recovers prediction desyncs where server thinks item stopped, client thinks it didn't
ItemUpdate(this);
+ }
+ else
+ {
+ // bones_was_here: TODO: predict movers, enable client prediction of items with a groundentity,
+ // and then send those less often too (and not all on the same frame)
+ this.nextthink = time;
+
+ if(this.origin != this.oldorigin)
+ ItemUpdate(this);
+ }
}
bool Item_ItemsTime_SpectatorOnly(GameItem it);
setthink(this, Item_Think);
this.nextthink = time;
-
- //Send_Effect(EFFECT_ITEM_RESPAWN, this.origin + this.mins_z * '0 0 1' + '0 0 48', '0 0 0', 1);
- Send_Effect(EFFECT_ITEM_RESPAWN, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
}
void Item_RespawnCountdown(entity this)
return true;
}
+void Item_NotifyWeapon(entity player, int wep)
+{
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && (it == player || (IS_SPEC(it) && it.enemy == player)), {
+ msg_entity = it;
+ WriteHeader(MSG_ONE, TE_CSQC_WEAPONPICKUP);
+ WriteByte(MSG_ONE, wep);
+ });
+}
+
bool Item_GiveTo(entity item, entity player)
{
// if nothing happens to player, just return without taking the item
pickedup |= Item_GiveAmmoTo(item, player, RES_FUEL, g_pickup_fuel_max);
if (item.itemdef.instanceOfWeaponPickup)
{
- WepSet w;
+ WepSet w, wp;
w = STAT(WEAPONS, item);
- w &= ~STAT(WEAPONS, player);
+ wp = w & ~STAT(WEAPONS, player);
- if (w || (item.spawnshieldtime && item.pickup_anyway > 0))
+ if (wp || (item.spawnshieldtime && item.pickup_anyway > 0))
{
pickedup = true;
FOREACH(Weapons, it != WEP_Null, {
if(w & (it.m_wepset))
+ Item_NotifyWeapon(player, it.m_id);
+
+ if(wp & (it.m_wepset))
{
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_ITEM_JETPACK_GOT);
}
- int its;
- if((its = (item.items - (item.items & player.items)) & IT_PICKUPMASK))
+ int its = (item.items - (item.items & player.items)) & IT_PICKUPMASK;
+ if (its)
{
pickedup = true;
player.items |= its;
void Item_Touch(entity this, entity toucher)
{
// remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
- if (Item_IsLoot(this))
+ if (ITEM_IS_LOOT(this))
{
if (ITEM_TOUCH_NEEDKILL())
{
+ this.SendFlags |= ISF_REMOVEFX;
RemoveItem(this);
return;
}
toucher = M_ARGV(1, entity);
- if (Item_IsExpiring(this))
+ if (ITEM_IS_EXPIRING(this))
{
this.strength_finished = max(0, this.strength_finished - time);
this.invincible_finished = max(0, this.invincible_finished - time);
bool gave = ITEM_HANDLE(Pickup, this.itemdef, this, toucher);
if (!gave)
{
- if (Item_IsExpiring(this))
+ if (ITEM_IS_EXPIRING(this))
{
// undo what we did above
this.strength_finished += time;
STAT(LAST_PICKUP, toucher) = time;
- Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
- _sound (toucher, (this.itemdef.instanceOfPowerup ? CH_TRIGGER_SINGLE : CH_TRIGGER), (this.item_pickupsound ? this.item_pickupsound : Sound_fixpath(this.item_pickupsound_ent)), VOL_BASE, ATTEN_NORM);
+ GameItem def = this.itemdef;
+ int ch = ((def.instanceOfPowerup && def.m_itemid != IT_RESOURCE) ? CH_TRIGGER_SINGLE : CH_TRIGGER);
+ _sound(toucher, ch, this.item_pickupsound, VOL_BASE, ATTEN_NORM);
MUTATOR_CALLHOOK(ItemTouched, this, toucher);
if (wasfreed(this))
return;
}
- if (Item_IsLoot(this))
+ if (ITEM_IS_LOOT(this))
{
- delete(this);
+ this.SendFlags |= ISF_REMOVEFX;
+ RemoveItem(this);
return;
}
if (!this.spawnshieldtime)
{
Item_Show(this, !this.state);
- if (Item_IsLoot(this))
+ if (ITEM_IS_LOOT(this))
{
return;
}
});
}
+void Item_CopyFields(entity this, entity to)
+{
+ setorigin(to, this.origin);
+ to.spawnflags = this.spawnflags;
+ to.noalign = ITEM_SHOULD_KEEP_POSITION(this);
+ to.cnt = this.cnt;
+ to.team = this.team;
+ to.spawnfunc_checked = true;
+ // TODO: copy respawn times? this may not be desirable in some cases
+ //to.respawntime = this.respawntime;
+ //to.respawntimejitter = this.respawntimejitter;
+}
+
// Savage: used for item garbage-collection
void RemoveItem(entity this)
{
if(wasfreed(this) || !this) { return; }
if(this.waypointsprite_attached)
WaypointSprite_Kill(this.waypointsprite_attached);
- Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
- delete(this);
+
+ if (this.SendFlags & ISF_REMOVEFX)
+ {
+ // delay removal until ISF_REMOVEFX has been sent
+ setthink(this, RemoveItem);
+ this.nextthink = time + 2 * autocvar_sys_ticrate; // micro optimisation: next frame will be too soon
+ this.solid = SOLID_NOT; // untouchable
+ }
+ else
+ delete(this);
}
// pickup evaluation functions
float ammo_pickupevalfunc(entity player, entity item)
{
- bool need_shells = false, need_nails = false, need_rockets = false, need_cells = false, need_plasma = false, need_fuel = false;
+ entity item_resource = NULL; // pointer to the resource that may be associated with the given item
entity wpn = NULL;
float c = 0;
float rating = 0;
- // Detect needed ammo
+ // detect needed ammo
if(item.itemdef.instanceOfWeaponPickup)
{
- entity ammo = NULL;
- if(GetResource(item, RES_SHELLS)) { need_shells = true; ammo = ITEM_Shells; }
- else if(GetResource(item, RES_BULLETS)) { need_nails = true; ammo = ITEM_Bullets; }
- else if(GetResource(item, RES_ROCKETS)) { need_rockets = true; ammo = ITEM_Rockets; }
- else if(GetResource(item, RES_CELLS)) { need_cells = true; ammo = ITEM_Cells; }
- else if(GetResource(item, RES_PLASMA)) { need_plasma = true; ammo = ITEM_Plasma; }
- else if(GetResource(item, RES_FUEL)) { need_fuel = true; ammo = ITEM_JetpackFuel; }
-
+ entity res = item.itemdef.m_weapon.ammo_type;
+ entity ammo = (res != RES_NONE) ? GetAmmoItem(res) : NULL;
if(!ammo)
return 0;
+ if(res != RES_NONE && GetResource(item, res))
+ item_resource = res;
+
wpn = item;
rating = ammo.m_botvalue;
}
FOREACH(Weapons, it != WEP_Null, {
if(!(STAT(WEAPONS, player) & (it.m_wepset)))
continue;
+ if(it.ammo_type == RES_NONE)
+ continue;
- switch(it.ammo_type)
+ if(GetResource(item, it.ammo_type))
{
- case RES_SHELLS: need_shells = true; break;
- case RES_BULLETS: need_nails = true; break;
- case RES_ROCKETS: need_rockets = true; break;
- case RES_CELLS: need_cells = true; break;
- case RES_PLASMA: need_plasma = true; break;
- case RES_FUEL: need_fuel = true; break;
+ item_resource = it.ammo_type;
+ break;
}
});
rating = item.bot_pickupbasevalue;
float noammorating = 0.5;
- if ((need_shells) && GetResource(item, RES_SHELLS) && (GetResource(player, RES_SHELLS) < g_pickup_shells_max))
- c = GetResource(item, RES_SHELLS) / max(noammorating, GetResource(player, RES_SHELLS));
-
- if ((need_nails) && GetResource(item, RES_BULLETS) && (GetResource(player, RES_BULLETS) < g_pickup_nails_max))
- c = GetResource(item, RES_BULLETS) / max(noammorating, GetResource(player, RES_BULLETS));
-
- if ((need_rockets) && GetResource(item, RES_ROCKETS) && (GetResource(player, RES_ROCKETS) < g_pickup_rockets_max))
- c = GetResource(item, RES_ROCKETS) / max(noammorating, GetResource(player, RES_ROCKETS));
-
- if ((need_cells) && GetResource(item, RES_CELLS) && (GetResource(player, RES_CELLS) < g_pickup_cells_max))
- c = GetResource(item, RES_CELLS) / max(noammorating, GetResource(player, RES_CELLS));
-
- if ((need_plasma) && GetResource(item, RES_PLASMA) && (GetResource(player, RES_PLASMA) < g_pickup_plasma_max))
- c = GetResource(item, RES_PLASMA) / max(noammorating, GetResource(player, RES_PLASMA));
-
- if ((need_fuel) && GetResource(item, RES_FUEL) && (GetResource(player, RES_FUEL) < g_pickup_fuel_max))
- c = GetResource(item, RES_FUEL) / max(noammorating, GetResource(player, RES_FUEL));
+ if(item_resource && (GetResource(player, item_resource) < GetResourceLimit(player, item_resource)))
+ c = GetResource(item, item_resource) / max(noammorating, GetResource(player, item_resource));
rating *= min(c, 2);
if(wpn)
gettouch(this)(this, actor);
}
-void _StartItem(entity this, entity def, float defaultrespawntime, float defaultrespawntimejitter)
+void StartItem(entity this, entity def)
{
- string itemname = def.m_name;
- Model itemmodel = def.m_model;
- Sound pickupsound = def.m_sound;
- float(entity player, entity item) pickupevalfunc = def.m_pickupevalfunc;
- float pickupbasevalue = def.m_botvalue;
- int itemflags = def.m_itemflags;
-
- startitem_failed = false;
+ if (def.m_spawnfunc_hookreplace)
+ def = def.m_spawnfunc_hookreplace(def, this);
+ this.itemdef = def;
+ if (def.m_canonical_spawnfunc != "") // FIXME why do weapons set itemdef to an entity that doesn't have this?
+ this.classname = def.m_canonical_spawnfunc;
- this.item_model_ent = itemmodel;
- this.item_pickupsound_ent = pickupsound;
+ startitem_failed = true; // early return means failure
+ // some mutators check for resources set by m_iteminit in FilterItem
if(def.m_iteminit)
def.m_iteminit(def, this);
- if(!this.respawntime) // both need to be set
+ // also checked by some mutators in FilterItem
+ this.items = def.m_itemid;
+ this.weapon = def.instanceOfWeaponPickup ? def.m_weapon.m_id : 0;
+ if(this.weapon)
+ STAT(WEAPONS, this) = WepSet_FromWeapon(REGISTRY_GET(Weapons, this.weapon));
+ this.flags = FL_ITEM | def.m_itemflags;
+
+ // FilterItem may change any field of a specific instance of an item, but
+ // it must not change any itemdef field (would cause mutators to break other mutators),
+ // and must not convert items into different ones (StartItem could be refactored to support that).
+ if(MUTATOR_CALLHOOK(FilterItem, this))
{
- this.respawntime = defaultrespawntime;
- this.respawntimejitter = defaultrespawntimejitter;
+ delete(this);
+ return;
}
+ if (!this.item_model_ent)
+ this.item_model_ent = def.m_model;
+
+ if (!this.item_pickupsound_ent)
+ this.item_pickupsound_ent = def.m_sound;
+ if (!this.item_pickupsound && this.item_pickupsound_ent)
+ this.item_pickupsound = Sound_fixpath(this.item_pickupsound_ent);
+ if (this.item_pickupsound == "")
+ LOG_WARNF("No pickup sound set for a %s", this.classname);
+
if(!this.pickup_anyway && def.m_pickupanyway)
this.pickup_anyway = def.m_pickupanyway();
- int itemid = def.m_itemid;
- this.items = itemid;
- int weaponid = def.instanceOfWeaponPickup ? def.m_weapon.m_id : 0;
- this.weapon = weaponid;
-
+ // bones_was_here TODO: implement sv_cullentities_dist and replace g_items_maxdist with it
if(!this.fade_end)
- {
- this.fade_start = autocvar_g_items_mindist;
this.fade_end = autocvar_g_items_maxdist;
- }
- if(weaponid)
- STAT(WEAPONS, this) = WepSet_FromWeapon(REGISTRY_GET(Weapons, weaponid));
-
- this.flags = FL_ITEM | itemflags;
+ // bones_was_here TODO: can we do this after we're sure the entity won't be deleted?
IL_PUSH(g_items, this);
- if(MUTATOR_CALLHOOK(FilterItem, this)) // error means we do not want the item
- {
- startitem_failed = true;
- delete(this);
- return;
- }
-
- precache_model(this.model);
- precache_sound(this.item_pickupsound);
-
- if(q3compat && !this.team)
- {
- string t = GetField_fullspawndata(this, "team", false);
- // bones_was_here: this hack is cheaper than changing to a .string strcmp()
- if(t) this.team = crc16(false, t);
- }
+ this.mdl = this.model ? this.model : strzone(this.item_model_ent.model_str());
+ setmodel(this, MDL_Null); // precision set below
+ // set item size before we spawn a waypoint or droptofloor or MoveOutOfSolid
+ setsize (this, this.pos1 = def.m_mins, this.pos2 = def.m_maxs);
- if (Item_IsLoot(this))
+ if (ITEM_IS_LOOT(this))
{
this.reset = RemoveItem;
+
set_movetype(this, MOVETYPE_TOSS);
+ this.gravity = 1;
- // Savage: remove thrown items after a certain period of time ("garbage collection")
- setthink(this, RemoveItem);
- this.nextthink = time + autocvar_g_items_dropped_lifetime;
+ setthink(this, Item_Think);
+ this.nextthink = time + IT_UPDATE_INTERVAL;
+ this.wait = time + autocvar_g_items_dropped_lifetime;
+
+ this.owner = NULL; // anyone can pick this up, including the player who threw it
+ this.item_spawnshieldtime = time + 0.5; // but not straight away
this.takedamage = DAMAGE_YES;
this.event_damage = Item_Damage;
//this.damagedbycontents = true;
//IL_PUSH(g_damagedbycontents, this);
- if (Item_IsExpiring(this))
+ if (ITEM_IS_EXPIRING(this))
{
// if item is worthless after a timer, have it expire then
this.nextthink = max(this.strength_finished, this.invincible_finished, this.superweapons_finished);
}
+ // most loot items have a bigger horizontal size than a player
+ nudgeoutofsolid(this);
+
// don't drop if in a NODROP zone (such as lava)
traceline(this.origin, this.origin, MOVE_NORMAL, this);
if (trace_dpstartcontents & DPCONTENTS_NODROP)
{
- startitem_failed = true;
delete(this);
return;
}
}
else
{
+ this.reset = Item_Reset;
+
+ // must be done after def.m_iteminit() as that may set ITEM_FLAG_MUTATORBLOCKED
if(!have_pickup_item(this))
{
- startitem_failed = true;
delete(this);
return;
}
+ // must be done before Item_Reset() and after MUTATORBLOCKED check (blocked items may have null func ptrs)
+ if(!this.respawntime) // both need to be set
+ {
+ if (def.m_respawntime)
+ this.respawntime = def.m_respawntime();
+ else
+ LOG_WARNF("Default respawntime for a %s is unavailable from its itemdef", this.classname);
+
+ if (def.m_respawntimejitter)
+ this.respawntimejitter = def.m_respawntimejitter();
+ else
+ LOG_WARNF("Default respawntimejitter for a %s is unavailable from its itemdef", this.classname);
+ }
+
if(this.angles != '0 0 0')
this.SendFlags |= ISF_ANGLES;
- this.reset = this.team ? Item_FindTeam : Item_Reset;
+ if(q3compat)
+ {
+ if (!this.team)
+ {
+ string t = GetField_fullspawndata(this, "team");
+ // bones_was_here: this hack is cheaper than changing to a .string strcmp()
+ if(t) this.team = crc16(false, t);
+ }
+
+ // In Q3 the origin is in the middle of the bbox ("radius" 15), in Xon it's at the bottom
+ // so we need to offset vertically (only for items placed by the mapper).
+ this.origin.z += -15 - this.mins.z;
+ setorigin(this, this.origin);
+ }
+
// it's a level item
if(this.spawnflags & 1)
this.noalign = 1;
// do item filtering according to game mode and other things
if (this.noalign <= 0)
{
- // first nudge it off the floor a little bit to avoid math errors
- setorigin(this, this.origin + '0 0 1');
- // set item size before we spawn a spawnfunc_waypoint
- setsize(this, def.m_mins, def.m_maxs);
- this.SendFlags |= ISF_SIZE;
// note droptofloor returns false if stuck/or would fall too far
if (!this.noalign)
droptofloor(this);
{
// target_give not yet supported; maybe later
print("removed targeted ", this.classname, "\n");
- startitem_failed = true;
delete(this);
return;
}
{
// why not flags & fl_item?
FOREACH_ENTITY_RADIUS(this.origin, 3, it.is_item, {
- LOG_TRACE("XXX Found duplicated item: ", itemname, vtos(this.origin));
+ LOG_TRACE("XXX Found duplicated item: ", def.m_name, vtos(this.origin));
LOG_TRACE(" vs ", it.netname, vtos(it.origin));
error("Mapper sucks.");
});
this.is_item = true;
}
- weaponsInMap |= WepSet_FromWeapon(REGISTRY_GET(Weapons, weaponid));
+ weaponsInMap |= WepSet_FromWeapon(REGISTRY_GET(Weapons, this.weapon));
if ( def.instanceOfPowerup
|| def.instanceOfWeaponPickup
|| (def.instanceOfHealth && def != ITEM_HealthSmall)
|| (def.instanceOfArmor && def != ITEM_ArmorSmall)
- || (itemid & (IT_KEY1 | IT_KEY2))
+ || (def.m_itemid & (IT_KEY1 | IT_KEY2))
)
{
if(!this.target || this.target == "")
}
Item_ItemsTime_SetTime(this, 0);
+
+ this.glowmod = def.m_color;
}
this.bot_pickup = true;
- this.bot_pickupevalfunc = pickupevalfunc;
- this.bot_pickupbasevalue = pickupbasevalue;
- this.mdl = this.model ? this.model : strzone(this.item_model_ent.model_str());
- this.netname = itemname;
+ this.bot_pickupevalfunc = def.m_pickupevalfunc;
+ this.bot_pickupbasevalue = def.m_botvalue;
+ this.netname = def.m_name;
settouch(this, Item_Touch);
- setmodel(this, MDL_Null); // precision set below
//this.effects |= EF_LOWPRECISION;
// support skinned models for powerups
if(!this.skin)
this.skin = def.m_skin;
- setsize (this, this.pos1 = def.m_mins, this.pos2 = def.m_maxs);
-
- this.SendFlags |= ISF_SIZE;
-
if (!(this.spawnflags & 1024)) {
if(def.instanceOfPowerup)
this.ItemStatus |= ITS_ANIMATE1;
this.ItemStatus |= ITS_ANIMATE2;
}
- if(Item_IsLoot(this))
- this.gravity = 1;
- else
- this.glowmod = def.m_color;
-
if(def.instanceOfWeaponPickup)
{
- if (!Item_IsLoot(this)) // if dropped, colormap is already set up nicely
+ if (!ITEM_IS_LOOT(this)) // if dropped, colormap is already set up nicely
this.colormap = 1024; // color shirt=0 pants=0 grey
if (!(this.spawnflags & 1024))
this.ItemStatus |= ITS_ANIMATE1;
this.effects |= EF_NOGUNBOB; // marker for item team search
InitializeEntity(this, Item_FindTeam, INITPRIO_FINDTARGET);
+ this.reset = Item_FindTeam;
}
else
Item_Reset(this);
// call this hook after everything else has been done
if (MUTATOR_CALLHOOK(Item_Spawn, this))
{
- startitem_failed = true;
delete(this);
return;
}
- setItemGroup(this);
-}
-
-void StartItem(entity this, GameItem def)
-{
- def = def.m_spawnfunc_hookreplace(def, this);
-
- if (def.spawnflags & ITEM_FLAG_MUTATORBLOCKED)
- {
- delete(this);
- return; // TODO does not set startitem_failed
- }
+ // we should be sure this item will spawn before loading its assets
+ // CSQC handles model precaching: it may not use this model (eg simple items) and may not have connected yet
+ //precache_model(this.mdl);
+ precache_sound(this.item_pickupsound);
- this.classname = def.m_canonical_spawnfunc;
+ setItemGroup(this);
- _StartItem(
- this,
- this.itemdef = def,
- def.m_respawntime(), // defaultrespawntime
- def.m_respawntimejitter() // defaultrespawntimejitter
- );
+ startitem_failed = false;
}
#define IS_SMALL(def) ((def.instanceOfHealth && def == ITEM_HealthSmall) || (def.instanceOfArmor && def == ITEM_ArmorSmall))
void setItemGroup(entity this)
{
- if(!IS_SMALL(this.itemdef) || Item_IsLoot(this))
+ if(!IS_SMALL(this.itemdef) || ITEM_IS_LOOT(this))
return;
FOREACH_ENTITY_RADIUS(this.origin, 120, (it != this) && IS_SMALL(it.itemdef),
void target_items_use(entity this, entity actor, entity trigger)
{
- if(Item_IsLoot(actor))
+ if(ITEM_IS_LOOT(actor))
{
EXACTTRIGGER_TOUCH(this, trigger);
delete(actor);
EXACTTRIGGER_TOUCH(this, trigger);
}
- IL_EACH(g_items, it.enemy == actor && Item_IsLoot(it),
+ IL_EACH(g_items, it.enemy == actor && ITEM_IS_LOOT(it),
{
delete(it);
});