• 🏆 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!

MUI Advanced Equipment System: Expansion

Status
Not open for further replies.
Level 19
Joined
Mar 18, 2012
Messages
1,716
EDIT: Moved to spell section ItemPower

In the map I am working on at the moment I'm using MUI Advanced Equipment System. But i felt like something is missing. So I wrote this small system which adds an individual damage multiplier to each registered item.
The idea behind this is to call GetPower(unit, powerid) in any spell struct, which gives the opportunity calculate damage more dynamic.

For example:
A unit carries a staff which adds 20% damage to all fire spells and a cap that adds 5 % to fire spells
Now it casts such a spell
In the spell struct we set damage to 10*AbilityLevel*GetPower(unit, integer for fire). The result will be damage = 10*AbililtyLevel*1.25

Since it is the most frequent downloaded inventory system on THW, this could turn out to be really useful.
As this is only an expansion to an already existing resource, I don't think it belongs into the spell section, but rather in the lab.
Also this is not 100% finished. It misses a destroy method and does not support the ChangeEquipmentOwner function (yet). For my needs this is complete, dependent on the resonance I'll write those missing lines of code.


Opinions and suggestions are very welcome.

Requires: Table, Alloc, UnitIndexer, AdvancedEquipmentSystem
JASS:
library SpellPower uses Alloc, UnitIndexer, AdvancedEquipmentSystem, Table

    private struct Power extends array
        implement Alloc
    
        private static TableArray tb
        private static thistype array unitIndex
        private static hashtable hash = InitHashtable()
        
        private static method removePower takes nothing returns boolean
            local integer id = GetTriggeringItemId()
            local thistype this = unitIndex[GetUnitId(GetEquippingUnit())]
            local integer i = 1
            loop
                exitwhen i == 10
                    set tb[this].real[i] = tb[this].real[i] - LoadReal(hash, id, i)
                    set tb[this][i] = tb[this][i] - LoadInteger(hash, id, i)
                    set i = i + 1
            endloop
            return false
        endmethod
        
        private static method addPower takes nothing returns boolean
            local integer id = GetTriggeringItemId()
            local thistype this = unitIndex[GetUnitId(GetEquippingUnit())]
            local integer i = 1
            loop
                exitwhen i == 10
                    set tb[this].real[i] = tb[this].real[i] + LoadReal(hash, id, i)
                    set tb[this][i] = tb[this][i] + LoadInteger(hash, id, i)
                    set i = i + 1
            endloop
            return false
        endmethod
        
        static method getRealPower takes unit WhichUnit, integer WhichPower returns real 
            return tb[unitIndex[GetUnitId(WhichUnit)]].real[WhichPower]
        endmethod
        
        static method getIntPower takes unit WhichUnit, integer WhichPower returns integer
            return tb[unitIndex[GetUnitId(WhichUnit)]][WhichPower]
        endmethod
    
        static method createPower takes unit WhichUnit returns nothing
            local thistype this = allocate() 
            set unitIndex[GetUnitId(WhichUnit)] = this
            set tb[this].real[1] = 1.//Fire
            set tb[this].real[2] = 1.//Twohand
            set tb[this].real[3] = 0.00//Crit Chance
            set tb[this].real[4] = 1.00//Crit Factor
            set tb[this].real[5] = 0.00//Block Change
            set tb[this].real[6] = 0//Min Block Amount
            set tb[this].real[7] = 0//Max Block Damage
            set tb[this].real[8] = 0//Min Bonus Damage
            set tb[this].real[9] = 0//Max Bonus Damage
            set tb[this][1] = 0//IntFire
            set tb[this][2] = 0//IntTwohand
            set tb[this][3] = 0//IntCrit
            set tb[this][4] = 0//IntCritFactor
            set tb[this][5] = 0//IntBlockC
            set tb[this][6] = 0//IntBlockMin
            set tb[this][7] = 0//IntBlockMax
            set tb[this][8] = 0//IntDamMin
            set tb[this][9] = 0//IntDamMax
        endmethod
        
        static method registerItem takes integer WhichItem, integer WhichSpellPower, real RealAmount, integer IntAmount returns nothing
            call SaveReal(hash,WhichItem, WhichSpellPower, RealAmount)
            call SaveInteger(hash, WhichItem, WhichSpellPower, IntAmount)
        endmethod
        
        private static method onInit takes nothing returns nothing
            set tb = TableArray[0x2000]//[200] could be enough
            call RegisterItemEquipEvent(function thistype.addPower)
            call RegisterItemUnequipEvent(function thistype.removePower)
        endmethod
    endstruct
    
    public function RegisterSpellPowerItem takes integer WhichItem, integer WhichPower, real RealAmount, integer IntAmount returns nothing
        call Power.registerItem(WhichItem, WhichPower, RealAmount, IntAmount)
    endfunction
    
    function GetRealPower takes unit WhichUnit, integer WhichPower returns real//Returns real: good for calculation
        return Power.getRealPower(WhichUnit, WhichPower)
    endfunction
    
    function GetIntPower takes unit WhichUnit, integer WhichPower returns integer//Returns integer: good for display(Multiboard, Textag)
        return Power.getIntPower(WhichUnit, WhichPower)
    endfunction
    
    function InitPowerSystemForUnit takes unit u returns nothing
        call Power.createPower(u)
    endfunction
    
endlibrary

Edit: Actually it is not bound to AdvancedEquipmentSystem and can be used for any equipment system. You just need a custom trigger for onEquip and onUnequip.
 
Last edited:
Looks nice. :) In Ardent Heroes, I did something similar for spell power, crit, dodge, miss etc. (but I coupled it with my own damage modification system to apply all those changes).

Right now, increasing fire, ice, magic etc. is kind of map specific. But it is certainly a nice sample. As for the code, you can actually use arrays for some of them in place of tables. For example, tb. UnitIndexers will assign user data in the range of 0-8190, so you don't need to assign them to tables, you can just make an array of type thistype.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
I haven't even thought about parameters like crit or dodge, yet. Thank you :).
Concerning the tables: I will change that.

Fire, Ice, ... I just wrote those to picture, what this resource should do.

Edit: At the moment this works with small numbers like 0.05. Which is suboptimal, because real/integer conversion rounds incorrect 0.999 -> 0. If i remember correctly even 1.000 is rounded to 0.
E.g. : GetPower returns 1.050 as damage amplifier of 5% --> 1.050*100-100 --> 5.0000 still R2I will return 4.
This issue doesn't affect the system itself, but if you want to display values on for example a Multiboard you would want to convert reals to integers.
Amplified damage + 5% looks way nicer than + 1.050, but will return 4 although it should be ( and is ) 5.

Edit2:
Replaced one table with a thistype array and improved the code slightly.
Now saves integers and reals, to avoid rounding issues.
One is now able to return either integers or reals by getIntPower() or getRealPower(), which turns out to be useful, depending on what you want to manipulate.
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,716
so you don't need to assign them to tables, you can just make an array of type thistype .
I assume reading an array is more effective than reading from a Table.

I just realized an item can only have one Power assigned ...

Uses now one hashtable, since I don't know the integer range of items and therefore couldn't set a proper TableArray size.

Moving to the spell section.
 
Last edited:
Status
Not open for further replies.
Top