• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece!🔗 Click here to enter!

[VJass] RecycleUnits

Level 21
Joined
Mar 19, 2009
Messages
444
RecycleUnits

A small library cause I get bored.

Basically: store unit type to make a player earn gold and lumber when it want to recycle this unit through a spell.

Requirements

TimerUtils by Vexorian
SpellEvent by Anitarf

JASS:
library RecycleUnits initializer init needs TimerUtils,SpellEvent// both libraries are available on w3c.net

//****

//This simple library is just a way (between several others) to store the gold and lumber cost of any unit you want to
//I use a hashtable to store the variables. There is no need to use this if you only get 5-10 units stored.
//On the other hand, some maps (like it may be for Tower Defense, or, personnaly, for my old map Stars, you may have hundred units you want to be able to get recycled
//Then, a classic loop to check the unit id, and the gold/lumber stored in integer numbers may be less fast than a hashtable to find the costs
//More, a hashtable with some text macro is really sexier to use :p

//So, basically, the only thing you have to do is to store a unit type, a gold cost and a lumber cost . Not hard uh?

//In order to make this library more complete, I added some options.

//Features
//-Recycle a unit (add gold and lumber to a player) when the unit uses a skill
//-Can display a texttag showing the amount of resources earned to the player only or all playing players
//-Can add random factors to the returned amount of ressources
//-Can add a special effect when the spell is used, instantly or with a duration
//-Can instantly destroy the recycled unit or after a while

//Credits: jk2pach. Since this library is really simple, I do not care if you do not give credits. Really, just enjoy it.

//***

//***Settings***

globals
    //The ability id of the spell triggering the recycle
    private constant integer SPELL_RECYCLE = 'A000'

    //Design

    //Names for gold and lumber (if you want it to be iron, cash etc...)
    private constant string NAME_GOLD = "gold"
    private constant string NAME_LUMBER = "lumber"

    //Colors applied to the gold and the lumber on the texttag
    private constant string COLOR_GOLD = "|cff008040"
    private constant string COLOR_LUMBER = "|cff80FFFF"

    //Special Effect added on the unit when it is recycled
    //Set it to "" if you do no want any effect
    private constant string RECYCLE_FX = "Abilities\\Spells\\Orc\\Voodoo\\VoodooAuraTarget.mdl"
    //The attachement point of the special effect
    private constant string RECYCLE_ATTACHEMENT = "origin"
    //The duration of the special effect. Set it to 0. if it is an instant special effect (without any stand animation)
    private constant real FX_DURATION = 2.

    //Options

    //If you do not want any floating text to show the resources earned
    private constant boolean CREATE_TEXTTAG = true
    //If you want to display the floating text to all players and not only to the owner of the recycled unit
    private constant boolean DISPLAY_TEXTTAG = false

    //Random numbers: set here the variations of the ressources granted when the unit is recycled.
    //For example, if you set the 4 variables to 1., the amount of gold and lumber payed back will be the one you set in variables
    private constant real RANDOM_GOLD_MIN = 0.25
    private constant real RANDOM_GOLD_MAX = 1.
    private constant real RANDOM_LUMBER_MIN = 0.5
    private constant real RANDOM_LUMBER_MAX = 1.

    //The duration of the recycle: if you set it to 0., it will be an instant kill of the unit.
    private constant real RECYCLE_DURATION = 2.

    //Do not edit the following global variables
    private constant string C =  " |r"  //just to set a text to the white color
    private key INDEX_GOLD //Used in the hasthable; a key is a unic constant integer
    private key INDEX_LUMBER
    private hashtable HashT //Our hashtable
endglobals 

    //The following macro is used to store the variables attached to the units (gold and lumber)
    //Why a textmacro? Because it is sexier for small amounts of variables
    //Why a hashtable? Because if you store hundreds units in the recycle system, a classic loop checking the unitId will be a bit slower

    //! textmacro t__RecycleSystem_Init takes UNIT_TYPE , UNIT_GOLD, UNIT_LUMBER 
        call SaveInteger(HashT,$UNIT_TYPE$,INDEX_GOLD,$UNIT_GOLD$)
        call SaveInteger(HashT,$UNIT_TYPE$,INDEX_LUMBER,$UNIT_LUMBER$)
    //! endtextmacro 

    //There, you edit the buildings you want to store into the recycle system
    //The first argument such has 'h001' is the unit Id
    //The second and the third are the gold cost and the lumber cost, such as "250" and "5"
    //Remember you need to surround the variables with ""

    private function SetCostVariables takes nothing returns nothing 
            //! runtextmacro t__RecycleSystem_Init("'h001'","250", "5")
            //! runtextmacro t__RecycleSystem_Init("'h002'","150", "5")
            //! runtextmacro t__RecycleSystem_Init("'h003'","200", "5")
            //! runtextmacro t__RecycleSystem_Init("'h004'","400", "30")
            //! runtextmacro t__RecycleSystem_Init("'h005'","400", "30")
    endfunction


    //***
    //Do not edit anything under this line unless you sure about what you do
    //***


    //A little struct used for special effects with a duration
    //For example, if you set RECYCLE_FX to the Holy Bolt model, then, it is useless to get a timed effect, because
    //this special effect can be created and destroyed instantly.
    //On the contrary, the special effect RECYCLE_FX I give in my example (voodoo aura) is a model with a "stand" animation
    //meaning it needs to get a duration to be shown. There, the effect must be destroyed after a while and not instantly

    private struct str
        effect e 
    endstruct 

    //The function to destroy our special effect when it is timed.

    private function WaitForEffect takes nothing returns nothing 
        local timer t = GetExpiredTimer() //Get the timer
        local str dat = GetTimerData(t) //Retreive the data attached to the timer through the library TimerUtils
            call DestroyEffect(dat.e) //Destroy the effect
            call ReleaseTimer(t) //Recycle the timer through TimerUtils
            call dat.destroy() //Destroy the struct
    endfunction

    //When there is an effect set (RECYCLE_FX not equal to "") and the duration of the effect (RECYCLE_DURATION) is greater than 0.
    //The effect will be destroyed after RECYCLE_DURATION seconds, through a struct and a timer linked to TimerUtils

    private function AddTimedEffectToUnit takes unit whichUnit returns nothing
        local timer t = NewTimer() //Create a timer through TimerUtils
        local str  dat = str.create() //Create the struct
            set dat.e = AddSpecialEffectTarget(RECYCLE_FX,whichUnit,RECYCLE_ATTACHEMENT) //Add the special effect to the unit
            call SetTimerData(t, dat) //Attach the struct to the timer
            call TimerStart (t,RECYCLE_DURATION, false, function WaitForEffect ) //Start the timer
    endfunction

    //The function which creates a texttag if CREATE_TEXTTAG is set to true

    private function AddTextTag takes unit whichUnit,boolean isVisibleForAll, string text returns nothing
        local texttag tag = CreateTextTag()    
            call SetTextTagText(tag, text, 0.025) 
            call SetTextTagPos(tag, GetUnitX(whichUnit) - 10, GetUnitY(whichUnit), 50.)
            call SetTextTagVelocity(tag, 0.0355 * Cos(90.*bj_DEGTORAD), 0.0355 * Sin(90.*bj_DEGTORAD)) 
            call SetTextTagColor(tag, 255, 255, 255,255) 
            call SetTextTagFadepoint(tag,1.5)
            call SetTextTagLifespan(tag, 2.)
            call SetTextTagPermanent(tag, false) 
            if isVisibleForAll == false then
                if GetOwningPlayer(whichUnit)!=GetLocalPlayer() then
                    call SetTextTagVisibility(tag,false) 
                endif 
            endif 
            set tag = null 
    endfunction

    //Just a little function to add gold and lumber on the owner of the recycled unit

    private function SetResource takes player whichPlayer, integer gold, integer lumber returns nothing
        call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_GOLD,GetPlayerState(whichPlayer,PLAYER_STATE_RESOURCE_GOLD)+gold) 
        call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_LUMBER,GetPlayerState(whichPlayer,PLAYER_STATE_RESOURCE_LUMBER)+lumber) 
    endfunction

    //The main function which detects the use of the ability SPELL_RECYCLE

    private function RecycleUnit takes nothing returns nothing
         //casterId check the unit type id of the recycled unit. It will allow us to find the gold and lumber cost of the caster, stored in the hashtable
         //randomGold check the base gold cost of the unit through the hashtable and applies on it the random factors set in globals
         //same with randomLumber
         //SpellEvent.CastingUnit replaces GetTriggerUnit() on a spell event, since we use the SpellEventLibrary
        local integer casterId = GetUnitTypeId(SpellEvent.CastingUnit)
        local integer randomGold = R2I(GetRandomReal(RANDOM_GOLD_MIN,RANDOM_GOLD_MAX)*LoadInteger(HashT,casterId,INDEX_GOLD))
        local integer randomLumber = R2I(GetRandomReal(RANDOM_LUMBER_MIN,RANDOM_LUMBER_MAX)*LoadInteger(HashT,casterId,INDEX_LUMBER))

            call SetResource(GetOwningPlayer(SpellEvent.CastingUnit),randomGold,randomLumber) //Add the ressources to the owner of the recycled unit
            call UnitRemoveAbility(SpellEvent.CastingUnit,SPELL_RECYCLE) //Just in the case where the unit does not get an instant recyclement: we remove the ability to recycle to prevent any abuse

            if CREATE_TEXTTAG == true then //depending on the settings, adds a texttag
                call AddTextTag(SpellEvent.CastingUnit,DISPLAY_TEXTTAG,COLOR_GOLD+I2S(randomGold)+NAME_GOLD+C+" - "+COLOR_LUMBER+I2S(randomLumber)+NAME_LUMBER+C)
            endif

            if RECYCLE_DURATION > 0. then //depending on your setting, the recycled unit is instantly killed or not
                call UnitApplyTimedLife(SpellEvent.CastingUnit,'BTLF',RECYCLE_DURATION)
            else
                call KillUnit(SpellEvent.CastingUnit)
            endif

            if RECYCLE_FX != "" then //if you set any special effect, create one
                if FX_DURATION > 0.  then //if the duration is greater than 0., it will be a timed effect, if not, an instant effect.
                   call AddTimedEffectToUnit(SpellEvent.CastingUnit)
                else
                   call DestroyEffect(AddSpecialEffectTarget(RECYCLE_FX,SpellEvent.CastingUnit,RECYCLE_ATTACHEMENT))
                endif
            endif
    endfunction 

    //The initializer. Nothing special to say.

    private function init takes nothing returns nothing 
            call RegisterSpellCastResponse(SPELL_RECYCLE,RecycleUnit) //Through the library SpellEvent,register the spell
            set HashT = InitHashtable() //initialize the hasthable where we store the units and their ressources cost
            call SetCostVariables()//Initialize the variables you set
    endfunction 

endlibrary
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Let me see if I have this right... whenever a unit is used as an effect, it adds a variant amount of gold to the owning player and it recycles that unit?


For one, I must say you should modularize the whole thing... >.<

For example, there are plenty of libraries for recycling, there are plenty of libraries for effects, and there are even libraries for retrieving gold/lumber costs of units : O (although the last aforementioned libraries needs updates).

When I see a chaotic jumble of features that don't really seem to be related, it makes me, and probably a few others, confused as to the purpose of the library : P. This is the reason why I asked my first question = ).

But I mean, at one point, if it does what I think it does, it'd only be a few lines of JASS code with the other systems to produce the same results >.>.

Those are just my thoughts on it though. I guess we'll see if we're on the same page here momentarily : P.

And your title is pretty misleading too : |...
 
Top