• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Snippet] Unit State Percent

Level 31
Joined
Jul 10, 2007
Messages
6,306
Requirements:
Installation Script
Light version doesn't require this script
JASS:
//! externalblock extension=lua ObjectMerger $FILENAME$
    //! runtextmacro LUA_FILE_HEADER()
    //! i dofile("GetVarObject")
    
    //! i local id = getvarobject("Hvsh", "units", "UNITS_UNIT_STATE_PERCENT", true)
    
    //! i createobject("Hvsh", id)
    //! i makechange(current, "uabi", "Aloc,Avul")
    //! i makechange(current, "usid", "0")
    //! i makechange(current, "usin", "0")
    //! i makechange(current, "usca", "0")
    
    //! i updateobjects()
//! endexternalblock

JASS:
library UnitStatePercent /* v1.0.1.7
*************************************************************************************
*
*   UnitStatePercent allows one to deal with Unit States as if they were 
*   represented by percents instead of literal values.  This is very useful
*   for Save/Load.
*
************************************************************************************
*
*   */uses/*
*
*       */ WorldBounds          /*  hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
*       */ SetHeroLevelX        /*  hiveworkshop.com/forums/1994340-post545.html
*
*************************************************************************************
*   Functions
*
*       function GetPercentHeroXP takes unit u returns integer
*       function AddPercentHeroXP takes unit u, integer p returns nothing
*
*       function GetPercentUnitLife takes unit u returns integer
*       function SetPercentUnitLife takes unit u, integer p returns nothing
*
*       function GetPercentUnitMana takes unit u returns integer
*       function SetPercentUnitMana takes unit u, integer p returns nothing
*
*       function GetPercentUnitX takes unit u returns integer
*       function PercentToX takes integer l returns real
*
*       function GetPercentUnitY takes unit u returns integer
*       function PercentToY takes integer l returns real
*
*       function GetPercentUnitFacing takes unit u returns integer
*       function PercentToFacing takes integer f returns real
*
************************************************************************************/
    globals
        private real xl=0
        private real yl=0
        private unit h=null
    endglobals
    private module Init
        private static method onInit takes nothing returns nothing
            set xl=WorldBounds.maxX-WorldBounds.minX
            set yl=WorldBounds.maxY-WorldBounds.minY
            set h=CreateUnit(Player(15),UNITS_UNIT_STATE_PERCENT,WorldBounds.maxX,WorldBounds.maxY, 0)
            call SetUnitX(h,WorldBounds.maxX)
            call SetUnitY(h,WorldBounds.maxY)
            call PauseUnit(h,true)
        endmethod
    endmodule
    private struct Inits extends array
        implement Init
    endstruct
    //retrieves how far a hero is into its level as an integer %
    //u refers to the hero
    function GetPercentHeroXP takes unit u returns integer
        local integer l=GetHeroLevel(u)
        local integer m=0
        if (1<l) then
            call SetHeroLevelX(h,l)
            set m=GetHeroXP(h)
        endif
        call SetHeroLevelX(h,l+1)
        set m=(GetHeroXP(u)-m)*100/(GetHeroXP(h)-m)
        call UnitStripHeroLevel(h,l+1)
        return m
    endfunction
    //adds an integer percent xp to a hero
    //u refer to hero, p refers to percent
    //make sure the hero was its original level before adding
        //call SetHeroLevel(u, myLvl, false)
        //call AddPercentHeroXP(u, 30) //pushes the hero 30% into the level
    function AddPercentHeroXP takes unit u,integer p returns nothing
        local integer l
        local integer m=0
        if (0<p) then
            set l=GetHeroLevel(u)
            if (1<l) then
                call SetHeroLevelX(h,l)
                set m=GetHeroXP(h)
            endif
            call SetHeroLevelX(h,l+1)
            call AddHeroXP(u,R2I((GetHeroXP(h)-m)*p/100.),false)
            call UnitStripHeroLevel(h,l+1)
        endif
    endfunction
    //retrieves a unit's current life as a percent
    function GetPercentUnitLife takes unit u returns integer
        return R2I((GetWidgetLife(u)/GetUnitState(u,UNIT_STATE_MAX_LIFE))*100+.5)
    endfunction
    //sets a unit's life given a percent
    function SetPercentUnitLife takes unit u, integer p returns nothing
        call SetWidgetLife(u,p/100.*GetUnitState(u,UNIT_STATE_MAX_LIFE))
    endfunction
    //retrieves a unit's current mana as a percent
    function GetPercentUnitMana takes unit u returns integer
        local real m=GetUnitState(u,UNIT_STATE_MAX_MANA)
        if (0==m) then
            return 0
        endif
        return R2I(GetUnitState(u,UNIT_STATE_MANA)/m*100+.5)
    endfunction
    //sets a unit's mana given a percent
    function SetPercentUnitMana takes unit u, integer p returns nothing
        call SetUnitState(u,UNIT_STATE_MANA,p/100.*GetUnitState(u,UNIT_STATE_MAX_MANA))
    endfunction
    function GetPercentUnitX takes unit u returns integer
        return R2I((GetWidgetX(u)-WorldBounds.minX)/xl*100+.5)
    endfunction
    function PercentToX takes integer l returns real
        return l/100.*xl+WorldBounds.minX
    endfunction
    function GetPercentUnitY takes unit u returns integer
        return R2I((GetWidgetY(u)-WorldBounds.minY)/yl*100+.5)
    endfunction
    function PercentToY takes integer l returns real
        return l/100.*yl+WorldBounds.minY
    endfunction
    function GetPercentUnitFacing takes unit u returns integer
        local integer i=R2I(GetUnitFacing(u)/360.*100+.5)
        if (100==i) then
            return 0
        endif
        return i
    endfunction
    function PercentToFacing takes integer f returns real
        return f/100.*360
    endfunction
endlibrary

Light Version
Does not require Lua
JASS:
library UnitStatePercent /* v1.0.1.7
*************************************************************************************
*
*   UnitStatePercent allows one to deal with Unit States as if they were 
*   represented by percents instead of literal values.  This is very useful
*   for Save/Load.
*
************************************************************************************
*
*   */uses/*
*
*       */ WorldBounds          /*  hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
*
*************************************************************************************
*   Functions
*
*       function GetPercentUnitLife takes unit u returns integer
*       function SetPercentUnitLife takes unit u, integer p returns nothing
*
*       function GetPercentUnitMana takes unit u returns integer
*       function SetPercentUnitMana takes unit u, integer p returns nothing
*
*       function GetPercentUnitX takes unit u returns integer
*       function PercentToX takes integer l returns real
*
*       function GetPercentUnitY takes unit u returns integer
*       function PercentToY takes integer l returns real
*
*       function GetPercentUnitFacing takes unit u returns integer
*       function PercentToFacing takes integer f returns real
*
************************************************************************************/
    globals
        private real xl=0
        private real yl=0
    endglobals
    private module Init
        private static method onInit takes nothing returns nothing
            set xl=WorldBounds.maxX-WorldBounds.minX
            set yl=WorldBounds.maxY-WorldBounds.minY
        endmethod
    endmodule
    private struct Inits extends array
        implement Init
    endstruct
    function GetPercentUnitLife takes unit u returns integer
        return R2I((GetWidgetLife(u)/GetUnitState(u,UNIT_STATE_MAX_LIFE))*100+.5)
    endfunction
    function SetPercentUnitLife takes unit u, integer p returns nothing
        call SetWidgetLife(u,p/100.*GetUnitState(u,UNIT_STATE_MAX_LIFE))
    endfunction
    function GetPercentUnitMana takes unit u returns integer
        local real m=GetUnitState(u,UNIT_STATE_MAX_MANA)
        if (0==m) then
            return 0
        endif
        return R2I(GetUnitState(u,UNIT_STATE_MANA)/m*100+.5)
    endfunction
    function SetPercentUnitMana takes unit u, integer p returns nothing
        if (0 != GetUnitState(u, UNIT_STATE_MAX_MANA)) then
            call SetUnitState(u,UNIT_STATE_MANA,p/100.*GetUnitState(u,UNIT_STATE_MAX_MANA))
        endif
    endfunction
    function GetPercentUnitX takes unit u returns integer
        return R2I((GetWidgetX(u)-WorldBounds.minX)/xl*100+.5)
    endfunction
    function PercentToX takes integer l returns real
        return l/100.*xl+WorldBounds.minX
    endfunction
    function GetPercentUnitY takes unit u returns integer
        return R2I((GetWidgetY(u)-WorldBounds.minY)/yl*100+.5)
    endfunction
    function PercentToY takes integer l returns real
        return l/100.*yl+WorldBounds.minY
    endfunction
    function GetPercentUnitFacing takes unit u returns integer
        local integer i=R2I(GetUnitFacing(u)/360.*100+.5)
        if (100==i) then
            return 0
        endif
        return i
    endfunction
    function PercentToFacing takes integer f returns real
        return f/100.*360
    endfunction
endlibrary

Demo
Run this in map to see approximations (very close to actual values!)
JASS:
struct tester extends array
    private static method test takes real x, real y, real facing, real life, real mana, integer level, integer xp returns nothing
        local unit u = CreateUnit(Player(0), 'Hpal', x, y, facing)
        local integer xps
        local integer mp
        local integer lp
        local integer fp
        
        if (level > 1) then
            call SetHeroLevel(u, level, false)
        endif
        call AddHeroXP(u, xp, false)
        call SetWidgetLife(u, life)
        call SetUnitState(u, UNIT_STATE_MANA, mana)
        
        //done above as setting levels will change the percents
        set lp = GetPercentUnitLife(u)
        set mp = GetPercentUnitMana(u)
        set fp = GetPercentUnitFacing(u)
        set xps = GetPercentHeroXP(u)
        set xp = GetHeroXP(u)
        
        call UnitStripHeroLevel(u, level)
        call SetHeroXP(u, 0, false)
        
        call SetUnitX(u, PercentToX(GetPercentUnitX(u)))
        call SetUnitY(u, PercentToY(GetPercentUnitY(u)))
        if (level > 1) then
            call UnitStripHeroLevel(u, 1)
            call SetHeroLevel(u, level, false)
        endif
        call AddPercentHeroXP(u, xps)
        call SetPercentUnitLife(u, lp)
        call SetPercentUnitMana(u, mp)
        call SetUnitFacing(u, PercentToFacing(fp))
        
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "x: " + R2S(x) + "==" + R2S(GetWidgetX(u)))
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "y: " + R2S(y) + "==" + R2S(GetWidgetY(u)))
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "facing: " + R2S(facing) + "==" + R2S(GetUnitFacing(u)))
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "life: " + R2S(life) + "==" + R2S(GetWidgetLife(u)))
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "mana: " + R2S(mana) + "==" + R2S(GetUnitState(u, UNIT_STATE_MANA)))
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "level: " + I2S(level) + "==" + I2S(GetHeroLevel(u)))
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "xp: " + I2S(xp) + "==" + I2S(GetHeroXP(u)))
        set u = null
    endmethod
    private static method onInit takes nothing returns nothing
        call test(2691,WorldBounds.minY,124,450,0,2,50)
    endmethod
endstruct
 
Last edited:
Top