Removed all remaining references to AInventory

What remains is the class definition and one single reference that will be scriptified.
This commit is contained in:
Christoph Oelckers 2018-12-04 17:11:36 +01:00
parent cd563cc4db
commit 9348baeeb1
27 changed files with 74 additions and 89 deletions

View File

@ -591,7 +591,6 @@ enum EThingSpecialActivationType
class FDecalBase;
class AInventory;
inline AActor *GetDefaultByName (const char *name)
{
@ -747,10 +746,10 @@ public:
// should ever be overridden by custom classes.
// Uses an item and removes it from the inventory.
bool UseInventory (AInventory *item);
bool UseInventory (AActor *item);
// Tosses an item out of the inventory.
AInventory *DropInventory (AInventory *item, int amt = -1);
AActor *DropInventory (AActor *item, int amt = -1);
// Removes all items from the inventory.
void ClearInventory();
@ -759,15 +758,15 @@ public:
bool CheckLocalView (int playernum) const;
// Finds the first item of a particular type.
AInventory *FindInventory (PClassActor *type, bool subclass=false);
AInventory *FindInventory (FName type, bool subclass = false);
AActor *FindInventory (PClassActor *type, bool subclass=false);
AActor *FindInventory (FName type, bool subclass = false);
template<class T> T *FindInventory ()
{
return static_cast<T *> (FindInventory (RUNTIME_CLASS(T)));
}
// Adds one item of a particular type. Returns NULL if it could not be added.
AInventory *GiveInventoryType (PClassActor *type);
AActor *GiveInventoryType (PClassActor *type);
// Destroys all the inventory the actor is holding.
void DestroyAllInventory ();
@ -1188,7 +1187,7 @@ public:
int validcount;
TObjPtr<AInventory*> Inventory; // [RH] This actor's inventory
TObjPtr<AActor*> Inventory; // [RH] This actor's inventory
uint32_t InventoryID; // A unique ID to keep track of inventory items
uint8_t smokecounter;

View File

@ -2944,8 +2944,8 @@ void AM_drawKeys ()
mpoint_t p;
DAngle angle;
TThinkerIterator<AInventory> it(NAME_Key);
AInventory *key;
TThinkerIterator<AActor> it(NAME_Key);
AActor *key;
while ((key = it.Next()) != NULL)
{

View File

@ -289,7 +289,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
r = pr_botmove();
if (r < 128)
{
TThinkerIterator<AInventory> it (MAX_STATNUM+1, bglobal.firstthing);
TThinkerIterator<AActor> it (NAME_Inventory, MAX_STATNUM+1, bglobal.firstthing);
auto item = it.Next();
if (item != NULL || (item = it.Next()) != NULL)
@ -362,9 +362,7 @@ void DBot::WhatToGet (AActor *item)
if (item->IsKindOf(NAME_Weapon))
{
// FIXME
AInventory *heldWeapon;
heldWeapon = player->mo->FindInventory(item->GetClass());
auto heldWeapon = player->mo->FindInventory(item->GetClass());
if (heldWeapon != NULL)
{
if (!weapgiveammo)
@ -383,7 +381,7 @@ void DBot::WhatToGet (AActor *item)
auto ac = PClass::FindActor(NAME_Ammo);
auto parent = item->GetClass();
while (parent->ParentClass != ac) parent = static_cast<PClassActor*>(parent->ParentClass);
AInventory *holdingammo = player->mo->FindInventory(parent);
AActor *holdingammo = player->mo->FindInventory(parent);
if (holdingammo != NULL && holdingammo->IntVar(NAME_Amount) >= holdingammo->IntVar(NAME_MaxAmount))
{
return;

View File

@ -58,7 +58,7 @@ void C_AimLine(FTranslatedLineTarget *t, bool nonshootable)
void C_PrintInv(AActor *target)
{
AInventory *item;
AActor *item;
int count = 0;
if (target == NULL)

View File

@ -1532,7 +1532,7 @@ static int PatchSprite (int sprNum)
static int PatchAmmo (int ammoNum)
{
PClassActor *ammoType = NULL;
AInventory *defaultAmmo = NULL;
AActor *defaultAmmo = NULL;
int result;
int oldclip;
int dummy;
@ -1545,7 +1545,7 @@ static int PatchAmmo (int ammoNum)
ammoType = AmmoNames[ammoNum];
if (ammoType != NULL)
{
defaultAmmo = (AInventory*)GetDefaultByType (ammoType);
defaultAmmo = GetDefaultByType (ammoType);
if (defaultAmmo != NULL)
{
max = &defaultAmmo->IntVar(NAME_MaxAmount);
@ -1587,7 +1587,7 @@ static int PatchAmmo (int ammoNum)
if (type->IsDescendantOf (ammoType))
{
defaultAmmo = (AInventory *)GetDefaultByType (type);
defaultAmmo = GetDefaultByType (type);
defaultAmmo->IntVar(NAME_MaxAmount) = *max;
defaultAmmo->IntVar(NAME_Amount) = Scale (defaultAmmo->IntVar(NAME_Amount), *per, oldclip);
}
@ -1615,7 +1615,7 @@ static int PatchWeapon (int weapNum)
{
int result;
PClassActor *type = nullptr;
AInventory *info = nullptr;
AActor *info = nullptr;
bool patchedStates = false;
FStateDefinitions statedef;
@ -1624,7 +1624,7 @@ static int PatchWeapon (int weapNum)
type = WeaponNames[weapNum];
if (type != NULL)
{
info = (AInventory*)GetDefaultByType (type);
info = GetDefaultByType (type);
DPrintf (DMSG_SPAMMY, "Weapon %d\n", weapNum);
}
}

View File

@ -2254,7 +2254,7 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
while (item != nullptr)
{
AActor *next = item->Inventory;
IFVIRTUALPTR(item, AInventory, UseAll)
IFVIRTUALPTRNAME(item, NAME_Inventory, UseAll)
{
VMValue param[] = { item, players[player].mo };
VMCall(func, param, 2, nullptr, 0);

View File

@ -228,7 +228,7 @@ enum
// The VM cannot deal with this as an invalid pointer because it performs a read barrier on every object pointer read.
// This doesn't have to point to a valid weapon, though, because WP_NOCHANGE is never dereferenced, but it must point to a valid object
// and the class descriptor just works fine for that.
extern AInventory *WP_NOCHANGE;
extern AActor *WP_NOCHANGE;
#define MAXPLAYERNAME 15
@ -414,8 +414,8 @@ public:
uint8_t spreecount = 0; // [RH] Keep track of killing sprees
uint16_t WeaponState = 0;
AInventory *ReadyWeapon = nullptr;
AInventory *PendingWeapon = nullptr; // WP_NOCHANGE if not changing
AActor *ReadyWeapon = nullptr;
AActor *PendingWeapon = nullptr; // WP_NOCHANGE if not changing
TObjPtr<DPSprite*> psprites = nullptr; // view sprites (gun, etc)
int cheats = 0; // bit flags
@ -440,7 +440,7 @@ public:
PClassActor *MorphedPlayerClass = nullptr; // [MH] (for SBARINFO) class # for this player instance when morphed
int MorphStyle = 0; // which effects to apply for this player instance when morphed
PClassActor *MorphExitFlash = nullptr; // flash to apply when demorphing (cache of value given to MorphPlayer)
TObjPtr<AInventory*> PremorphWeapon = nullptr; // ready weapon before morphing
TObjPtr<AActor*> PremorphWeapon = nullptr; // ready weapon before morphing
int chickenPeck = 0; // chicken peck countdown
int jumpTics = 0; // delay the next jump for a moment
bool onground = 0; // Identifies if this player is on the ground or other object

View File

@ -76,7 +76,7 @@ bool PClass::bVMOperational;
// that does not work anymore. WP_NOCHANGE needs to point to a vaild object to work as intended.
// This Object does not need to be garbage collected, though, but it needs to provide the proper structure so that the
// GC can process it.
AInventory *WP_NOCHANGE;
AActor *WP_NOCHANGE;
DEFINE_GLOBAL(WP_NOCHANGE);
@ -232,7 +232,7 @@ void PClass::StaticInit ()
// WP_NOCHANGE must point to a valid object, although it does not need to be a weapon.
// A simple DObject is enough to give the GC the ability to deal with it, if subjected to it.
WP_NOCHANGE = (AInventory*)Create<DObject>();
WP_NOCHANGE = (AActor*)Create<DObject>();
WP_NOCHANGE->Release();
}

View File

@ -151,6 +151,12 @@ public:
TThinkerIterator (ENamedName subclass, int statnum=MAX_STATNUM+1) : FThinkerIterator(PClass::FindClass(subclass), statnum)
{
}
TThinkerIterator (FName subclass, int statnum, DThinker *prev) : FThinkerIterator(PClass::FindClass(subclass), statnum, prev)
{
}
TThinkerIterator (ENamedName subclass, int statnum, DThinker *prev) : FThinkerIterator(PClass::FindClass(subclass), statnum, prev)
{
}
TThinkerIterator (const char *subclass, int statnum=MAX_STATNUM+1) : FThinkerIterator(PClass::FindClass(subclass), statnum)
{
}

View File

@ -2610,7 +2610,7 @@ void FParser::SF_PlayerSelectedWeapon()
return;
}
players[playernum].PendingWeapon = (AInventory*)players[playernum].mo->FindInventory(ti);
players[playernum].PendingWeapon = players[playernum].mo->FindInventory(ti);
}
t_return.type = svt_int;

View File

@ -484,7 +484,7 @@ CCMD (useflechette)
PClassActor *type = who->FlechetteType;
if (type != NULL)
{
AInventory *item;
AActor *item;
if ( (item = who->FindInventory (type) ))
{
SendItemUse = item;
@ -495,7 +495,7 @@ CCMD (useflechette)
// The default flechette could not be found, or the player had no default. Try all 3 types then.
for (int j = 0; j < 3; ++j)
{
AInventory *item;
AActor *item;
if ( (item = who->FindInventory (bagnames[j])) )
{
SendItemUse = item;

View File

@ -98,7 +98,6 @@ void G_AddViewPitch (int look, bool mouse = false);
// Adds to consoleplayer's viewangle if allowed
void G_AddViewAngle (int yaw, bool mouse = false);
class AInventory;
extern const AActor *SendItemUse, *SendItemDrop;
extern int SendItemDropAmount;

View File

@ -293,7 +293,7 @@ bool FWeaponSlots::LocateWeapon (PClassActor *type, int *const slot, int *const
DEFINE_ACTION_FUNCTION(FWeaponSlots, LocateWeapon)
{
PARAM_SELF_STRUCT_PROLOGUE(FWeaponSlots);
PARAM_CLASS(weap, AInventory);
PARAM_CLASS(weap, AActor);
int slot = 0, index = 0;
bool retv = self->LocateWeapon(weap, &slot, &index);
if (numret >= 1) ret[0].SetInt(retv);

View File

@ -1041,8 +1041,8 @@ public:
if (CPlayer->ReadyWeapon != nullptr)
{
ammo1 = CPlayer->ReadyWeapon->PointerVar<AInventory>(NAME_Ammo1);
ammo2 = CPlayer->ReadyWeapon->PointerVar<AInventory>(NAME_Ammo2);
ammo1 = CPlayer->ReadyWeapon->PointerVar<AActor>(NAME_Ammo1);
ammo2 = CPlayer->ReadyWeapon->PointerVar<AActor>(NAME_Ammo2);
if (ammo1 == nullptr)
{
ammo1 = ammo2;
@ -1473,9 +1473,9 @@ public:
return w == nullptr ? nullptr : (w->PointerVar<PClassActor>(no == 1 ? NAME_AmmoType1 : NAME_AmmoType2));
}
AInventory *ammo1, *ammo2;
AActor *ammo1, *ammo2;
int ammocount1, ammocount2;
AInventory *armor;
AActor *armor;
FImageCollection Images;
unsigned int invBarOffset;
player_t *CPlayer = nullptr;

View File

@ -154,7 +154,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
}
else
{
sprite = ((AInventory *)GetDefaultByType(item))->TextureIDVar(NAME_Icon);
sprite = GetDefaultByType(item)->TextureIDVar(NAME_Icon);
}
image = -1;
}
@ -304,7 +304,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
}
}
protected:
void GetIcon(AInventory *item)
void GetIcon(AActor *item)
{
int apply;
FTextureID icon = FSetTextureID(GetInventoryIcon(item, flags, &apply));

View File

@ -89,7 +89,7 @@ void cht_DoCheat (player_t *player, int cheat)
"PowerTargeter",
};
PClassActor *type;
AInventory *item;
AActor *item;
FString smsg;
const char *msg = "";
char msgbuild[32];

View File

@ -1847,7 +1847,7 @@ int CheckInventory (AActor *activator, const char *type, bool max)
}
else if (info != nullptr && info->IsDescendantOf(NAME_Inventory))
{
return ((AInventory *)GetDefaultByType(info))->IntVar(NAME_MaxAmount);
return GetDefaultByType(info)->IntVar(NAME_MaxAmount);
}
}
return item ? item->IntVar(NAME_Amount) : 0;
@ -6218,7 +6218,7 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
case ACSF_DropInventory:
{
const char *type = FBehavior::StaticLookupString(args[1]);
AInventory *inv;
AActor *inv;
if (type != NULL)
{

View File

@ -4065,7 +4065,7 @@ static bool DoRadiusGive(AActor *self, AActor *thing, PClassActor *item, int amo
if ((flags & RGF_NOSIGHT) || P_CheckSight(thing, self, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
{ // OK to give; target is in direct path, or the monster doesn't care about it being in line of sight.
AInventory *gift = static_cast<AInventory *>(Spawn(item));
auto gift = Spawn(item);
if (gift->IsKindOf(NAME_Health))
{
gift->IntVar(NAME_Amount) *= amount;
@ -4093,7 +4093,7 @@ static bool DoRadiusGive(AActor *self, AActor *thing, PClassActor *item, int amo
DEFINE_ACTION_FUNCTION(AActor, A_RadiusGive)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_CLASS (item, AInventory);
PARAM_CLASS (item, AActor);
PARAM_FLOAT (distance);
PARAM_INT (flags);
PARAM_INT (amount);
@ -4103,7 +4103,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RadiusGive)
PARAM_INT (limit);
// We need a valid item, valid targets, and a valid range
if (item == nullptr || (flags & RGF_MASK) == 0 || !flags || distance <= 0 || mindist >= distance)
if (item == nullptr || (flags & RGF_MASK) == 0 || !flags || distance <= 0 || mindist >= distance || !item->IsDescendantOf(NAME_Inventory))
{
ACTION_RETURN_INT(0);
}

View File

@ -961,7 +961,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
if (takestuff)
{
auto item = static_cast<AInventory *>(Spawn(reply->GiveType));
auto item = Spawn(reply->GiveType);
// Items given here should not count as items!
item->ClearCounters();
if (item->GetClass()->TypeName == NAME_FlameThrower)

View File

@ -3157,21 +3157,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail)
return 0;
}
//---------------------------------------------------------------------------
//
// Modifies the drop amount of this item according to the current skill's
// settings (also called by ADehackedPickup::TryPickup)
//
//---------------------------------------------------------------------------
void ModifyDropAmount(AInventory *inv, int dropamount)
{
IFVIRTUALPTR(inv, AInventory, ModifyDropAmount)
{
VMValue params[] = { inv, dropamount };
VMCall(func, params, 2, nullptr, 0);
}
}
//---------------------------------------------------------------------------
//
// PROC P_DropItem

View File

@ -327,7 +327,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
for (AActor *item = Inventory; item != NULL; )
{
AActor *next = item->Inventory;
IFVIRTUALPTR(item, AInventory, OwnerDied)
IFVIRTUALPTRNAME(item, NAME_Inventory, OwnerDied)
{
VMValue params[1] = { item };
VMCall(func, params, 1, nullptr, 0);

View File

@ -2159,15 +2159,14 @@ FUNC(LS_Radius_Quake)
FUNC(LS_UsePuzzleItem)
// UsePuzzleItem (item, script)
{
AInventory *item;
AActor *item;
if (!it) return false;
// Check player's inventory for puzzle item
auto pitype = PClass::FindActor(NAME_PuzzleItem);
for (item = it->Inventory; item != NULL; item = item->Inventory)
{
if (item->IsKindOf (pitype))
if (item->IsKindOf (NAME_PuzzleItem))
{
if (item->IntVar(NAME_PuzzleItemNumber) == arg0)
{

View File

@ -770,10 +770,10 @@ DEFINE_ACTION_FUNCTION(AActor, SetState)
void AActor::DestroyAllInventory ()
{
AInventory *inv = Inventory;
AActor *inv = Inventory;
if (inv != nullptr)
{
TArray<AInventory *> toDelete;
TArray<AActor *> toDelete;
// Delete the list in a two stage approach.
// This is necessary because an item may destroy another item (e.g. sister weapons)
@ -813,7 +813,7 @@ DEFINE_ACTION_FUNCTION(AActor, DestroyAllInventory)
//
//============================================================================
bool AActor::UseInventory (AInventory *item)
bool AActor::UseInventory (AActor *item)
{
IFVIRTUAL(AActor, UseInventory)
{
@ -834,12 +834,12 @@ bool AActor::UseInventory (AInventory *item)
//
//===========================================================================
AInventory *AActor::DropInventory (AInventory *item, int amt)
AActor *AActor::DropInventory (AActor *item, int amt)
{
IFVM(Actor, DropInventory)
{
VMValue params[] = { this, item, amt };
AInventory *retval = 0;
AActor *retval = 0;
VMReturn ret((void**)&retval);
VMCall(func, params, 3, &ret, 1);
return retval;
@ -853,9 +853,9 @@ AInventory *AActor::DropInventory (AInventory *item, int amt)
//
//============================================================================
AInventory *AActor::FindInventory (PClassActor *type, bool subclass)
AActor *AActor::FindInventory (PClassActor *type, bool subclass)
{
AInventory *item;
AActor *item;
if (type == NULL)
{
@ -881,7 +881,7 @@ AInventory *AActor::FindInventory (PClassActor *type, bool subclass)
return item;
}
AInventory *AActor::FindInventory (FName type, bool subclass)
AActor *AActor::FindInventory (FName type, bool subclass)
{
return FindInventory(PClass::FindActor(type), subclass);
}
@ -889,7 +889,7 @@ AInventory *AActor::FindInventory (FName type, bool subclass)
DEFINE_ACTION_FUNCTION(AActor, FindInventory)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_CLASS(type, AInventory);
PARAM_CLASS(type, AActor);
PARAM_BOOL(subclass);
ACTION_RETURN_OBJECT(self->FindInventory(type, subclass));
}
@ -900,11 +900,11 @@ DEFINE_ACTION_FUNCTION(AActor, FindInventory)
//
//============================================================================
AInventory *AActor::GiveInventoryType (PClassActor *type)
AActor *AActor::GiveInventoryType (PClassActor *type)
{
if (type != nullptr)
{
auto item = static_cast<AInventory *>(Spawn (type));
auto item = Spawn (type);
if (!CallTryPickup (item, this))
{
item->Destroy ();
@ -918,7 +918,7 @@ AInventory *AActor::GiveInventoryType (PClassActor *type)
DEFINE_ACTION_FUNCTION(AActor, GiveInventoryType)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_CLASS(type, AInventory);
PARAM_CLASS(type, AActor);
ACTION_RETURN_OBJECT(self->GiveInventoryType(type));
}
@ -4806,7 +4806,7 @@ void AActor::LevelSpawned ()
tics = 1 + (pr_spawnmapthing() % tics);
}
// [RH] Clear MF_DROPPED flag if the default version doesn't have it set.
// (AInventory::BeginPlay() makes all inventory items spawn with it set.)
// (Inventory.BeginPlay() makes all inventory items spawn with it set.)
if (!(GetDefault()->flags & MF_DROPPED))
{
flags &= ~MF_DROPPED;
@ -7534,7 +7534,7 @@ int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive)
auto inv = Inventory;
while (inv != nullptr)
{
IFVIRTUALPTR(inv, AInventory, ModifyDamage)
IFVIRTUALPTRNAME(inv, NAME_Inventory, ModifyDamage)
{
VMValue params[5] = { (DObject*)inv, damage, int(damagetype), &damage, passive };
VMCall(func, params, 5, nullptr, 0);
@ -8051,7 +8051,7 @@ DEFINE_ACTION_FUNCTION(AActor, ClearInterpolation)
DEFINE_ACTION_FUNCTION(AActor, ApplyDamageFactors)
{
PARAM_PROLOGUE;
PARAM_CLASS(itemcls, AInventory);
PARAM_CLASS(itemcls, AActor);
PARAM_NAME(damagetype);
PARAM_INT(damage);
PARAM_INT(defdamage);

View File

@ -1057,7 +1057,7 @@ void player_t::DestroyPSprites()
//
//------------------------------------------------------------------------------------
void P_SetSafeFlash(AInventory *weapon, player_t *player, FState *flashstate, int index)
void P_SetSafeFlash(AActor *weapon, player_t *player, FState *flashstate, int index)
{
auto wcls = PClass::FindActor(NAME_Weapon);
if (flashstate != nullptr)
@ -1101,7 +1101,7 @@ void P_SetSafeFlash(AInventory *weapon, player_t *player, FState *flashstate, in
DEFINE_ACTION_FUNCTION(_PlayerInfo, SetSafeFlash)
{
PARAM_SELF_STRUCT_PROLOGUE(player_t);
PARAM_OBJECT_NOT_NULL(weapon, AInventory);
PARAM_OBJECT_NOT_NULL(weapon, AActor);
PARAM_POINTER(state, FState);
PARAM_INT(index);
P_SetSafeFlash(weapon, self, state, index);

View File

@ -437,7 +437,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
}
// Has hit ground.
AInventory *ironfeet;
AActor *ironfeet;
// [RH] Apply any customizable damage
if (sector->damageamount > 0)
@ -445,10 +445,9 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
// Allow subclasses. Better would be to implement it as armor and let that reduce
// the damage as part of the normal damage procedure. Unfortunately, I don't have
// different damage types yet, so that's not happening for now.
auto pitype = PClass::FindActor(NAME_PowerIronFeet);
for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory)
{
if (ironfeet->IsKindOf(pitype))
if (ironfeet->IsKindOf(NAME_PowerIronFeet))
break;
}
@ -646,7 +645,7 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType)
if (Terrains[floorType].DamageAmount &&
!(level.time & Terrains[floorType].DamageTimeMask))
{
AInventory *ironfeet = NULL;
AActor *ironfeet = NULL;
if (Terrains[floorType].AllowProtection)
{

View File

@ -2057,7 +2057,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, GetMugshot, GetMugshot)
DEFINE_ACTION_FUNCTION_NATIVE(DBaseStatusBar, GetInventoryIcon, GetInventoryIcon)
{
PARAM_PROLOGUE;
PARAM_OBJECT(item, AInventory);
PARAM_OBJECT(item, AActor);
PARAM_INT(flags);
int applyscale;
FTextureID icon = FSetTextureID(GetInventoryIcon(item, flags, &applyscale));

View File

@ -10,9 +10,9 @@ class Inventory : Actor native
const BLINKTHRESHOLD = (4*32);
const BONUSADD = 6;
native Actor Owner; // Who owns self item? NULL if it's still a pickup.
native int Amount; // Amount of item self instance has
native int MaxAmount; // Max amount of item self instance can have
native Actor Owner; // Who owns this item? NULL if it's still a pickup.
native int Amount; // Amount of item this instance has
native int MaxAmount; // Max amount of item this instance can have
native int InterHubAmount; // Amount of item that can be kept between hubs or levels
native int RespawnTics; // Tics from pickup time to respawn time
native TextureID Icon; // Icon to show on status bar or HUD