System Prioritized Unit Appearance (PUA)

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
JASS:
/*
    Prioritized Unit Appearance
        v 1.0.2
            by kingking
    
    ===================
    What does PUA do?
    ===================
    Spell makers often find unit's colour,scale and time scale can be overwritten by other spells.
    Example :
    Unit A has 1.0 of scale.
    Spell A set the unit's scale to 2.0
    Spell B set the unit's scale to 4.5
    The unit now has the scale of 4.5
    
    When spell A is removed, the unit's scale will be set back to 1.0.
    Spell B's scale effect is removed along it.
    
    PUA is aimed to solve that.
    
    ===================
    Working principle :
    ===================
    PUA attaches a list of settings to unit. When the spell is removed, it will check, if the spell
    is at the top of the list. If it is, then PUA will set the setting to lower node. Otherwise,
    the unit will remain on same setting.
    
    ===================
    APIs :
    ===================
    ~ UnitType based.
        SetUnitTypeDefaultScale takes integer unitid, real scalex, real scaley, real scalez
        - If you got the unit type with custom scale, please set.
        
        SetUnitTypeDefaultColour takes integer unitid, integer red, integer green, integer blue, integer alpha
        - If you got the unit type with customer colour, please set.
        
    **** Unit types that are not set with functions above will be assigned to default settings automatically.
    **** It will not work with units that were created before the function is called.
    
    ~ Unit based.
        SetUnitDefaultScale takes unit u, real scalex, real scaley, real scalez
        - Unit's default scale.
        
        SetUnitDefaultColour takes unit u, integer red, integer green, integer blue, integer alpha
        - Unit's default colour.
        
        SetUnitDefaultTimeScale takes unit u, real timescale
        - Unit's default time scale.
    
        AddUnitScale takes unit u, string key, real scalex, real scaley, real scalez
        - Assign scale to unit.
        
        AddUnitColour takes unit u, string key, integer red, integer green, integer blue, integer alpha
        - Assign colour to unit.
        
        AddUnitTimeScale takes unit u, string key, real timescale
        - Assign time scale to unit.
        
        AddUnitScaleForPlayer takes unit u, string key, real scalex, real scaley, real scalez, boolean condition
        - Assign scale to unit.
        
        AddUnitColourForPlayer takes unit u, string key, integer red, integer green, integer blue, integer alpha, boolean condition
        - Assign colour to unit.
        
        AddUnitTimeScaleForPlayer takes unit u, string key, real timescale, boolean condition
        - Assign time scale to unit.
    
        RemoveUnitScale takes unit u, string key
        - Remove assigned scale from unit.
        
        RemoveUnitColour takes unit u, string key
        - Remove assigned colour from unit.
        
        RemoveUnitTimeScale takes unit u, string key
        - Remove assigned time scale from unit.
        
    ****The key parameter must be same when assigning and removing the setting from unit, otherwise, it will not work.
    ****It is ideal to put spell's name into the key paramater.
    
    ===================
    Known limitation :
    ===================
    ~ PUA will not work in onInit method in struct.
    
    ===================
    Requirements :
    ===================
    AIDS, by Jesus4Lyf
    Latest jasshelper, to compile the code.
    
*/

library PUA requires AIDS

    globals
        private constant integer HASH_NEXT=53
        private constant integer MAX_HASH_VALUE=8191
        private integer array HashedInt
    endglobals

    private function Hash takes integer int returns integer
        local integer hash=int-(int/MAX_HASH_VALUE)*MAX_HASH_VALUE
        loop
            exitwhen HashedInt[hash]==int
            if HashedInt[hash]==0 then
                set HashedInt[hash]=int
                return hash
            endif
            set hash=hash+HASH_NEXT
            if hash>=MAX_HASH_VALUE then
                set hash=hash-MAX_HASH_VALUE
            endif
        endloop
        return hash
    endfunction
    //Handy function from Jesus4Lyf
    
    //! textmacro PUA_DATA takes NAME
    private struct $NAME$Data
        private static integer array data
        static method operator []= takes integer i, integer d returns nothing
            set data[Hash(i)]=d
        endmethod
        static method operator [] takes integer i returns integer
            return data[Hash(i)]
        endmethod
    endstruct
    //! endtextmacro PUA_DATA
    //! runtextmacro PUA_DATA ("Colour")
    //! runtextmacro PUA_DATA ("Scale")
    //! runtextmacro PUA_DATA ("TimeScale")
    private struct UnitColour
        integer r
        integer g
        integer b
        integer a
        private static method onInit takes nothing returns nothing
            local thistype this=thistype(0)
            set this.r=255
            set this.g=255
            set this.b=255
            set this.a=255
        endmethod
    endstruct
    
    private struct UnitScale
        real x
        real y
        real z
        private static method onInit takes nothing returns nothing
            local thistype this=thistype(0)
            set this.x=1.0
            set this.y=1.0
            set this.z=1.0
        endmethod
    endstruct
    
    private struct UnitTimeScale
        real value
        private static method onInit takes nothing returns nothing
            local thistype this=thistype(0)
            set this.value=1.0
        endmethod
    endstruct
    
    //Since the structs are either list head or node, so I just use unified structure for them.
    private module ListElements
        readonly thistype prev
        readonly thistype next
        boolean flag
        string word
        
        static method createHead takes nothing returns thistype
            local thistype this=thistype.allocate()
            set this.prev=this
            set this.next=this
            return this
        endmethod
        
        method link takes thistype c returns nothing
            set this.prev.next=c
            set c.prev=this.prev
            set this.prev=c
            set c.next=this
        endmethod
        
        method unlink takes nothing returns nothing
            set this.prev.next=this.next
            set this.next.prev=this.prev
        endmethod
        
        method search takes string word returns thistype
            local thistype c=this
            set this=this.next
            loop
            exitwhen this==c
                if this.word==word then
                    return this
                endif
                set this=this.next
            endloop
            return 0
        endmethod
        
        method chainDestroy takes nothing returns nothing
            local thistype c=this
            set this=this.next
            loop
            exitwhen this==c
                call this.destroy()
                set this=this.next
            endloop
            call this.destroy()
        endmethod
    endmodule
    
    //! textmacro PUA_VARS takes NAME, TYPE
        private $TYPE$ $NAME$x
        method operator $NAME$= takes $TYPE$ v returns nothing
            set this.$NAME$x=v
        endmethod
        method operator $NAME$ takes nothing returns $TYPE$
            if this.flag==true then
                return this.prev.$NAME$
            endif
            return this.$NAME$x
        endmethod
    //! endtextmacro
    
    private struct ColourList
        implement ListElements
        //! runtextmacro PUA_VARS ("r","integer")
        //! runtextmacro PUA_VARS ("g","integer")
        //! runtextmacro PUA_VARS ("b","integer")
        //! runtextmacro PUA_VARS ("a","integer")
    endstruct
    
    private struct ScaleList
        implement ListElements
        //! runtextmacro PUA_VARS ("x","real")
        //! runtextmacro PUA_VARS ("y","real")
        //! runtextmacro PUA_VARS ("z","real")
    endstruct
    
    private struct TimeScaleList
        implement ListElements
        //! runtextmacro PUA_VARS ("value","real")
    endstruct
    
    private struct UnitStruct extends array
        ColourList clist
        ScaleList slist
        TimeScaleList tlist
        
        private method AIDS_onCreate takes nothing returns nothing
            local integer id=GetUnitTypeId(this.unit)
            local UnitColour c=ColourData[id]
            local UnitScale s=ScaleData[id]
            local UnitTimeScale t=TimeScaleData[id]
            
            set this.clist=ColourList.createHead()
            set this.slist=ScaleList.createHead()
            set this.tlist=TimeScaleList.createHead()
            
            set this.clist.r=c.r
            set this.clist.g=c.g
            set this.clist.b=c.b
            set this.clist.a=c.a
            set this.clist.flag=false
            
            set this.slist.x=s.x
            set this.slist.y=s.y
            set this.slist.z=s.z
            set this.slist.flag=false
            
            set this.tlist.value=t.value
            set this.tlist.flag=false
        endmethod
        
        private method AIDS_onDestroy takes nothing returns nothing
            call this.clist.chainDestroy()
            call this.slist.chainDestroy()
            call this.tlist.chainDestroy()
        endmethod
        
        //! runtextmacro AIDS()
    endstruct
    
    function SetUnitTypeDefaultScale takes integer unitid, real x, real y, real z returns nothing
        local UnitScale s=ScaleData[unitid]
        if s==0 then
            set s=UnitScale.create()
            set ScaleData[unitid]=s
        endif
        set s.x=x
        set s.y=y
        set s.z=z
    endfunction
    
    function SetUnitTypeDefaultColour takes integer unitid, integer r, integer g, integer b, integer a returns nothing
        local UnitColour c=ColourData[unitid]
        if c==0 then
            set c=UnitColour.create()
            set ColourData[unitid]=c
        endif
        set c.r=r
        set c.g=g
        set c.b=b
        set c.a=a
    endfunction
    
    function SetUnitDefaultScale takes unit u, real x, real y, real z returns nothing
        local ScaleList s
        if u==null then
            return
        endif
        set s=UnitStruct<u>.slist
        set s.x=x
        set s.y=y
        set s.z=z
    endfunction
    
    function SetUnitDefaultColour takes unit u, integer r, integer g, integer b, integer a returns nothing
        local ColourList c
        if u==null then
            return
        endif
        set c=UnitStruct<u>.clist
        set c.r=r
        set c.g=g
        set c.b=b
        set c.a=a
    endfunction
    
    function SetUnitDefaultTimeScale takes unit u, real value returns nothing
        if u==null then
            return
        endif
        set UnitStruct<u>.tlist.value=value
    endfunction
    
    function AddUnitScale takes unit u, string word, real x, real y, real z returns nothing
        local UnitStruct dat
        local ScaleList s
        if u==null then
            return
        endif
        set dat=UnitStruct<u>
        set s=ScaleList.create()
        set s.word=word
        set s.x=x
        set s.y=y
        set s.z=z
        set s.flag=false
        call dat.slist.link(s)
        call SetUnitScale(u,x,y,z)
    endfunction
        
    function AddUnitColour takes unit u, string word, integer r, integer g, integer b, integer a returns nothing
        local UnitStruct dat
        local ColourList c
        if u==null then
            return
        endif
        set dat=UnitStruct<u>
        set c=ColourList.create()
        set c.word=word
        set c.r=r
        set c.g=g
        set c.b=b
        set c.a=a
        set c.flag=false
        call dat.clist.link(c)
        call SetUnitVertexColor(u,r,g,b,a)
    endfunction
    
    function AddUnitTimeScale takes unit u, string word, real value returns nothing
        local UnitStruct dat
        local TimeScaleList t
        if u==null then
            return
        endif
        set dat=UnitStruct<u>
        set t=TimeScaleList.create()
        set t.word=word
        set t.value=value
        set t.flag=false
        call dat.tlist.link(t)
        call SetUnitTimeScale(u,value)
    endfunction
    
    function AddUnitScaleForPlayer takes unit u, string word, real x, real y, real z, boolean boo returns nothing
        local UnitStruct dat
        local ScaleList s
        if u==null then
            return
        endif
        set dat=UnitStruct<u>
        set s=ScaleList.create()
        set s.word=word
        set s.flag=not boo
        if boo then
            set s.x=x
            set s.y=y
            set s.z=z
        endif
        call dat.slist.link(s)
        call SetUnitScale(u,s.x,s.y,s.z)
    endfunction
    
    function AddUnitColourForPlayer takes unit u, string word, integer r, integer g, integer b, integer a, boolean boo returns nothing
        local UnitStruct dat
        local ColourList c
        if u==null then
            return
        endif
        set dat=UnitStruct<u>
        set c=ColourList.create()
        set c.word=word
        set c.flag=not boo
        if boo then
            set c.r=r
            set c.g=g
            set c.b=b
            set c.a=a
        endif
        call dat.clist.link(c)
        call SetUnitVertexColor(u,c.r,c.g,c.b,c.a)
    endfunction
    
    function AddUnitTimeScaleForPlayer takes unit u, string word, real value, boolean boo returns nothing
        local UnitStruct dat
        local TimeScaleList t
        if u==null then
            return
        endif
        set dat=UnitStruct<u>
        set t=TimeScaleList.create()
        set t.word=word
        set t.flag=not boo
        if boo then
            set t.value=value
        endif
        call dat.tlist.link(t)
        call SetUnitTimeScale(u,t.value)
    endfunction
    
    function RemoveUnitScale takes unit u, string word returns nothing
        local ScaleList dat
        if u==null then
            return
        endif
        set dat=UnitStruct<u>.slist.search(word)
        if dat!=0 then
            call dat.unlink()
            call dat.destroy()
            set dat=UnitStruct<u>.slist.prev
            call SetUnitScale(u,dat.x,dat.y,dat.z)
        endif
    endfunction
    
    function RemoveUnitColour takes unit u, string word returns nothing
        local ColourList dat
        if u==null then
            return
        endif
        set dat=UnitStruct<u>.clist.search(word)
        if dat!=0 then
            call dat.unlink()
            call dat.destroy()
            set dat=UnitStruct<u>.clist.prev
            call SetUnitVertexColor(u,dat.r,dat.g,dat.b,dat.a)
        endif
    endfunction
    
    function RemoveUnitTimeScale takes unit u, string word returns nothing
        local TimeScaleList dat
        if u==null then
            return
        endif
        set dat=UnitStruct<u>.tlist.search(word)
        if dat!=0 then
            call dat.unlink()
            call dat.destroy()
            set dat=UnitStruct<u>.tlist.prev
            call SetUnitTimeScale(u,dat.value)
        endif
    endfunction
endlibrary</u></u></u></u></u></u></u></u></u></u></u></u></u></u></u>


Related links :
AIDS

Version History
  • v1.0.2 - Changed algorithm for ForPlayer API. The unit no longer shows default settings to player who is not picked for ForPlayer API, it will show previous settings instead.
  • v1.0.1 - No longer requires Table. Added new alternative APIs to eliminate the restriction of calling old API in GetLocalPlayer() blocks.
  • v1.0.0 - First release.
 

tooltiperror

Super Moderator
Reaction score
231
I like it. :)

Interface is a bit weird. Why not just base it off the colors? Do the strings matter?
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Yep, the string represents the keyword for attached settings.
Updated to v1.0.1!
 

tooltiperror

Super Moderator
Reaction score
231
Actually suits its purpose quite well.

I see no reason to leave this in resource limbo :thup:

Approved.
 

Bribe

vJass errors are legion
Reaction score
67
Unit scale should just be one value (for the X). The Y and Z of that function do nothing :(

This way, you could avoid creating two useless arrays for useless Y and Z components.
 

Romek

Super Moderator
Reaction score
963
Could we see some example code?
 

Bribe

vJass errors are legion
Reaction score
67
For PUA or for what I wrote?

If you wanted to test what I wrote it'd be pretty easy:

JASS:
function CreateFootmanWithScale takes real x, real y, real z returns nothing
    call SetUnitScale(CreateUnit(Player(0), &#039;hfoo&#039;, 0, 0, 0), x, y, z)
endfunction

function InitTrig_Test takes nothing returns nothing
    call CreateFootmanWithScale(1.0, 0, 0)
    call CreateFootmanWithScale(1.0, 1.0, 0)
    call CreateFootmanWithScale(1.0, 0, 1.0)
endfunction


There will be three footman with exactly the same 1:1 scale.
 

Romek

Super Moderator
Reaction score
963
For the system. :p

There's no arguing with the fact that SetUnitScale is broken.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/
  • The Helper The Helper:
    Here is another comfort food favorite - Million Dollar Casserole - https://www.thehelper.net/threads/recipe-million-dollar-casserole.193614/

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top