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: 287

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.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      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