[CODE] Build-Style Toggleable Powerups

Post your example zscripts/ACS scripts/etc here.

[CODE] Build-Style Toggleable Powerups

Postby Mikk- » Wed Jan 13, 2021 10:40 am

I found the need for a not-so-hacky implementation of Build Style toggleable powerups, so I wrote a clean, flexible, ZScript based toggleable powerup system. I felt it would be a nifty resource for those that may want to create their own powerups that work this way.

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 allExpand view
class ToggleableInventory : customInventory
    
{
    // whether the item is toggled "on" or "off"
    bool active;        

    
// 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 time in tics (or negative values for seconds) it takes to regenerate 1 unit, 0 implies no regeneration.
    property DepletePeriod: ActiveTics; int ActiveTics;    
    default
        
{
        // the default depletion period is 1 second.
        ToggleableInventory.DepletePeriod -1;        
        
// the default regeneration period is 3 seconds.
        ToggleableInventory.RegenPeriod -3;                
        
        inventory
.Amount 100;                            
        inventory
.MaxAmount 100;                        
        
+INVENTORY.INVBAR;
        +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(amount < 1)                                    
            
{
            // if the amount is 0, then remove the powerup.
            owner.TakeInventory(type, 1);    
            
            
// turn the active state to false.            
            active = false;        
            
            
// if the item is not to be kept when reaching 0 units, remove it.    
            if(!bKEEPDEPLETED)                            
                DepleteOrDestroy
();
            }
            
        
// Deplete/Regenerate the amount if Age is divided by the DepletionPeriod/RegenPeriod is 0.
        if(active && getAge() % activeTics == 0)        
            amount 
= max(amount - 1, 0);
            
        if
(!active && RegenTics && GetAge() % RegenTics == 0)
            amount = min(amount + 1, maxAmount);
        

        
}
    // 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;                    
        
}                                                
    
     states
        
{
        Use:
            TNT1 A 0
                
{
                // if the amount is < 1 (i.e. fully depleted), don't do anything
                if(invoker.amount < 1)                    
                    return
;
                    
                if
(invoker.active)                        
                    
{
                    // remove the powerup if active... 
                    // these blocks are where you can also play sounds, visual flashes etc.
                    invoker.owner.TakeInventory(invoker.type, 1);
                    }
                else    
                    
{
                    // .. or give the powerup, if inactive.
                    invoker.GiveToggleablePowerup();    
                    
}
                    
                
// toggles the active boolean.
                invoker.active = !invoker.active;        
                
}
            // fail makes sure the item is kept in the inventory.
            fail;                                        
        
} 
    
}


and here are a couple of examples of togglable powerups:
Code: Select allExpand view
// in zscript...
class ToggleableNightvision : ToggleableInventory
    
{
    default
        
{
        ToggleableInventory.Type "PowerLightAmp";
        
        
// the period here is 10 tics, so just under 1/3 of a second.
        ToggleableInventory.DepletePeriod 10;    
        
        
// it will take 2 seconds to regenerate 1 unit of power.        
        ToggleableInventory.RegenPeriod -2;                
        
}
    }
 
// in DECORATE   
actor ToggleableRadsuit : ToggleableInventory
    
{
    ToggleableInventory.Type "PowerIronFeet"
    
    
// the period here is 2 seconds.
    ToggleableInventory.DepletePeriod -2

    
// 0 implies that there is no regeneration.        
    ToggleableInventory.RegenPeriod 0        

    
// clear the INVENTORY.KEEPDEPLETED flag, should you want the powerup to be removed upon depletion.
    -INVENTORY.KEEPDEPLETED                        
    
}
User avatar
Mikk-
yooooooooooo
 
Joined: 30 Jun 2009
Location: Somewhere off Kanagawa
Discord: Mikk0451#3922

Return to Script Library

Who is online

Users browsing this forum: No registered users and 1 guest