• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Standard Dummy Recycler [v1.1b] by baassee

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Like
Reactions: Prince.Zero
I found this lurking around in my creations map, a little bit unpolished but yet useful for users who don't want to recreate their dummies over and over and over again.

Remade it from scratch and here we go, a standard dummy recycler. XeCast as an inspiration but this dont have any cast stuff. You just call function, get the dummy, do whatever you want with it and recycle. Contains 5 functions, 4 to create dummy, 1 to recycle.

It's basic 2 create functions and 2 functions that got an auto recycle mechanism using timers, that's why TimerUtils is required.

This might be useful to someone. Contains proper instructions inside the JASS tag and also a GUI example for GUI users using udg globals.

Please give credit if you use this to me for the dummyrecycle library and Vexorian for TimerUtils.

Link to TimerUtils

The test map is made by -bzk-, I'm allowed to use this as long as I credit him so credit goes to him for the test map. Found in simple spell pack.

Enjoy.

JASS:
library DummyRecycler requires TimerUtils
//
//
//
//      *Dummyrecycler v1.1b*
//          by baassee
//
//      *Requirments*
//
//          TimerUtils by Vexorian
//
//      *Credits*
//
//          To Vexorian for TimerUtils
//1         watermelon_1234 for helping me alot with this!
//
//      *Changelog*
//
//          v1.0 Release
//
//          v1.1 -Fixed debug infront of debug messages.
//               -Added a check to check
//                if the user have boundsentinel or not, if not, the system will
//                create it's own kinda boundsentinel.
//               -Added two more functions which are provided to help the GUI
//                users even more. One is normal newdummy but takes location loc
//                and the second is the same but with auto recycling.
//
//          v1.1b -Now the recycle struct is private. Special thanks goes to watermelon_1234
//                 for helping me with this.
//
//      *Standard information*
//
//          This is just a standard dummy recycler with a limit of 8191 dummies.
//          Always remember to recycle the dummies after you used them and
//          NOT apply timed life to them or kill/remove them. Then the recycler
//          will just continue to create units and that is not what this library
//          is created for. It uses TimerUtils for a few functions, the auto
//          recycling functions. All dummies are created for a player and not
//          for player(15). If you want to do that, use NewDummy function and set
//          the player to player(15).
//
//          Please give proper credit to me for this library and vexorian for
//          TimerUtils. Do not distrubate this to other maps without permission.
//
//      *Functions provided by this library*
//
//          function NewDummy takes player owner, real x, real y returns unit
//              gets a new dummy from the system for owner, spawned at coord (x,y)
//
//          function RecycleDummy takes unit u returns nothing
//              recycles dummy u and moves it to STORAGE(X,Y) if MOVE == true
//              Warning, you can't recycle units that isn't the dummy unittype
//
//          function NewDummyEx takes unit caster returns unit
//              gets a dummy created at the position of the triggering unit
//
//          function NewDummyLoc takes player owner, location loc returns unit
//              just like NewDummy but this takes a loc, easier for GUI users
//              who don't want the dummy to be created at the casters coordinates
//
//          function NewDummyAuto takes player owner, real x, real y, real time returns unit
//              just like NewDummy function but this auto recycles the dummy after set time
//
//          function NewDummyExAuto takes unit caster, real time returns unit
//              just like NewDummyAuto but this is made from the NewDummyEx function.
//
//          function NewDummyLocAuto takes player owner, location loc, real time returns unit
//              just like NewDummyLoc but this have the auto recycle function
//
//
//
//      *Exmaples*
//
//          These below are just JASS examples, check the example category if you
//          are a GUI user :D
//
//
//          local unit u = NewDummy(Player(15), 0., 0.)
//          call RecycleDummy(u)
//              Creates a dummy for player(15) at coordinates (0,0)
//
//          local unit u = NewDummyEx(GetTriggerUnit())
//          call RecycleDummy(u)
//              Creates a dummy for the owner of GetTriggerUnit() and on the same spot
//
//          local real x = GetUnitX(GetTriggerUnit())
//          local real y = GetUnitY(GetTriggerUnit())
//          local unit u = NewDummyAuto(GetOwningPlayer(GetTriggerUnit()), x, y, 1.)
//              Creates a dummy for the owner of GetTriggerUnit() and recycles it after 1 second.
//
//          local unit u = NewDummyExAuto(GetTriggerUnit(), 5.)
//              Creates a dumym for the owner of GetTriggerUnit() and recycles after 5 seconds.
//
//      *How to import*
//
//          Copy the dummy unit to your map or make your own dummy unit, preffered with
//          a dummy model such as the xe dummy or others. Make sure the dummy have locust.
//
//          If you don't have timerutils then copy the whole category to your map else
//          you can just copy this trigger.
//
//          Set up stuff as you want to such as store coordinates and remember to set the
//          dummy rawcode.
//
//          Credit baassee and you are good to go!
//
//
//
//      *SETUP PART*
    globals
//
//      The counter variable, don't touch.
//
            private integer N                   = 0
//
//      The Rawcode of the dummy that will be used by this system.
//      To get rawcodes, select the dummy inside the object editor
//      and press ctrl + d and the raw code will show up instead
//      of the name.
//
            private constant integer RAWCODE    = 'h006'
//
//      A boolean to check if the dummies should be moved to the
//      storage spot or just remain where they are.
//
            private constant boolean MOVE       = true
//
//      If the boolean above is true, enter the x coordinate
//      here.
//
            private constant real STOREX        = 0.
//
//      If the boolean MOVE is true, enter the y
//      coordinate here.
//
            private constant real STOREY        = 0.
//
//      Dummy global that will be used. Don't touch.
//
            private unit array DUMMY
            
//
//      The setup continues below, just read the comments.
//
    endglobals
    
//
//      Here it checks if you have the library BoundSentinel,
//      if you have, you won't need this protect stuff.
//
    
    static if not LIBRARY_BoundSentinel then
        globals
        
//
//      Sets the reals of the map. You can change
//      the region if you want to, but it shouldn't be
//      necessary as you set the storage coordinates
//      by yourself
//
        
            private constant real MINX          = GetRectMinX(bj_mapInitialPlayableArea)
            private constant real MAXX          = GetRectMaxX(bj_mapInitialPlayableArea)
            private constant real MINY          = GetRectMinY(bj_mapInitialPlayableArea)
            private constant real MAXY          = GetRectMaxY(bj_mapInitialPlayableArea)
        
        endglobals
    endif
//
//      *END OF SETUP*
//
//
//      *Recycle function below*
//
    
    function RecycleDummy takes unit u returns nothing
        // just to check the limit, I dont think someone that use this proper
        // will reach this but to protect the users from themselves.
        if N != 8191 then
            if u != null and GetUnitTypeId(u) == RAWCODE then
                // here I set the color to false cause it's not needed
                // as they wont be used by any player until called again.
                call SetUnitOwner(u, Player(15), false)
                call PauseUnit(u, true)
                set N = N + 1
                set DUMMY[N] = u
                if MOVE == true then
                // checks for boundsentinel so I don't have to do my own check
                // because I'll know it will be safe with boundsentinel
                    static if LIBRARY_BoundSentinel then
                    // moves units if you have boundsentinel
                        call SetUnitX(u, STOREX)
                        call SetUnitY(u, STOREY)
                    else // if you dont have boundsentinel, we do our own check
                        if (MINX <= STOREX) and (STOREX <= MAXX) and (MINY <= STOREY) and  (STOREY <= MAXY) then
                            call SetUnitX(u, STOREX)
                            call SetUnitY(u, STOREY)
                            else
                                // announcing that the user have made it wrong and have to re-do it.
                                debug call BJDebugMsg("DUMMYRECYCLER - The map doesn't contain the coordinates you've set, please change them.")
                        endif
                    endif
                endif
            else 
            // just a debug message to show the user what he did wrong with recycling.
                debug call BJDebugMsg("DUMMYRECYCLER - Tried to recycle a nulled unit or a not-dummy type unit.")
            endif
        else
        // a announce that a user have used way to many dummies.
            debug call BJDebugMsg("DUMMYRECYCLER - You've reached the max number of dummies, please use dummies properly.")
            // doing as vexorian does, explode the unit
            call ExplodeUnitBJ(u)
        endif
    endfunction
    
//
//      A normal struct with timers that is used for the autorecycle functions.
//          NOW a private struct, will look weird having it between the functions but it will
//          only work that way. Special thanks to watermelon_1234 for helping me with this.
//
    private struct recycler
        
        unit    u
        
        static method start takes unit u, real time returns thistype
            local thistype this = thistype.allocate()
            local timer t = NewTimer()
            set .u = u
            call SetTimerData(t, this)
            call TimerStart(t, time, false, function thistype.recycle)
        
            return this
        endmethod
        
        static method recycle takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            call RecycleDummy(.u)
            call ReleaseTimer(GetExpiredTimer())
            call .destroy()
        endmethod
    endstruct
    
    //
    //      The rest of the functions!
    //
    
    function NewDummy takes player owner, real x, real y returns unit
        if N == 0 then
            return CreateUnit(owner, RAWCODE, x, y, 0.)
        endif
        call PauseUnit(DUMMY[N], false)
        // yeah I don't know why I set the color to true but someone might use it.
        call SetUnitOwner(DUMMY[N], owner, true)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
    
    function NewDummyEx takes unit caster returns unit
        local real x = GetUnitX(caster)
        local real y = GetUnitY(caster)
        if N == 0 then
            return CreateUnit(GetOwningPlayer(caster), RAWCODE, x, y, 0.)
        endif
        call PauseUnit(DUMMY[N], false)
        // yeah I don't know why I set the color to true but someone might use it.
        call SetUnitOwner(DUMMY[N], GetOwningPlayer(caster), true)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
    
    function NewDummyLoc takes player owner, location loc returns unit
        local real x = GetLocationX(loc)
        local real y = GetLocationY(loc)
        if N == 0 then
            return CreateUnit(owner, RAWCODE, x, y, 0.)
        endif
        call PauseUnit(DUMMY[N], false)
        call SetUnitOwner(DUMMY[N], owner, true)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
    
    function NewDummyAuto takes player owner, real x, real y, real time returns unit
        local unit u
        if N == 0 then
            set u = CreateUnit(owner, RAWCODE, x, y, 0.)
            call recycler.start(u, time)
            return u
        endif
        call PauseUnit(DUMMY[N], false)
        // yeah I don't know why I set the color to true but someone might use it.
        call SetUnitOwner(DUMMY[N], owner, true)
        call recycler.start(DUMMY[N], time)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
    
    function NewDummyExAuto takes unit caster, real time returns unit
        local unit u
        local real x = GetUnitX(caster)
        local real y = GetUnitY(caster)
        if N == 0 then
            set u = CreateUnit(GetOwningPlayer(caster), RAWCODE, x, y, 0.)
            call recycler.start(u, time)
            return u
        endif
        call PauseUnit(DUMMY[N], false)
        // yeah I don't know why I set the color to true but someone might use it.
        call SetUnitOwner(DUMMY[N], GetOwningPlayer(caster), true)
        call recycler.start(DUMMY[N], time)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
    
    function NewDummyLocAuto takes player owner, location loc, real time returns unit
        local unit u
        local real x = GetLocationX(loc)
        local real y = GetLocationY(loc)
        if N == 0 then
            set u = CreateUnit(owner, RAWCODE, x, y, 0.)
            call recycler.start(u, time)
            return u
        endif
        call PauseUnit(DUMMY[N], false)
        call SetUnitOwner(DUMMY[N], owner, true)
        call recycler.start(DUMMY[N], time)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
endlibrary


v1.0 - Release

v1.1 -
  • Fixed debug infront of debug messages.
  • Added a check to check if the user have boundsentinel or not, if not, the system will create it's own kinda boundsentinel.
  • Added two more functions which are provided to help the GUI users even more. One is normal newdummy but takes location loc and the second is the same but with auto recycling.
v1.1b - Now struct is private. The code is a little messier but it's private now. Special thanks to watermelon_1234


Keywords:
standard, dummy, recycler, gui, friendly, vjass, baassee
Contents

Dummy Recycler v1.1b (Map)

Reviews
16:56, 1st Mar 2011 Bribe: The vanilla JASS one you built is way better than this. I advise just keeping with the vanilla JASS version. Rejected. Let me know if you want to submit an updated version - you should submit it to the JASS...

Moderator

M

Moderator

16:56, 1st Mar 2011
Bribe:

The vanilla JASS one you built is way better than this. I advise just keeping with the vanilla JASS version.

Rejected. Let me know if you want to submit an updated version - you should submit it to the JASS Submissions then, not the Spells section.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
when I am recycling dummys for massive missile spam or something I have got the problem that the old special effect of a dummy takes a few seconds to be destroyed properly so I would recommend some kind of delay between recycling and being able to use the dummy again
(something like RecycleDummyEx( unit u, real duration ))

I also made something to recycle and create different unittypes so I did not have to mess with creating and destroying special effects again and again(which leaks)
might be an option for you, too
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
when I am recycling dummys for massive missile spam or something I have got the problem that the old special effect of a dummy takes a few seconds to be destroyed properly so I would recommend some kind of delay between recycling and being able to use the dummy again
(something like RecycleDummyEx( unit u, real duration ))

I also made something to recycle and create different unittypes so I did not have to mess with creating and destroying special effects again and again(which leaks)
might be an option for you, too

Use the NewDummyExAuto or NewDummyAuto functions for automatic destruction, there you can add your delay :D

Didnt get the second part :$

thanks for posting :)

the system is simple and great
4/5
vote for approval
+rep :p

-------
though i would not recommend using this for projectile dummies -_-

Thank you very much :)

edit:

nah it's meant for casting dummies or special effects at first
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
Use the NewDummyExAuto or NewDummyAuto functions for automatic destruction, there you can add your delay:D

I don't know much about jass but for me it looks more like this what you are doing:

1. new dummy
2. wait
3. recycle dummy instantly

but what I am talking about is this:

1. new dummy
2. recycle dummy
3. wait (dummy can't be allocated again during that time)
4. dummy can be used again

something like this:

JASS:
function RecycleDummy takes unit u, real time returns nothing
    call ShowUnit(u, false)
    //some other actions
    call waitforgotthefunctionname(time)
    add dummy to array again
endfunction
with timers or anything that does not interupt like wait

Didnt get the second part :$

NewDummy takes unittype ut
so I won't have to create new special effects every time I want one
I can just play the units' death animation instead of leaking memory because blizzards destroy-special-effect function sucks
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
Yes it functions as that.

Why dont you want the dummy allocated again? If you add the delay part the special effects will end before anyone will use it again. But I'll consider your option, then I can use my struct a little bit more :D

So you want this to use multiple dummies? Then the recycling part have to keep on track of every unit type you load. But I'll probably add this too if possible :D

Thanks again.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Oh wow, I was trying to make a system like this in the morning. XD

Anyway... short review:

  • I suggest having a static if to check if BoundSentinel is there. If it's not, then do your own safety check.
  • Is there something better about doing not IsUnitType(u, ConvertUnitType(RAWCODE)) than GetUnitTypeId(u) != RAWCODE ?
  • You should use the debug keyword in front of debug messages.
  • I'm not entirely sure about this, but isn't u leaking in both NewDummyAuto and NewDummyAutoEx? You could get rid of that leak by using a global like bj_lastCreatedUnit
  • Do you intend to have recycler "public" like that? In other words, do you want the user to be able to access that struct? If you do, you should put a short documentation on that.
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
Oh wow, I was trying to make a system like this in the morning. XD

Anyway... short review:

  • I suggest having a static if to check if BoundSentinel is there. If it's not, then do your own safety check.
  • Is there something better about doing not IsUnitType(u, ConvertUnitType(RAWCODE)) than GetUnitTypeId(u) != RAWCODE ?
  • You should use the debug keyword in front of debug messages.
  • I'm not entirely sure about this, but isn't u leaking in both NewDummyAuto and NewDummyAutoEx? You could get rid of that leak by using a global like bj_lastCreatedUnit
  • Do you intend to have recycler "public" like that? In other words, do you want the user to be able to access that struct? If you do, you should put a short documentation on that.

1. Alright I'll add that :D Forgot about that actually.

2. Oh I didn't knew that one, thought there was something better like yours but couldn't find it.

3. I wasn't sure about this either, I'll add it.

3. What am I leaking :O

4. Oh I thought you couldn't access private structs with outside functions, quick fix. Yes I want it private, it's not a big deal to use for others :D

Thanks alot !

Why not just have one dummy caster per map =)?

I alrdy know that one, it isn't good enough. Instant casts isn't enough by other words. Easy stuff that can screw up is for an example Fan of Knives. It wont even show effect even if it's instant.
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
I thought units, reals, integers, booleans etc. Didn't have handles that needed to be destroyed and nulled :O

But as you say maybe it's not good to null it, maybe someone uses it and it fucks up for them :D Thanks!

But how do I do with the struct, can't make it private :(
 
Level 15
Joined
Jul 6, 2009
Messages
889
A problem with using only one dummy caster is that it can't support spells that aren't instantly cast.

Oh =( But your doing something wrong if you need to use a dummy caster to cast non-instant spells =(

=)

I alrdy know that one, it isn't good enough. Instant casts isn't enough by other words. Easy stuff that can screw up is for an example Fan of Knives. It wont even show effect even if it's instant.

=) Ok =) Continue on =)
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Move the struct below the function RecycleDummy but just above your Auto functions.
JASS:
library DummyRecycler requires TimerUtils
//
//
//
//      *Dummyrecycler v1.1*
//          by baassee
//
//      *Requirments*
//
//          TimerUtils by Vexorian
//
//      *Credits*
//
//          To Vexorian for TimerUtils
//
//      *Changelog*
//
//          v1.0 Release
//
//          v1.1 -Fixed debug infront of debug messages.
//               -Added a check to check
//                if the user have boundsentinel or not, if not, the system will
//                create it's own kinda boundsentinel.
//               -Added two more functions which are provided to help the GUI
//                users even more. One is normal newdummy but takes location loc
//                and the second is the same but with auto recycling.
//
//      *Standard information*
//
//          This is just a standard dummy recycler with a limit of 8191 dummies.
//          Always remember to recycle the dummies after you used them and
//          NOT apply timed life to them or kill/remove them. Then the recycler
//          will just continue to create units and that is not what this library
//          is created for. It uses TimerUtils for a few functions, the auto
//          recycling functions. All dummies are created for a player and not
//          for player(15). If you want to do that, use NewDummy function and set
//          the player to player(15).
//
//          Please give proper credit to me for this library and vexorian for
//          TimerUtils. Do not distrubate this to other maps without permission.
//
//      *Functions provided by this library*
//
//          function NewDummy takes player owner, real x, real y returns unit
//              gets a new dummy from the system for owner, spawned at coord (x,y)
//
//          function RecycleDummy takes unit u returns nothing
//              recycles dummy u and moves it to STORAGE(X,Y) if MOVE == true
//              Warning, you can't recycle units that isn't the dummy unittype
//
//          function NewDummyEx takes unit caster returns unit
//              gets a dummy created at the position of the triggering unit
//
//          function NewDummyLoc takes player owner, location loc returns unit
//              just like NewDummy but this takes a loc, easier for GUI users
//              who don't want the dummy to be created at the casters coordinates
//
//          function NewDummyAuto takes player owner, real x, real y, real time returns unit
//              just like NewDummy function but this auto recycles the dummy after set time
//
//          function NewDummyExAuto takes unit caster, real time returns unit
//              just like NewDummyAuto but this is made from the NewDummyEx function.
//
//          function NewDummyLocAuto takes player owner, location loc, real time returns unit
//              just like NewDummyLoc but this have the auto recycle function
//
//
//
//      *Exmaples*
//
//          These below are just JASS examples, check the example category if you
//          are a GUI user :D
//
//
//          local unit u = NewDummy(Player(15), 0., 0.)
//          call RecycleDummy(u)
//              Creates a dummy for player(15) at coordinates (0,0)
//
//          local unit u = NewDummyEx(GetTriggerUnit())
//          call RecycleDummy(u)
//              Creates a dummy for the owner of GetTriggerUnit() and on the same spot
//
//          local real x = GetUnitX(GetTriggerUnit())
//          local real y = GetUnitY(GetTriggerUnit())
//          local unit u = NewDummyAuto(GetOwningPlayer(GetTriggerUnit()), x, y, 1.)
//              Creates a dummy for the owner of GetTriggerUnit() and recycles it after 1 second.
//
//          local unit u = NewDummyExAuto(GetTriggerUnit(), 5.)
//              Creates a dumym for the owner of GetTriggerUnit() and recycles after 5 seconds.
//
//      *How to import*
//
//          Copy the dummy unit to your map or make your own dummy unit, preffered with
//          a dummy model such as the xe dummy or others. Make sure the dummy have locust.
//
//          If you don't have timerutils then copy the whole category to your map else
//          you can just copy this trigger.
//
//          Set up stuff as you want to such as store coordinates and remember to set the
//          dummy rawcode.
//
//          Credit baassee and you are good to go!
//
//
//
//      *SETUP PART*
    globals
//
//      The counter variable, don't touch.
//
            private integer N                   = 0
//
//      The Rawcode of the dummy that will be used by this system.
//      To get rawcodes, select the dummy inside the object editor
//      and press ctrl + d and the raw code will show up instead
//      of the name.
//
            private constant integer RAWCODE    = 'h006'
//
//      A boolean to check if the dummies should be moved to the
//      storage spot or just remain where they are.
//
            private constant boolean MOVE       = true
//
//      If the boolean above is true, enter the x coordinate
//      here.
//
            private constant real STOREX        = 0.
//
//      If the boolean MOVE is true, enter the y
//      coordinate here.
//
            private constant real STOREY        = 0.
//
//      Dummy global that will be used. Don't touch.
//
            private unit array DUMMY
            
//
//      The setup continues below, just read the comments.
//
    endglobals
    
//
//      Here it checks if you have the library BoundSentinel,
//      if you have, you won't need this protect stuff.
//
    
    static if not LIBRARY_BoundSentinel then
        globals
        
//
//      Sets the reals of the map. You can change
//      the region if you want to, but it shouldn't be
//      necessary as you set the storage coordinates
//      by yourself
//
        
            private constant real MINX          = GetRectMinX(bj_mapInitialPlayableArea)
            private constant real MAXX          = GetRectMaxX(bj_mapInitialPlayableArea)
            private constant real MINY          = GetRectMinY(bj_mapInitialPlayableArea)
            private constant real MAXY          = GetRectMaxY(bj_mapInitialPlayableArea)
        
        endglobals
    endif
//
//      *END OF SETUP*
//
//
//      *Functions used below*
//
    
    function RecycleDummy takes unit u returns nothing
        // just to check the limit, I dont think someone that use this proper
        // will reach this but to protect the users from themselves.
        if N != 8191 then
            if u != null and GetUnitTypeId(u) == RAWCODE then
                // here I set the color to false cause it's not needed
                // as they wont be used by any player until called again.
                call SetUnitOwner(u, Player(15), false)
                call PauseUnit(u, true)
                set N = N + 1
                set DUMMY[N] = u
                if MOVE == true then
                // checks for boundsentinel so I don't have to do my own check
                // because I'll know it will be safe with boundsentinel
                    static if LIBRARY_BoundSentinel then
                    // moves units if you have boundsentinel
                        call SetUnitX(u, STOREX)
                        call SetUnitY(u, STOREY)
                    else // if you dont have boundsentinel, we do our own check
                        if (MINX <= STOREX) and (STOREX <= MAXX) and (MINY <= STOREY) and  (STOREY <= MAXY) then
                            call SetUnitX(u, STOREX)
                            call SetUnitY(u, STOREY)
                            else
                                // announcing that the user have made it wrong and have to re-do it.
                                debug call BJDebugMsg("DUMMYRECYCLER - The map doesn't contain the coordinates you've set, please change them.")
                        endif
                    endif
                endif
            else 
            // just a debug message to show the user what he did wrong with recycling.
                debug call BJDebugMsg("DUMMYRECYCLER - Tried to recycle a nulled unit or a not-dummy type unit.")
            endif
        else
        // a announce that a user have used way to many dummies.
            debug call BJDebugMsg("DUMMYRECYCLER - You've reached the max number of dummies, please use dummies properly.")
            // doing as vexorian does, explode the unit
            call ExplodeUnitBJ(u)
        endif
    endfunction
    
    //
//      A normal struct with timers that is used for the autorecycle functions.
//
    private struct recycler
        
        unit    u
        
        static method start takes unit u, real time returns thistype
            local thistype this = thistype.allocate()
            local timer t = NewTimer()
            set .u = u
            call SetTimerData(t, this)
            call TimerStart(t, time, false, function thistype.recycle)
        
            return this
        endmethod
        
        static method recycle takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            call RecycleDummy(.u)
            call ReleaseTimer(GetExpiredTimer())
            call .destroy()
        endmethod
    endstruct
    
    function NewDummy takes player owner, real x, real y returns unit
        if N == 0 then
            return CreateUnit(owner, RAWCODE, x, y, 0.)
        endif
        call PauseUnit(DUMMY[N], false)
        // yeah I don't know why I set the color to true but someone might use it.
        call SetUnitOwner(DUMMY[N], owner, true)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
    
    function NewDummyEx takes unit caster returns unit
        local real x = GetUnitX(caster)
        local real y = GetUnitY(caster)
        if N == 0 then
            return CreateUnit(GetOwningPlayer(caster), RAWCODE, x, y, 0.)
        endif
        call PauseUnit(DUMMY[N], false)
        // yeah I don't know why I set the color to true but someone might use it.
        call SetUnitOwner(DUMMY[N], GetOwningPlayer(caster), true)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
    
    function NewDummyLoc takes player owner, location loc returns unit
        local real x = GetLocationX(loc)
        local real y = GetLocationY(loc)
        if N == 0 then
            return CreateUnit(owner, RAWCODE, x, y, 0.)
        endif
        call PauseUnit(DUMMY[N], false)
        call SetUnitOwner(DUMMY[N], owner, true)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
    
    function NewDummyAuto takes player owner, real x, real y, real time returns unit
        local unit u
        if N == 0 then
            set u = CreateUnit(owner, RAWCODE, x, y, 0.)
            call recycler.start(u, time)
            return u
        endif
        call PauseUnit(DUMMY[N], false)
        // yeah I don't know why I set the color to true but someone might use it.
        call SetUnitOwner(DUMMY[N], owner, true)
        call recycler.start(DUMMY[N], time)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
    
    function NewDummyExAuto takes unit caster, real time returns unit
        local unit u
        local real x = GetUnitX(caster)
        local real y = GetUnitY(caster)
        if N == 0 then
            set u = CreateUnit(GetOwningPlayer(caster), RAWCODE, x, y, 0.)
            call recycler.start(u, time)
            return u
        endif
        call PauseUnit(DUMMY[N], false)
        // yeah I don't know why I set the color to true but someone might use it.
        call SetUnitOwner(DUMMY[N], GetOwningPlayer(caster), true)
        call recycler.start(DUMMY[N], time)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
    
    function NewDummyLocAuto takes player owner, location loc, real time returns unit
        local unit u
        local real x = GetLocationX(loc)
        local real y = GetLocationY(loc)
        if N == 0 then
            set u = CreateUnit(owner, RAWCODE, x, y, 0.)
            call recycler.start(u, time)
            return u
        endif
        call PauseUnit(DUMMY[N], false)
        call SetUnitOwner(DUMMY[N], owner, true)
        call recycler.start(DUMMY[N], time)
        call SetUnitX(DUMMY[N], x)
        call SetUnitY(DUMMY[N], y)
        set N = N - 1
            return DUMMY[N + 1]
    endfunction
endlibrary
;D

It does kind of look ugly that the struct is between the API, but that's the only way it'll work unless you use keyword.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
This thing needs some static if's, a lot, in fact, because you have some constant booleans in there which could really be put to better use.

what's with == true?

Indentation got fouled up in some areas.

MINX <= STOREX) and (STOREX <= MAXX) and (MINY <= STOREY) and (STOREY <= MAXY

That should just come as a disclaimer to the user: don't be dumb enough to put extraneous values in STOREX and STOREY.


NewDummyExAuto and NewDummyLocAuto should just be function wrappers for NewDummyAuto, since they do the exact same thing. Code duplication is never a good thing. NewDummyExAuto is also a bad name as it doesn't imply it takes a unit as an argument.
 
Top