System Evolving/Devolving Unit

Nestharus

o-o
Reaction score
84
From Demo 1 of Stacked Fields as that demo was just so awesome ; D.

Getting some major updates to use Unit Indexer

Requires- http://www.thehelper.net/forums/showthread.php?t=151978 (2.1.0.0)

Notes-
I am not making a plain evolution system as they are unsafe with unit indexing systems. Evolution/Devolution systems like this one are safe.


Introduction
Wouldn't it be cool if you had like a peasant and he trained really hard and became a footman? Then he trained hard some more by killing guys or w/e and became a swordsman? Eventually a captain? A knight? A full fledged hero?

What if he screws up or gets lazy and goes from hero back to knight? Maybe he lost too many battles, lost some skills, or w/e else?

This system let's you do that with ease. When a unit changes (up a rank), it's called an evolution. When a unit goes down a rank, it's called a devolution. This system can do both =D.

Try the test map out for yourself. Move the unit around, order it to attack, and etc.

Test Map Command-
pop [num]
Devolves a unit num times.

you can type pop by itself, pop0, pop 1, or even pop 335939 and it'll all work ; D. You can even have a typo like adadsa a apopa 2 and it'll still work >.<. Just need to have the pop somewhere in there ; O.

This is safe with index systems

If you attach a struct to a unit and evolve that unit, the struct will still be on it.

If you evolve a unit, triggers that were registered specifically with it will not run anymore.

If a unit decays/is removed, the struct will still get destroyed, so don't worry =).

Safe Usage
If you have a trigger that runs and you use get(handle) to retrieve the EvolvingUnit index, it is always a good idea to make sure that the index is not 0.

If it is 0, the struct you retrieved is null, meaning your evolving unit no longer exists.

If you don't use get, then make sure the evolving unit (unit) is not null.

Code
JASS:
library EvoDevoUnit

globals
    //only use hash if you plan on having a crap load of units with a crap
    //load of evolutions, like 100 units that each evolve 100 times.
    private constant boolean USE_HASH = false
endglobals

//1.2.0.6
//Description
//  Evolves and Devolves units. Retains all unit data.
////////////////////////////////////////////////////
//EvolveUnit struct API
////////////////////////////////////////////////////
//Fields/Properties
//  readonly unit unit
//          the evolution unit handle
//  readonly integer level
//          current evolution level
//Methods
//  static get(handle h) returns EvolvingUnit
//          used with for handle attachment
//  evolve(integer unitType) returns nothing
//          evolve
//  devolve() returns nothing
//          devolve
//  devolveCount(integer count) returns nothing
//          devolve certain amount of times. If you want to devolve more than once but you don&#039;t want to clear, 
//          use this instead of devolve as it&#039;ll be much faster
//  base() returns nothing
//          devolve  to original
//  create(unit) returns EvolveUnit
//          create new
//  destroy() returns nothing
//          destroy
//  attach(handle) returns nothing
//          attaches instance to handle
    scope sdfidsjfosi
    endscope
    
    private keyword evoCodeDId
    private keyword hashref
    
    private keyword HASH_EvolvingDevolvingUnit
    private struct EvolvingDevolvingUnit extends array
        public unit unit

        static if HASH_EvolvingDevolvingUnit then
            private static key k_unit
            
            public method restore takes hashtable h, integer instance returns nothing
                set unit = LoadUnitHandle(h, instance, k_unit)
            endmethod

            public method archive takes hashtable h, integer instance returns nothing
                if (unit != null) then
                    call SaveUnitHandle(h, instance, k_unit, unit)
                endif
            endmethod
        endif

        public method allocate takes nothing returns nothing
            set unit = null
        endmethod

        public method deallocate takes nothing returns nothing
            //should pretty much just be used for cleaning up handles/structs
            if (unit != null) then
                call RemoveUnit(unit)
            endif
        endmethod
    endstruct
    
    //! runtextmacro MAKE_FIELD_STACK(&quot;EvolvingDevolvingUnit&quot;, &quot;USE_HASH&quot;)
    
    private struct Order extends array
        public integer order
        public widget targetWidget
        public real targetX
        public real targetY
    endstruct
    
    private struct SpawnData extends array
        public static real x
        public static real y
        public static real lifeRatio
        public static real facing
        public static player p
        public static integer i
        public static integer count
        public static integer count2
        public static item array items
        public static real manaRatio
        public static boolean select
        public static real mana
        public static integer userData
        public static boolean useFood
        public static delegate Order orderX
        
        public static method allocate takes unit u, Order ordered returns nothing
            local integer unitId = GetUnitTypeId(u)
            set useFood = GetUnitFoodUsed(u) != 0
            set userData = GetUnitUserData(u)
            set orderX = ordered
            if (GetUnitCurrentOrder(u) != ordered.order) then
                set order = -1
            endif
            set select = IsUnitSelected(u, GetLocalPlayer())
            set x = GetUnitX(u)
            set y = GetUnitY(u)
            set facing = GetUnitFacing(u)
            set p = GetOwningPlayer(u)
            set mana = GetUnitState(u, UNIT_STATE_MANA)
            if (mana != 0) then
                set manaRatio = mana/GetUnitState(u, UNIT_STATE_MAX_MANA)
            else
                set manaRatio = 0
            endif
            set lifeRatio = GetWidgetLife(u)/GetUnitState(u, UNIT_STATE_MAX_LIFE)
            set count = UnitInventorySize(u)
            set i = 0
            loop
                exitwhen i == count
                set items<i> = UnitItemInSlot(u, i)
                if (items<i> != null) then
                    call UnitDropItemSlot(u, items<i>, i)
                endif
                set i = i + 1
            endloop
        endmethod
        
        public static method copy takes unit u, boolean basics returns nothing
            call IssueImmediateOrder(u, &quot;stop&quot;)
            if (basics) then
                call SetUnitX(u, x)
                call SetUnitY(u, y)
                call SetUnitFacingTimed(u, facing, 0)
                call SetUnitOwner(u, p, true)
            endif
            call SetUnitUserData(u, userData)
            call SetUnitUseFood(u, useFood)
            call SelectUnit(u, select)
            call SetWidgetLife(u, GetUnitState(u, UNIT_STATE_MAX_LIFE)*lifeRatio)
            set mana = GetUnitState(u, UNIT_STATE_MANA)
            if (mana != 0) then
                call SetUnitState(u, UNIT_STATE_MANA, mana*manaRatio)
            endif
            set i = 0
            loop
                exitwhen i == count
                if (items<i> != null) then
                    call UnitAddItem(u, items<i>)
                    set items<i> = null
                endif
                set i = i + 1
            endloop
            
            if (order != -1) then
                if (targetWidget != null) then
                    call IssueTargetOrderById(u, order, targetWidget)
                else
                    call IssuePointOrderById(u, order, targetX, targetY)
                endif
            endif
        endmethod
    endstruct

    struct EvolvingUnit extends array
        implement EvolvingDevolvingUnitStack
        
        private static hashtable hashref = InitHashtable()
        private integer tCount
        
        private static boolexpr pointOrder
        private static boolexpr targetOrder
        private trigger trackPointOrder
        private trigger trackTargetOrder
        private integer trackPointOrderId
        private integer trackTargetOrderId
        
        private static real hideX
        private static real hideY
        
        //recycler
        private thistype next
        private thistype previous
        private static timer recycler = CreateTimer()
        private static boolean recycleRunning = false
        
        private static method operator head takes nothing returns thistype
            return 0
        endmethod
        
        public method attach takes handle h returns nothing
            local integer id = GetHandleId(h)
            call SaveInteger(hashref, id, 0, this)
            call SaveInteger(hashref, this, tCount, id)
            set tCount = tCount + 1
        endmethod
        
        public static method get takes handle h returns thistype
            return LoadInteger(hashref, GetHandleId(h), 0)
        endmethod
        
        //hide unit
        public method operator unit takes nothing returns unit
            return EvolvingDevolvingUnit.unit
        endmethod

        private method operator unit= takes unit u returns nothing
            set EvolvingDevolvingUnit.unit = u
        endmethod
        
        public method operator level takes nothing returns integer
            return EvolvingDevolvingUnit.size
        endmethod
        
        public method destroy takes nothing returns nothing
            if (trackPointOrder != null) then //make sure allocated
                call deallocateEvolvingDevolvingUnit() //all you have to do
                
                ////////////////////////////////////////////////////////
                call RemoveSavedInteger(hashref, trackPointOrderId, 0)
                call RemoveSavedInteger(hashref, trackTargetOrderId, 0)
                
                call DestroyTrigger(trackPointOrder)
                call DestroyTrigger(trackTargetOrder)
                
                set Order(this).targetWidget = null
                
                set trackPointOrder = null
                set trackTargetOrder = null
                
                set next.previous = previous
                set previous.next = next
                
                loop
                    exitwhen tCount == 0
                    set tCount = tCount - 1
                    call RemoveSavedInteger(hashref, LoadInteger(hashref, this, tCount), 0)
                endloop
                call FlushChildHashtable(hashref, this)
            endif
        endmethod
        
        private static method runRecycle takes nothing returns nothing
            local thistype this = head.next
            loop
                exitwhen this == 0
                if (unit == null) then
                    call destroy()
                endif
                set this = next
            endloop
            
            if (head.next == 0) then
                set recycleRunning = false
                call PauseTimer(recycler)
            endif
        endmethod
        
        private method recycle takes nothing returns nothing
            set head.next.previous = this
            set next = head.next
            set head.next = this
            set previous = head
            
            if (not recycleRunning) then
                set recycleRunning = true
                call TimerStart(recycler, 2, true, function thistype.runRecycle)
            endif
        endmethod
        
        private static method trackPointOrderX takes nothing returns boolean
            local Order this = get(GetTriggeringTrigger())
            set this.targetWidget = null
            set this.targetX = GetOrderPointX()
            set this.targetY = GetOrderPointY()
            set this.order = GetIssuedOrderId()
            return false
        endmethod
        
        private static method trackTargetOrderX takes nothing returns boolean
            local Order this = get(GetTriggeringTrigger())
            set this.targetWidget = GetOrderTarget()
            set this.order = GetIssuedOrderId()
            return false
        endmethod
        
        private method registerTrigs takes nothing returns nothing
            call TriggerRegisterUnitEvent(trackPointOrder, unit, EVENT_UNIT_ISSUED_POINT_ORDER)
            call TriggerRegisterUnitEvent(trackTargetOrder, unit, EVENT_UNIT_ISSUED_TARGET_ORDER)
        endmethod

        public static method create takes unit u returns thistype
            local thistype this = 0
            if (u != null) then
                set this = allocateEvolvingDevolvingUnit()
                set unit = u
                
                set trackPointOrder = CreateTrigger()
                set trackTargetOrder = CreateTrigger()
                
                set trackPointOrderId = GetHandleId(trackPointOrder)
                set trackTargetOrderId = GetHandleId(trackTargetOrder)
                call SaveInteger(hashref, trackPointOrderId, 0, this)
                call SaveInteger(hashref, trackTargetOrderId, 0, this)
                
                set Order(this).order = -1
                call TriggerAddCondition(trackPointOrder, pointOrder)
                call TriggerAddCondition(trackTargetOrder, targetOrder)
                
                call registerTrigs()
                call recycle()
            endif
            return this
        endmethod
        
        private method startCopy takes nothing returns nothing
            call DisableTrigger(trackPointOrder)
            call DisableTrigger(trackTargetOrder)
            call SpawnData.allocate(unit, this)
            call ShowUnit(unit, false)
            call PauseUnit(unit, true)
            call SetUnitX(unit, hideX)
            call SetUnitY(unit, hideY)
        endmethod
        
        private method finishCopy takes boolean basics returns nothing
            call ShowUnit(unit, true)
            call PauseUnit(unit, false)
            call SpawnData.copy(unit, basics)
            call EnableTrigger(trackPointOrder)
            call EnableTrigger(trackTargetOrder)
        endmethod

        public method devolve takes nothing returns nothing
            if (trackPointOrder != null) then
                if (unit != null) then
                    if (not EvolvingDevolvingUnit.empty) then
                        call startCopy()
                        
                        call EvolvingDevolvingUnit.pop()
                        
                        call finishCopy(true)
                    endif
                else
                    call destroy()
                endif
            endif
        endmethod
        
        public method devolveCount takes integer steps returns nothing
            if (trackPointOrder != null) then
                if (unit != null) then
                    if (steps != 0 and not EvolvingDevolvingUnit.empty) then
                        call startCopy()
                        
                        call EvolvingDevolvingUnit.popCount(steps)
                        
                        call finishCopy(true)
                    endif
                else
                    call destroy()
                endif
            endif
        endmethod
        
        public method evolve takes integer unitType returns nothing
            if (trackPointOrder != null) then
                if (unit != null) then
                    call startCopy()
                    
                    call EvolvingDevolvingUnit.push()
                    set unit = CreateUnit(SpawnData.p, unitType, SpawnData.x, SpawnData.y, SpawnData.facing)
                    
                    call finishCopy(false)
                    call registerTrigs()
                else
                    call destroy()
                endif
            endif
        endmethod

        public method base takes nothing returns nothing
            if (trackPointOrder != null) then
                if (unit != null) then
                    if (not EvolvingDevolvingUnit.empty) then
                        call startCopy()
                        
                        call EvolvingDevolvingUnit.clear()
                        
                        call finishCopy(true)
                    endif
                else
                    call destroy()
                endif
            endif
        endmethod
        
        private static method onInit takes nothing returns nothing
            local rect world = GetWorldBounds()
            set hideX = GetRectMaxX(world)
            set hideY = GetRectMaxY(world)
            call RemoveRect(world)
            set world = null
            
            set pointOrder = Condition(function thistype.trackPointOrderX)
            set targetOrder = Condition(function thistype.trackTargetOrderX)
        endmethod
    endstruct
endlibrary
</i></i></i></i></i></i>


Demo Code
JASS:
//Order the unit around the map so you can see that it is still moving even while evolving/devolving
//type pop to devolve the unit
//watch as its evolution takes longer and longer as the xp required increases

//Commands-
//pop [num]
//  devolve num times. If num isn&#039;t specified, pop once
scope EvoDevoDemonstration
    private scope EvoUnit
        private keyword allocate
        private keyword deallocate
        private keyword evolution
        private keyword super
        
        private module EvoUnit
            private delegate EvolvingUnit un
            private integer levelX
            private integer xpX
            
            public static integer array evolution
            
            public method operator super takes nothing returns EvolvingUnit
                return un
            endmethod
            
            public method operator evoLevel takes nothing returns integer
                return super.level
            endmethod
            
            public method operator canEvolve takes nothing returns boolean
                return evolution[evoLevel+1] != 0
            endmethod
            
            public method operator canDevolve takes nothing returns boolean
                return evoLevel != 0
            endmethod
            
            public method operator level takes nothing returns integer
                return levelX
            endmethod
            
            public method operator xp takes nothing returns integer
                return xpX
            endmethod
            
            public method evolve takes nothing returns nothing
                if (canEvolve) then
                    set levelX = 0
                    set xpX = 0
                    call super.evolve(evolution[evoLevel+1])
                endif
            endmethod
            
            public method evolveCount takes integer steps returns nothing
                set levelX = 0
                set xpX = 0
                loop
                    exitwhen steps == 0 or evolution[evoLevel+1] == 0
                    set steps = steps - 1
                    call super.evolve(evolution[evoLevel+1])
                endloop
            endmethod
            
            public method devolveCount takes integer steps returns nothing
                if (canDevolve) then
                    set levelX = 0
                    set xpX = 0
                    call super.devolveCount(steps)
                endif
            endmethod
            
            public method devolve takes nothing returns nothing
                if (canDevolve) then
                    set levelX = 0
                    set xpX = 0
                    call super.devolve()
                endif
            endmethod
            
            public method base takes nothing returns nothing
                if (canDevolve) then
                    set levelX = 0
                    set xpX = 0
                    call super.base()
                endif
            endmethod
            
            public method operator level= takes integer val returns nothing
                set levelX = val
                set xpX = 0
                if (levelX &gt;= EVO_LEVEL) then
                    call evolve()
                elseif (levelX &lt; 0) then
                    call devolve()
                endif
            endmethod
            
            public method operator xp= takes integer val returns nothing
                set xpX = val
                if (xpX &gt;= evoLevel*EVO_LEVEL) then
                    set level = level + 1
                elseif (xpX &lt; 0) then
                    set level = level - 1
                endif
            endmethod
            
            public static method allocate takes unit u returns thistype
                local thistype this = EvolvingUnit.create(u)
                set un = this
                return this
            endmethod
            
            public method deallocate takes nothing returns nothing
                call super.destroy()
            endmethod
        endmodule
        
        struct HumanSoldier extends array
            private static constant real LEVEL_MULTIPLIER = 2
            private static constant integer EVO_LEVEL = 1
            implement EvoUnit
            
            public static method create takes player p, real x, real y, real facing returns thistype
                return allocate(CreateUnit(p, thistype.evolution[0], x, y, facing))
            endmethod
            
            public method destroy takes nothing returns nothing
                call deallocate()
            endmethod
            
            private static method onInit takes nothing returns nothing
                set evolution[0] = &#039;hpea&#039;
                set evolution[1] = &#039;hmil&#039;
                set evolution[2] = &#039;hfoo&#039;
                set evolution[3] = &#039;hcth&#039;
                set evolution[4] = &#039;hkni&#039;
            endmethod
        endstruct
    endscope
    
    private struct Demonstration extends array
        private static constant string POP = &quot;pop&quot;
        private static integer popSize
        
        private static constant player P = Player(0)
        private static constant real X = 2000
        private static constant real Y = 2000
        
        private static constant real TICK = 1
        private static constant integer XP_PER_TICK = 1
        
        private delegate HumanSoldier humanSoldier
        
        private static method addXp takes nothing returns nothing
            local thistype this = HumanSoldier.get(GetExpiredTimer())
            set xp = xp + 1
        endmethod
        
        private static method delevel takes nothing returns boolean
            local thistype this = HumanSoldier.get(GetTriggeringTrigger())
            
            local integer count
            local integer i
            local string char
            local string str = GetEventPlayerChatString()
            local integer length
            local boolean useCount = false
            
            if (str == POP) then
                call devolve()
            elseif (SubString(str, 0, popSize) == POP) then
                set str = SubString(str, popSize, StringLength(str))
                set i = 0
                set count = 0
                set length = StringLength(str)
                
                loop
                    set char = SubString(str, i, i+1)
                    if (char == &quot;0&quot; or char == &quot;1&quot; or char == &quot;2&quot; or char == &quot;3&quot; or char == &quot;4&quot; or char == &quot;5&quot; or char == &quot;6&quot; or char == &quot;7&quot; or char == &quot;8&quot; or char == &quot;9&quot;) then
                        set count = count * 10 + S2I(char)
                        set useCount = true
                    endif
                    set i = i + 1
                    exitwhen i == length
                endloop
                
                if (not useCount) then
                    set count = 1
                endif
                
                if (count &gt;= evoLevel) then
                    call base()
                else
                    call devolveCount(count)
                endif
            endif
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger deTr = CreateTrigger()
            local timer xpT = CreateTimer()
            local thistype this = HumanSoldier.create(P, X, Y, 0)
            set humanSoldier = this
            set popSize = StringLength(POP)
            
            call TriggerRegisterPlayerChatEvent(deTr, Player(0), POP, false)
            call TriggerAddCondition(deTr, Condition(function thistype.delevel))
            
            call attach(deTr)
            call attach(xpT)
            
            call TimerStart(xpT, TICK, true, function thistype.addXp)
        endmethod
    endstruct
    
endscope
 

Attachments

  • test map.zip
    23.3 KB · Views: 284

HeX.16

Isn't Trollin You Right Now
Reaction score
131
Please make a test map? Also make a discription i for one dont know what this system does.
 

Nestharus

o-o
Reaction score
84
uploaded a map...

not sure what to say for the description ; o


Next thing I shall make will be items = ). If you want custom things like crazy evolving/devolving spells (let's say that when u get ur spell to level 5, it evolves or something), I might take requests. Then again, you can just use my Boxed Type Stack lib and do it yourself >: O. Really not that hard if you use that lib ; D.


Oh, something else that is quite interesting... if you are using UserData to attach structs to units, like through AIDS or w/e, your structs will be attached to the evolved units as well. Your triggers, however, will not go.
 

Nestharus

o-o
Reaction score
84
Tested i cant tell you about your code... But the idea is pretty cool.

Well, some maps have evolving heroes or items like that, but not devolving >: D, fuahaha.

Actually, the concept used in this system can be used for inventories and mimicing as well.


Here is another interesting idea... you increase a unit's power as it kills more and decrease back to its normal as it kills less =). You could add like special bonus items to it and what not to do all sorts of rather interesting things.


But thank you ; D.
 

HeX.16

Isn't Trollin You Right Now
Reaction score
131
Well once this gets approved i got a great idea for it. But ill wait for some1 to check the code.
 

Nestharus

o-o
Reaction score
84
My bad =O. Originally I had a trackOrder too, but deleted that. Set all of the triggers everywhere in a frenzy : D.


Thank you =), will fix right now.

I'm also adding a dynamic trigger thingie too.


Yea, I was wondering why my trigger was running the Target method and was returning point coords o-o... guess that explains it huh : D.

edit
Updated/Fixed
 
Reaction score
91
It took me quite a while to figure out what you meant by "evolving" and "devolving" but after seeing your example it became clear... Neat idea, will probably test it if I have free time.
 

Nestharus

o-o
Reaction score
84
Released a new version of this with a much better demo ; D.

The demo command pop now takes a number and will parse your string and etc.. 100% safe too : p.

Added devolveCount so that you can devolve a unit x times (around same speed as clear).


Fixed some possible bugs, made it safer, etc. Removed some variables too with changes to the system this uses =).

I also, ofc, made this faster by tightening up the evolution stat code ; P. Pretty much took everything out of it that I could possibly take out (only handles the data, nothing extra).
 

Jesus4Lyf

Good Idea™
Reaction score
397
Couldn't you just strip this down to a single snippet? Something like:
JASS:
//
        public static method copy takes unit u returns nothing
            call IssueImmediateOrder(u, &quot;stop&quot;)
            call SetUnitUserData(u, userData)
            call SetUnitUseFood(u, useFood)
            call SelectUnit(u, select)
            call SetUnitX(u, x)
            call SetUnitY(u, y)
            call SetUnitFacingTimed(u, facing, 0)
            call SetUnitOwner(u, p, true)
            call SetWidgetLife(u, GetUnitState(u, UNIT_STATE_MAX_LIFE)*lifeRatio)
            set mana = GetUnitState(u, UNIT_STATE_MANA)
            if (mana != 0) then
                call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MAX_MANA)*manaRatio)
            endif
            set i = 0
            loop
                exitwhen i == count
                if (items<i> != null) then
                    call UnitAddItem(u, items<i>)
                    set items<i> = null
                endif
                set i = i + 1
            endloop
            
            if (order != -1) then
                if (targetWidget != null) then
                    call IssueTargetOrderById(u, order, targetWidget)
                else
                    call IssuePointOrderById(u, order, targetX, targetY)
                endif
            endif
        endmethod</i></i></i>

Because this doesn't solve any of the issues with evolving units. And surely could just be replaced by an array of units which you hide/show?

I mean, I suppose my point is, this code is longer than I could have possibly imagined it, and I'm not sure why. I don't even understand the demo code. Your interfaces need some work. :)
 

Nestharus

o-o
Reaction score
84
This supports both evolving and devolving ; (.

oh yea

And surely could just be replaced by an array of units which you hide/show?

that's how this system works dummy ;P, but it uses a stack.
 

Nestharus

o-o
Reaction score
84
It's not that simple... =P

You need to track orders, which is where we get order tracking triggers
You need garbage collection in case the unit no longer exists (not much overhead)
Array needs to be a stack... which requires further allocation, or a whole other struct =) (not many lines ya), but if you want it to support more it should be a single hashtable (which is what this uses).
You need to save values to the hashtable (like unit handle) as you push and restore values from hashtable as you pop

Yea, if it was an array, you wouldn't need that, but again that'd limit your total instances, and if your stuff gets deep enough you could have a lot of instances.


So really, all of the stuff I mentioned above produces a little less than the code I made (including the generated macro code).


Now, I do have a few extra things like the 2 triggers (one node stack trigger and one stack trigger), but I could remove those and just add a register trigger thingie. Originally it was just the stack trigger, but I figured it might be cool to have special effects or w/e for specific evolution units ; P.


Really, this system wasn't much and was rather simple. The code, to me, is actually rather easy to read, especially since all of the stack stuff is done in the background =).



My goal wasn't to make a copy unit thing so that other people could make evolution stacks or w/e...


Please feel free to look through and tell me whatever you think isn't necessary to make the code as tight as possible = ), but I really do think I did a pretty good job.
 

BlackRose

Forum User
Reaction score
239
I think I'll use this:

Unit (I mean't animal / Pokmeon) 1 - Egg
Unit 2 - Dinosaur
Unit 3 - Kingkingyyk3
Unit 4 - Nestharus
Unit 5 - Dead

:)
 

Nestharus

o-o
Reaction score
84
If you don't need the devolve stuff, plain old evolution would be best which is just clone the unit (save the type) and then remove it.

Plain evolution is much less code : P
 

BlackRose

Forum User
Reaction score
239
I plan to have a Dead unit revert back to you. :)

Every single unit in my map will have a ressurect spell, whenever they cast it, they revert to being a Nestharus, and overtime, back into an egg.

(Y)
 

Nestharus

o-o
Reaction score
84
If you want to attach your own structs, use evolution unit struct id rather than handle id of unit = ).



That's what I would do anyways ; P.


This also has a garbage collector, so if your unit ever goes out of scope, the object will be destroyed = ). Garbage collector only runs once every 2 seconds, but anyways ; P.

Also, you should make sure that you have a check to make sure unit is not null in your triggers so that you don't accidentally run stuff.

Total library size (all of the JASS code generated for actual map) is 423 lines.

edit
Had some issues with some misplaced things which caused vjass to auto generate triggers instead of generate unfound errors. Got rid of all vjass generated triggers, haha ; D, so the thing should actually run fast now : p.

The thing this uses, Typed Boxed Stack, also had some problems like that = ), so I fixed that up too : P.

edit
Tightened up code more o-o... made a much cooler demo : D (same demo but cooler organization, haha).

Changed a couple of features around and added a new method ;o.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top