To create your own actor inherit from the ToggleableInventory class, set up your properties (type, depletion period & regeneration period, icons etc.) and voila! You can also inherit from the ToggleableInventory class with DECORATE, should you need to!
Code: Select all
class ToggleableInventory : customInventory
{
// whether the item is toggled "on" or "off"
bool active;
// the internal ticker (as opposed to performing expensive modulo operations).
int ticker;
// the type of powerup to toggle.
property Type: Type; class<powerup> type;
// the time in tics (or negative values for seconds) it takes to deplete 1 unit
property RegenPeriod: RegenTics; int RegenTics;
// The sounds to play when [De]Activating the powerup...
property ActivateSound: ActivateSound; sound ActivateSound;
property DeactivateSound: DeactivateSound; sound DeactivateSound;
// ...Or to play when fully depleted.
property DepletedSound: DepletedSound; sound DepletedSound;
// the time in tics (or negative values for seconds) it takes to regenerate 1 unit, 0 implies no regeneration.
property DepletePeriod: ActiveTics; int ActiveTics;
// define the custom flags.
private int ti_Flags;
flagdef CheckFloorRegen: ti_Flags, 0; // only regenerate the powerup if the player is on the ground.
flagdef ActiveOnly: ti_Flags, 1; // powerup can only be activated, not deactivated.
default
{
// the default depletion period is 1 second.
ToggleableInventory.DepletePeriod -1;
// the default regeneration period is 3 seconds.
ToggleableInventory.RegenPeriod -3;
// the sounds to play when certain things happen
ToggleableInventory.ActivateSound "";
ToggleableInventory.DeactivateSound "";
ToggleableInventory.DepletedSound "";
inventory.Amount 100;
inventory.MaxAmount 100;
inventory.interhubamount 100;
+INVENTORY.INVBAR;
// clear this flag on inheriting classes should you wish for the item to be
// destroyed when depleted.
+INVENTORY.KEEPDEPLETED;
}
override void AttachToOwner(actor other)
{
super.AttachToOwner(other);
// if the period is negative, make positive & multiply by ticrate (35 in most cases).
if(ActiveTics < 0)
ActiveTics = (-ActiveTics) * TICRATE;
if(RegenTics < 0)
RegenTics = (-RegenTics) * TICRATE;
}
override void DoEffect()
{
if(active && amount < 1)
{
// if the amount is 0, then remove the powerup.
owner.TakeInventory(type, 1);
// turn the active state to false.
active = false;
// play the "Fully Depleted" sound.
owner.A_StartSound(DepletedSound, CHAN_BODY);
// if the item is not to be kept when reaching 0 units, remove it.
if(!bKEEPDEPLETED)
DepleteOrDestroy();
return;
}
// if for some reason the powerup is no longer in the player's inventory
// while active, deactivate the ToggleableInventory class.
if(active && !owner.CountInv(type))
active = false;
// deplete/regenerate the amount if ticker is equal to the DepletionPeriod/RegenPeriod.
if(active && ++ticker == activeTics)
{
ticker = 0;
amount = max(amount - 1, 0);
return;
}
if(!active && amount < maxAmount && RegenTics && ++ticker == RegenTics)
{
ticker = 0;
// If the +ToggleAbleInventory.CheckFloorRegen flag is enabled, don't perform regen.
// This is to prevent regeneration while falling (good for jetpacks and stuff)
if(bCheckFloorRegen && !owner.player.OnGround)
return;
amount = min(amount + 1, maxAmount);
return;
}
}
// this function simply substiutes GiveInventory to modify the given powerup's duration.
void GiveToggleablePowerup()
{
owner.GiveInventory(type, 1);
// find the powerup in the owner's inventory
let i = PowerUp(owner.FindInventory(type));
// set the duration to around 2 years of real time, (might as well be infinite)
// note: it is set to '0x7FFFFFFD' instead of '0x7FFFFFFF' to work with PowerTimeFreezer properly.
if(i)
i.EffectTics = 0x7FFFFFFD;
}
// these virtual functions can be overridden in inheriting classes
// to add things such as particle effects, sounds and other stuff
// when the powerup is activated or deactivated.
// don't forget to call the super. otherwise it will not play any sounds.
virtual void ActivatePowerup()
{
owner.A_StartSound(ActivateSound, CHAN_BODY);
}
virtual void DeActivatePowerup()
{
owner.A_StartSound(DeactivateSound, CHAN_BODY);
}
states
{
Use:
TNT1 A 0
{
// if there are no units left to consume
// don't activate the powerup.
if(invoker.amount < 1)
return;
if(invoker.active)
{
//if the ACTIVEONLY flag is set, then skip deactivating the powerup.
if(invoker.bActiveOnly)
return;
// remove the powerup if active...
// these blocks are where you can also play sounds, visual flashes etc.
invoker.owner.TakeInventory(invoker.type, 1);
// Perform audio & visual stuff in this function
// (can be overridden)
invoker.DeactivatePowerup();
}
else
{
// Give the powerup as defined in the function.
invoker.GiveToggleablePowerup();
// Perform audio & visual stuff in this function, too.
invoker.ActivatePowerup();
}
// set the ticker to 0 when toggled.
invoker.ticker = 0;
// toggle the state of the powerup.
invoker.active = !invoker.active;
}
fail;
}
}
Code: Select all
// in zscript...
class ToggleableWings : ToggleableInventory
{
default
{
ToggleableInventory.Type "PowerFlight";
ToggleableInventory.DepletePeriod 10;
ToggleableInventory.RegenPeriod -2;
// cannot regenerate power when in the air.
+ToggleableInventory.CHECKFLOORREGEN;
}
// causes an orange flash when activated.
override void ActivatePowerup()
{
super.ActivatePowerup();
owner.A_SetBlend("ff9900", 0.5, 25);
}
}
// in DECORATE
actor ToggleableRadsuit : ToggleableInventory
{
ToggleableInventory.Type "PowerIronFeet"
// the period here is 2 seconds.
ToggleableInventory.DepletePeriod -1
// 0 implies that there is no regeneration.
ToggleableInventory.RegenPeriod -1
ToggleableInventory.ActivateSound "switches/normbutn"
ToggleableInventory.DeactivateSound "switches/exitbutn"
ToggleableInventory.DepletedSound "brain/spit"
// clear the INVENTORY.KEEPDEPLETED flag, should you want the powerup to be removed upon depletion.
-INVENTORY.KEEPDEPLETED
}
}