[vJASS] [Snippet] GetUnitScale

Description is in code.

Code
JASS:
library GetUnitScale /* v1.3

      Provides functionality to get a unit's current and default scale.

      The system expects the default scale value to be exactly 1.00.
      If you modified the value in the object editor for a specific unit,
      you have to adapt it to the system. (see module DefaultScale)
 
 
 */ requires /*

        */ UnitDex        /* hiveworkshop.com/threads/system-unitdex-unit-indexer.248209/
        */ Table          /* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/

 
**                   API
**
**
**  function GetUnitScale (unit) returns real
**      Returns the current scale of the unit.
**
**  function GetUnitDefaultScale (unit) returns real
**      Returns the default scale of the unit.

***************************************************************************
**
**  Credits to guys named in brackets.
**
**  Requires:
**      - Table (Bribe)
**      - UnitDex (TriggerHappy)
**
**************************************************************************/


    // Here you can define the correct default scale, it the value is not "1" in object editor.
 
    private module DefaultScale
        private static method onInit takes nothing returns nothing
     
        // Example:  call apply('hfoo', 1.60)    //  -> Register footman with default scale 1.60.
     
     
     
        call RegisterUnitIndexEvent(Condition(function thistype.onIndex), EVENT_UNIT_INDEX)
        endmethod
    endmodule

    private struct UnitScale extends array
        private static key k
        readonly static Table table = k
        readonly real defaultScale
        readonly static real array currentScale
     
        private static thistype this = 0
        static method apply takes integer uType, real scale returns nothing
            if not thistype.table.has(uType) then
                set this = this + 1
                set thistype.table[uType] = this
            endif
            set this.defaultScale = scale
        endmethod
        implement DefaultScale
     
        static method operator [] takes integer uType returns thistype
            return thistype.table[uType]
        endmethod
     
        // onIndex we initalisize the scale value.
        private static method onIndex takes nothing returns boolean
            local integer id = GetIndexedUnitId()
            local integer uType = GetUnitTypeId(GetIndexedUnit())
         
            // Check if default scale is registered for this unit type.
            if not thistype.table.has(uType) then
                set thistype.currentScale[id] = 1.
            else
                set thistype.currentScale[id] = thistype[uType].defaultScale
            endif
            return false
        endmethod
     
        // hook methods
        static method DataUpdate takes unit u, real x, real y, real z returns nothing
            set thistype.currentScale[GetUnitUserData(u)] = x
        endmethod  
        static method DataUpdatePercent takes unit u, real x, real y, real z returns nothing
            set thistype.currentScale[GetUnitUserData(u)] = x*0.01
        endmethod
     
    endstruct
 
    hook SetUnitScale UnitScale.DataUpdate
    hook SetUnitScalePercent UnitScale.DataUpdatePercent
 
    // API functions
 
    function GetUnitScale takes unit u returns real
        return UnitScale.currentScale[GetUnitUserData(u)]
    endfunction
 
    function GetUnitDefaultScale takes unit u returns real
        if UnitScale.table.has(GetUnitTypeId(u)) then
            return UnitScale[GetUnitTypeId(u)].defaultScale
        endif
        return 1.
    endfunction
endlibrary
 
Last edited:
Level 22
Joined
Sep 24, 2005
Messages
4,820
a) Why not extend its capability to modification too? Currently, it can only be used to retrieve a unit's default and current scaling value.

b) Why don't you just make the users use the struct method as interface(API)? I also suggest an alternative naming scheme:


JASS:
struct UnitScale
  
 methods:

 UnitScale.getDefault
 UnitScale.getCurrent
 
 // From comment a)
 UnitScale.setDefault // could be useful lol
 UnitScale.setCurrent
 
 UnitScale.InitScaleValue(integer Type, real scale)

Of course, that's just the API, the non-api functions won't matter to the users anyway so its fine the way it is.
 
Level 22
Joined
Sep 24, 2005
Messages
4,820
What's the point of using 0 as a scaling value though? wouldn't that make the model disappear/too small to see lol.

EDIT: Also, ridiculous negative values can pass through the check, so your point still stands.
 
Level 37
Joined
Sep 26, 2009
Messages
8,447
JASS:
        private static thistype this = 0
        static method apply takes integer uType, real scale returns nothing
            if thistype[uType] == 0 then
                set this = this + 1
                set thistype.table[uType] = this
            endif
            set this.defaultScale = scale
        endmethod

Do you see the problem here? I'll give you a hint: typecasting instead of Table.
 
JASS:
        private static thistype this = 0
        static method apply takes integer uType, real scale returns nothing
            if thistype[uType] == 0 then
                set this = this + 1
                set thistype.table[uType] = this
            endif
            set this.defaultScale = scale
        endmethod

Do you see the problem here? I'll give you a hint: typecasting instead of Table.
I'm not sure I understand you, Bribe.

thistype[uType] == 0 -> I use static method operator [] operator, not (), so it is like using table.
 
Level 37
Joined
Sep 26, 2009
Messages
8,447
thistype[uType] != thistype.table[uType]. Run a BJDebugMsg and you'll see. thistype[uType] simply gets the integer value of the uType (for example 'hfoo') instead of loading the data stored in the table. You'd have to create a static method operator [] takes integer uType returns integer if you want to enable that functionality. As it is now, the resource will always create a new instance of "this" even if you pass the same uType repeatedly to it.

Long story short, change the check to thistype.table[uType] == 0 and you'll be fine.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,442
I don't program any more
Or maybe that's why you missed that. :)

EDIT:
I'm sure this is not correct:
// Example: call DefaultScale.apply('hfoo', 1.60) // -> Register footman with default scale 1.60.
And I more like setDefault more than apply

DefaultScale[uType] != 0 -> check if unit type is registered only. (not any check done for the actual value here)
My bad
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,717
UnitIndexer (Nestharus) API has changed in a way, that this snippet will no longer work with it.

Neither GetIndexedUnitId() not GetIndexedUnit() are part of the API.

onIndex event is now register via
a) module
b) call UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onIndexEvent))

You should register onIndexEvent via module initializer to be sure it gets registered before creating any units somewhere else.
table = key ... thats okey :), but since you have to init the index event you could also use table = Table.create()

if thistype[uType] == 0 then is working fine. I prefer table.has(integer) as it is closer to the Hashtable API HaveSavedInteger.

is defaultScale as member required? Can't we load that value directly from the table via table[unitTypeId]?
if not existing in the Table you can save the default scaling to 1.00, once an unit type is indexed for the first time.
 
UnitIndexer (Nestharus) API has changed in a way, that this snippet will no longer work with it.
Si senior, I just switched to UnitDex. :D

You should register onIndexEvent via module initializer to be sure it gets registered before creating any units somewhere else.
Ok.

if thistype[uType] == 0 then is working fine. I prefer table.has(integer) as it is closer to the Hashtable API HaveSavedInteger.
.has doesn't work for native types I think, but only for handles:

JASS:
private struct handles extends array
    method has takes integer key returns boolean
        return HaveSavedHandle(ht, this, key)
    endmethod
    method remove takes integer key returns nothing
        call RemoveSavedHandle(ht, this, key)
    endmethod
endstruct
And it didn't work for me when I tried it now.

is defaultScale as member required? Can't we load that value directly from the table via table[unitTypeId]?
if not existing in the Table you can save the default scaling to 1.00, once an unit type is indexed for the first time.
If user doesn't work with table it seems simpler for me. I'm not sure if it should be changed.

Edit:

UnitDex doesn't seem to work correctly.
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,717
Of course .has(key) works

Here is the macro for integer, real, string, boolean
JASS:
//! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE
private struct $TYPE$s extends array
    method operator [] takes integer key returns $TYPE$
        return Load$FUNC$(ht, this, key)
    endmethod
    method operator []= takes integer key, $TYPE$ value returns nothing
        call Save$FUNC$(ht, this, key, value)
    endmethod
    method has takes integer key returns boolean
        return HaveSaved$SUPER$(ht, this, key)
    endmethod
    method remove takes integer key returns nothing
        call RemoveSaved$SUPER$(ht, this, key)
    endmethod
endstruct
private module $TYPE$m
    method operator $TYPE$ takes nothing returns $TYPE$s
        return this
    endmethod
endmodule
//! endtextmacro
 
Top