Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

latest news: next gen Trigger, save/load, attack indexing

Discussion in 'The Lab' started by Nestharus, Sep 4, 2014.

  1. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    There have been a few new developments in the past months that are pretty cool that people may be unaware of ; ).

    Lua:
    Research is being conducted as to the cause of why some machines can't run the object merger exe with Lua. There are two possible causes. One is a lack of registry entries due to an illegal copy of wc3. The other could have to do with copying jassnewgen. Remember how it asks for your wc3 directory the first time you run it?

    Trigger:
    BooleanExpression currently uses a list of complete binary search trees that are then built into a balanced binary search tree. This results in good behavior and a slight speed boost on evaluation, but incurs hefty memory costs and severe overhead for building trees. The new design calls for a single tree, which would eliminate the tree build step and reduce memory usage.

    Save/Load:
    arhowk came up witg a new synchronization technique making use of a dummy unit selected by a player, ForceUIKey, spellbooks, abilities, and ability events. The data is still capped, but it transmits much less than the gamecache does, resulting in much faster speeds and feasible usage in maps. It takes 1 to 2 seconds, as claimed by the author, to synchronize a mountain of data. Combined with my special network code that packs and broadcasts data in streams, we'll have something epic.

    Attack indexing:
    I recently discored that damage is stored on an attack. When changing the damage on a unit around in between attacks is done, original damage used in attacks is preserved. The damage is actually calculated during attack. With this approach, damage can be treated as instance pointers to structs.

    Targeting:
    Adding/removing wind orb ability may enable units to be able to toggle between being able to hit air and not. Think of a bow that can be equipped.

    BigInt Division:
    A digit may be negative. When all digits are summed together, keeping in mind place, the number is put into standard form. This makes it possible to divide one number by another number 1 digit at a time only needing to divide by the leading digit of the divisor to get an estimate. This also enables subtraction that is on par with the speed of addition. Division turns into single digit division, followed by multiplication, followed by fast subtraction. At the end, multiplication and addition are used to bring the number to standard form. The answer is also absolutely accurate and there is no chance of overflow.


    There are still a lot of things left to be solved, like custom cooldowns, custom attack ranges, and item indexing, all with minimal overhead of course.
     
    Last edited: Sep 5, 2014
  2. Softmints

    Softmints

    Joined:
    Jun 3, 2005
    Messages:
    221
    Resources:
    9
    Models:
    1
    Maps:
    7
    Tutorials:
    1
    Resources:
    9
    Hi Nestharus,

    Thank you for your inspiring work on pushing the limits of Wc3 modding. You mentioned not having solutions for custom cooldowns or attack ranges yet, maybe I can offer some possible approaches from work on my project RoW.

    I've implemented custom cooldowns on items and units by using a Spell Shield dummy ability. My setup for hero abilities which need this functionality requires the following:
    • An Attribute Bonus with Show Icon=false so the ability can be learned by a hero and show a learn tooltip.
    • A Channel (or other) base ability to be used when casting the ability.
    • Spell Shield(s) with the appropriate tooltips for each level of the base ability, and variable cooldown values.
    When the ability is learned, I add the base ability to the hero. When it is cast, or needs to go on cooldown, SetPlayerAbilityAvailable(owner, base_ability_aid, false), add the Spell Shield, set the level as needed for the desired cooldown, and use a hostile dummy to cast Cripple on the unit to start the cooldown. Then a timer will swap the spell shield out for the base ability once it comes off cooldown.

    It is possible to dynamically reset the cooldown so that, for example, when a hero attacks an enemy, his cooldowns advance by 1 second. The "clock" effect on the ability will restart from 12'o'clock when this happens.

    The same is easily achieved with items, by substituting the real item with a Spell Shield version of the item. I use this to have, for example, a healing salve go on cooldown *after* the unit has taken damage and the effect ended. I have found this approach exceptionally clean and effective. The only caveat is an occasional "our units are under attack!" warning ping, or in the case of items, the subtle sound of dropping/picking up an item.

    As for attack ranges, I wrote a system which enables dynamic cast range on abilities by intercepting orders, which makes use of Rising_Dusk's LastOrder library. It could easily be adapted to intercept attacks, though I don't think a queued orders would be preserved. If there's a demand for it, I wouldn't have a problem uploading it.

    I don't know what item indexing refers to, but I've done work with items as well so maybe I can help?
     
  3. Mythic

    Mythic

    Media Manager

    Joined:
    Apr 24, 2012
    Messages:
    8,207
    Resources:
    131
    Models:
    112
    Icons:
    5
    Maps:
    5
    Spells:
    6
    Reforged HD Icons:
    1
    Tutorials:
    2
    Resources:
    131
    Wind Orb? :eek:

    I don't remember items/abiltiies of that name...
     
  4. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    @Softmints

    By custom cooldown, I mean custom cooldowns for unit attacks ; ), but for abilities/items are pretty cool too =).

    Item indexing is assigning a unique integer to an item via SetItemUserData. When the item goes out of scope, this integer is recycled. When the item goes into scope, this integer is assigned. There should be no delay for these operations.
     
  5. Softmints

    Softmints

    Joined:
    Jun 3, 2005
    Messages:
    221
    Resources:
    9
    Models:
    1
    Maps:
    7
    Tutorials:
    1
    Resources:
    9
    What are the use cases for custom cooldowns on unit attacks and item indexing? BonusMod and GetHandleId+Hashtables have always been sufficient for me.
     
  6. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    BonusMod won't work for setting cooldown. I can't go between .01 cooldown and 250 cooldown. It's capped at like 255% or something.

    GetHandleId+Hashtable is no good since the requirement is ItemUserData ;).

    Use cases are generic, do no matter ; p.
     
  7. Arhowk

    Arhowk

    Joined:
    Aug 8, 2007
    Messages:
    2,752
    Resources:
    0
    Resources:
    0
    the f*k you talkin bout.

    5 AP classes + 2 300-level college courses isnt exactly wc3 modding friendly

    Code (vJASS):
    library ArhowksNetwork initializer init requires Table, Ascii, GetDummy //everything is little endian
        globals
            private integer A0 = 'A#*0'
            private integer A1 = 'A#*1'
            private integer A2 = 'A#*2'
            private integer A3 = 'A#*3'
            private integer AF = 'A#*/'
            private integer A4 = 'A#*4'
            private integer array ABILS
           
            private string O0 = "A"
            private string O1 = "B"
            private string O2 = "C"
            private string O3 = "D"
            private string OF = "T"
            private string O4 = "E"
            private string array ORDERS
           
           
            private integer B_ALL = 'A%%7'
            private string B_AK = "W"
            private string B_LV = "E"
            private string B_WXYZ = "R"
            private string B_NUM = "Q"
            private string BIG_AK = "T"
            private string BIG_LV = "Y"
            private string BIG_WXYZ = "U"
           
            private string array oCache
            private string array bCache
       //     private integer cacheIndex = 0
            private boolean Syncing = false
            private unit dummyUnit
            private Table timerData
        endglobals
       
        function ClearUnit takes unit u returns nothing
            local location l = GetUnitLoc(u)
            call SetUnitPositionLoc(u, l)
            call RemoveLocation(l)
            set l = null
        endfunction
       
        struct BinaryDecode extends array
            implement Alloc
            integer val
           
            public method isFinished takes nothing returns boolean
                return val == 0
            endmethod
           
            public method next takes nothing returns integer
                local integer one = ModuloInteger(val, 4)
                set val = val / 4
                return one
            endmethod
           
            public static method create takes integer input returns thistype
                local thistype this = thistype.allocate()
                set this.val = input
                return this
            endmethod
        endstruct
       
        struct BinaryStream
       
            integer val
            integer res
            integer bakedRes
            integer count
            static integer DEFAULT_RES = 3
           
            public method add takes integer i returns nothing
                set val = val + (i * R2I(Pow(bakedRes, count)))
                set count = count + 1
            endmethod
           
            public method get takes nothing returns integer
                return val
            endmethod
           
            public method flush takes nothing returns nothing
                set val = 0
                set count = 0
            endmethod
           
            public method destroy takes nothing returns nothing
                call deallocate()
            endmethod
           
            public static method create takes integer res returns thistype
                local thistype this = thistype.allocate()
           
                set val = 0
                set this.res = res
                if res == 2 then
                    set bakedRes = 4
                else
                    set bakedRes = R2I(Pow(2, res))
                endif
                set count = 0
           
                return this
            endmethod
           
        endstruct
       
        struct UnitData extends array
            implement Alloc
           
            integer typee
            integer value
           
            public method recieve takes integer abilId returns nothing
                if typee == 0 then
                   // call FMsg("iqu")
                    call IntegerPacket(value).recieve(abilId)
                elseif typee == 1 then
                    call IntegerQueuePacket(value).recieve(abilId)
                else
                    call StringQueuePacket(value).recieve(abilId)
                endif
            endmethod
           
            public method destroy takes nothing returns nothing
                call deallocate()
            endmethod
           
            public static method create takes integer typ, integer thisv returns thistype
                local thistype this = thistype.allocate()
                set this.typee = typ
                set this.value = thisv
                return this
            endmethod
           
        endstruct
       
        struct IntegerPacket extends array
            implement Alloc
            integer val
            BinaryStream incoming
            UnitData unitData
            boolean fin
            integer value
            player p
            unit u
           
            method getValue takes nothing returns integer
                return value
            endmethod
           
            method destroy takes nothing returns nothing
                if not fin then
                    call Network_RemoveDummy(u)
                    call unitData.destroy()
                    set value = incoming.get()
                    call incoming.destroy()
                endif
                call deallocate()
            endmethod
           
            method wait takes boolean b returns boolean
                if b then
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                endif
                return fin
            endmethod
           
            method recieve takes integer i returns nothing
                local integer l = 0
                if i == AF then
                    call Network_RemoveDummy(u)
                    call unitData.destroy()
                    set value = incoming.get()
                    call incoming.destroy()
                    set fin = true
                else
                    set l = 0
                    loop
                        if ABILS[l] == i then
                            call incoming.add(l)
                            exitwhen true
                        endif
                        set l = l + 1
                        exitwhen l == 16
                    endloop
                endif
            endmethod
            static thistype tem
            static trigger broadc = null
            private static method broad2 takes nothing returns nothing
                local integer i
                local thistype this = tem
                local BinaryDecode stream = BinaryDecode.create(val)
               
                set u= Network_GetDummy(p)
                call UnitAddAbility(u, A0)
                call UnitAddAbility(u, A1)
                call UnitAddAbility(u, A2)
                call UnitAddAbility(u, A3)
                call UnitAddAbility(u, AF)
                call SetUnitUserData(u, unitData)
               
                if GetLocalPlayer() == p then
                    call ClearSelection(  )
                    call SelectUnit( u, true)
                endif
               
              //  call TriggerSyncStart()
               // call TriggerSyncReady()
                if not Syncing then
                    set Syncing = true
                    call SyncSelections()
                    set Syncing = false
                else
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                endif
               
                if GetLocalPlayer() == p then
                    if stream.isFinished() then
                        call ForceUIKey(ORDERS[0])
                    endif
                    loop
                        exitwhen stream.isFinished()
                        call ForceUIKey(ORDERS[stream.next()])
                    endloop
                    call ForceUIKey(OF)
                endif
                call stream.deallocate()
            endmethod
           
            public method broadcast takes nothing returns nothing
                set tem = this
                call TriggerExecute(broadc)
            endmethod
           
            public static method create takes integer value, player playerFor returns thistype
                local thistype this = thistype.allocate()
                set val = value
                set incoming = BinaryStream.create(0)
                set unitData = UnitData.create(0, this)
                set p = playerFor
                set u = null
                if broadc == null then
                    set broadc = CreateTrigger()
                    call TriggerAddAction(broadc, function thistype.broad2)
                endif
                set fin = false
                return this
            endmethod
           
        endstruct
       
        struct IntegerQueuePacket extends array
            implement Alloc
           
            BinaryStream incoming
            UnitData unitData
            Table incomingQueue
            integer incomingCount
            integer incomingQueuePos
            integer popPos
            boolean recievingCount
           
            Table Queue
            integer count
            boolean fin
            player p
            unit u
           
            method pop takes nothing returns integer
                set popPos = popPos + 1
                return incomingQueue[popPos-1]
            endmethod
           
            method getCount takes nothing returns integer
                return incomingCount
            endmethod
           
           
            method outOfData takes nothing returns boolean
                return popPos == incomingCount
            endmethod
           
            method add takes integer value returns nothing
                set Queue[count] = value
                set count = count + 1
            endmethod
           
            method destroy takes nothing returns nothing
                call Queue.destroy()
                call incoming.destroy()
                call unitData.destroy()
                set p = null
                call incomingQueue.destroy()
                if not fin then
                    call Network_RemoveDummy(u)
                endif
                call deallocate()
            endmethod
               
            method wait takes boolean b returns boolean
                if b then
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                endif
                return fin
            endmethod
           
            method recieve takes integer i returns nothing
                local integer l = 0
                if fin then
                    return
                endif
          //      call BJDebugMsg("RECIEVED")
         //       call BJDebugMsg("RECIEVED ORDER : " + I2S(i))
                if i == AF then
                    if recievingCount then
          //              call BJDebugMsg("RECIEVD CCUNT")
                        set incomingCount = incoming.get()
                        set recievingCount = false
                        if incomingCount == 0 then
                            call Network_RemoveDummy(u)
                            set fin = true
                        endif
                    else
                        //if incomingQueuePos = 100 then
                        //    call BJDebugMsg("count : " + I2S(incomingCount))
                        //endif
                        set incomingQueue[incomingQueuePos] = incoming.get()
                        set incomingQueuePos = incomingQueuePos + 1
                    endif
                    call incoming.flush()
                    if incomingQueuePos == incomingCount then
                        call Network_RemoveDummy(u)
                        set fin = true
                    endif
                else
                    set l = 0
                    loop
                        if ABILS[l] == i then
                            call incoming.add(l)
                            exitwhen true
                        endif
                        set l = l + 1
                        exitwhen l == 16
                    endloop
                endif
                call ClearUnit(u)
            endmethod
           
           
            static integer tr_i
            static trigger t = null
           
            private method broadcastint takes integer i returns nothing
                local BinaryDecode stream = BinaryDecode.create(i)
                local integer next
               
                if GetLocalPlayer() == p then
                    if stream.isFinished() then
             //           call BJDebugMsg("FINIHSED ORDER : " + ORDERS[0])
                        call ForceUIKey(ORDERS[0])
                    else
                        loop
                            exitwhen stream.isFinished()
                            set next = stream.next()
              //          call BJDebugMsg("NEXT ORDER : " + ORDERS[next])
                            call ForceUIKey(ORDERS[next])
                           
                        endloop
                    endif
               
                    call ForceUIKey( OF )
                endif
                call stream.deallocate()
            endmethod
           
            public method broadcast takes nothing returns nothing
                local integer i
               
                set recievingCount = true
                set u = Network_GetDummy(p)
                call UnitAddAbility(u, B_ALL)
                //call PauseUnit(u, true)
                //call PauseUnit(u, false)
                call SetUnitUserData(u, unitData)
               
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                if GetLocalPlayer() == p then
                    call ForceUICancel()
                endif
                if GetLocalPlayer() == p then
                    call ClearSelection()
                    call SelectUnit(u, true)
                endif
             //   call BJDebugMsg("1")
                if not Syncing then
                    set Syncing = true
                    call SyncSelections()
                    set Syncing = false
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                else
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                endif
               
                if GetLocalPlayer() == p then
                    call ForceUICancel()
                endif
                call UnitRemoveAbility(u, B_ALL)
                call UnitAddAbility(u, A0)
                call UnitAddAbility(u, A1)
                call UnitAddAbility(u, A2)
                call UnitAddAbility(u, A3)
                call UnitAddAbility(u, AF)
               
                call TriggerSyncStart()
                call TriggerSyncReady()
               
               
               
                call broadcastint(count)
                set i = 0
                loop
                    exitwhen i == count
         //           call BJDebugMsg("BROADCASTING INT : " + I2S(Queue[i]))
                    call broadcastint(Queue[i])
                    set i = i + 1
                endloop
          //      call BJDebugMsg("3")
            endmethod
           
            public static method create takes player playerFor returns thistype
                local thistype this = thistype.allocate()
                set incoming = BinaryStream.create(2)
                set p = playerFor
                set u = null
                set Queue = Table.create()
                set popPos = 0
                set incomingCount = 0
                set incomingQueuePos = 0
               
                set incomingQueue = Table.create()
                set count = 0
                set unitData = UnitData.create(1, this)
                set fin = false
                return this
            endmethod
        endstruct
       
        struct StringQueuePacket extends array
            implement Alloc
            player player
            unit u
            UnitData unitData
            Table stringData
           
            Table bTable
            Table oTable
            string packet
            integer sDataIndex
            integer sCacheIndex
            integer packetIndex
            integer cacheIndex
           
            public method operator [] takes integer i returns string
                return stringData.string[i]
            endmethod
           
            public method wait takes boolean pause returns boolean
                if pause then
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                endif
                if packetIndex >= sCacheIndex and u != null then
                    call RemoveUnit(u)
                    set u = null
                endif
                return packetIndex >= sCacheIndex
            endmethod
           
            public method recieve takes integer i returns nothing
                local string name = GetObjectName(i)
              //  call BJDebugMsg("GOT")
                if name != "invalid" then
              //      call BJDebugMsg("not invalid")
                    if name == "/" then
                     //   call BJDebugMsg("PACKET : " + packet)
                    //    call BJDebugMsg(
                        set stringData.string[sDataIndex] = packet
                        set sDataIndex = sDataIndex + 1
                        set packet = ""
                    else
             //           call BJDebugMsg("PACKET : " + packet)
                        if name == "space" then
                            set packet = packet + " "
                        else
                            set packet = packet + name
                        endif
                    endif
                endif
                set packetIndex = packetIndex + 1
                if packetIndex > sCacheIndex then  
                    call Network_RemoveDummy(u)
                    set u = null
                endif
            endmethod
           
            public method broadcast takes nothing returns nothing
                local integer i = 0
                set sCacheIndex = cacheIndex
                set packet = ""
               
                set u= Network_GetDummy(player)
                call UnitRemoveAbility(u, A0)
                call UnitRemoveAbility(u, A1)
                call UnitRemoveAbility(u, A2)
                call UnitRemoveAbility(u, A3)
                call UnitRemoveAbility(u, AF)
                call UnitAddAbility(u,B_ALL)
                call SetUnitLifeBJ(u, 1)
                call SetUnitUserData(u, unitData)
               
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                if GetLocalPlayer() == player then
                    call ClearSelection(  )
                    call SelectUnit( u, true)
                endif
                if not Syncing then
                    set Syncing = true
                    call SyncSelections()
                    set Syncing = false
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                else
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                endif
               
                call ForceUIKey("Q")
               
             //       call BJDebugMsg("cacheINdex : " + I2S(cacheIndex))
         //   call BJDebugMsg("broadcast broadcast broadcast")
                loop
                    exitwhen i == cacheIndex
                        if GetRandomInt(0,10) == 1 then
                            call PrintTextConditional(GetLocalPlayer() == player, bCache[i])
                        endif
                    if GetLocalPlayer() == player then
               //         call BJDebugMsg("book cache : " + bCache[i])
                        call ForceUIKey(bTable.string[i])
                        call ForceUIKey(oTable.string[i])
                        call ForceUICancel()
                    endif
                   
                    set i = i + 1
                endloop
               
            endmethod
            public method add takes string orderKey returns nothing
                local integer asc = S2A(orderKey)
                if asc >= 'a' and asc <= 'k' then
                    set bTable.string[cacheIndex] = B_AK
                    set oTable.string[cacheIndex] = orderKey
                elseif asc >= 'l' and asc <= 'v' then
                    set bTable.string[cacheIndex] = B_LV
                    set oTable.string[cacheIndex] = orderKey
                elseif asc >= 'w' and asc <= 'z'  then
                    set bTable.string[cacheIndex] = B_WXYZ
                    set oTable.string[cacheIndex] = orderKey
                elseif asc == '/' then
                    set bTable.string[cacheIndex] = B_WXYZ
                    set oTable.string[cacheIndex] = "T"
                elseif asc == ' ' then
                    set bTable.string[cacheIndex] = B_WXYZ
                    set oTable.string[cacheIndex] = "B"
                elseif asc >= '0' and asc <= '9' then
                    set oTable.string[cacheIndex] = Ascii2Char(asc + 17)
                    set bTable.string[cacheIndex] = B_NUM
                elseif asc >= 'A' and asc <= 'K' then
                    set bTable.string[cacheIndex] = BIG_AK
                    set oTable.string[cacheIndex] = orderKey
                elseif asc >= 'L' and asc <= 'V' then
                    set bTable.string[cacheIndex] = BIG_LV
                    set oTable.string[cacheIndex] = orderKey
                elseif asc >= 'W' and asc <= 'Z' then
                    set bTable.string[cacheIndex] = BIG_WXYZ
                    set oTable.string[cacheIndex] = orderKey
                else
                    set oTable.string[cacheIndex] = "A"
                    set bTable.string[cacheIndex] = B_WXYZ
                endif
                set cacheIndex = cacheIndex + 1
            endmethod
           
            public method destroy takes nothing returns nothing
                set cacheIndex = 0
                call unitData.destroy()
                call stringData.destroy()
                call oTable.destroy()
                call bTable.destroy()
              //  if packetIndex >= sCacheIndex then  
                    call Network_RemoveDummy(u)
                    set u = null
                //endif
                call deallocate()
            endmethod
           
            public static method create takes player p returns thistype
                local thistype this = thistype.allocate()
                set player = p
                set unitData = UnitData.create(2, this)
                set stringData = Table.create()
                set oTable = Table.create()
                set bTable = Table.create()
                set cacheIndex = 0
                return this
            endmethod
        endstruct
       
        struct StringPacket extends array
            implement Alloc
            player p

            Table data
            integer length
            boolean hasRecievedLength
            boolean hasRecievedData
            IntegerQueuePacket lengthPacket
            StringQueuePacket dataPacket
            integer dataIndex
           
            public method pop takes nothing returns string
                set dataIndex = dataIndex + 1
                return dataPacket[dataIndex - 1]
            endmethod
           
            public method operator [] takes integer i returns string
                return dataPacket[i]
            endmethod
           
            private method broadcastData takes nothing returns nothing
                local integer i = length
                local integer ib = 0
                local string bc
                local string add
                local boolean b = GetLocalPlayer() == p
                local integer len
                set dataPacket = StringQueuePacket.create(p)
                loop
                    exitwhen ib == dataIndex
                    set bc = data.string[ib]
                    set i = 0
                    set len = lengthPacket.pop()
                    loop
                        exitwhen len == 0
                        set len = len - 1
                       
                        if b then
                            set add = SubString(bc, 0, 1)
                            set bc = SubString(bc, 1, StringLength(bc))
                        else
                            set add = ""
                        endif
                       
                        call dataPacket.add(add)
                       
                    endloop
                    call dataPacket.add("/")
                    set ib = ib + 1
                endloop
                //call dataPacket.add("/")
                call lengthPacket.destroy()
                call dataPacket.broadcast()
            endmethod
           
            private method compileData takes nothing returns nothing
                call data.flush()
                set dataIndex = 0
                /*local integer i = length
                local integer da
                local boolean b = false
                call data.flush()
                set dataIndex = 0
                loop
                    set da = dataPacket.pop()
                    exitwhen da == ' #^Q' or (b and da == 0)
                    set b = da == 0
                    if da == ' #^Z' then
                        set dataIndex = dataIndex + 1
                    else
                        set data.string[dataIndex] = data.string[dataIndex] + A2S(da)
                    endif
                endloop
                set dataIndex = 0
                call dataPacket.destroy()*/

            endmethod
           
           
            public method wait takes boolean pause returns boolean
                if not hasRecievedLength then
                    if lengthPacket.wait(false) then  
                 //       call BJDebugMsg("length packet")
                        call TriggerSyncStart()
                        call TriggerSyncReady()
                        set hasRecievedLength = true
                        call broadcastData()
                        set dataIndex = 0
                    endif
                elseif not hasRecievedData then
                 //   call BJDebugMsg("wating data")
                    if dataPacket.wait(false) then
                        set hasRecievedData = true
                        call compileData()
                    endif
                endif
               
                   
                if pause then
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                endif
                return hasRecievedData
            endmethod
            integer compDataLength
           
            public method broadcast takes nothing returns nothing
                call lengthPacket.broadcast()
            endmethod
           
            public method add takes string s returns nothing
                call lengthPacket.add(StringLength(s))
                set data.string[dataIndex] = s
                set dataIndex = dataIndex + 1
            endmethod
           
            public method destroy takes nothing returns nothing
                call data.destroy()
                call lengthPacket.destroy()
                call dataPacket.destroy()
                call deallocate()
            endmethod
           
            public static method create takes player pFor returns thistype
                local thistype this = thistype.allocate()
                set compDataLength = 0
                set p = pFor
                set data = Table.create()
                set lengthPacket = IntegerQueuePacket.create(pFor)
                return this
            endmethod
           
        endstruct
       
        private function onAbil takes nothing returns nothing
         //       call BJDebugMsg("RECIEVED ORDER : " + I2S(GetSpellAbilityId()))
       
            if GetUnitTypeId(GetTriggerUnit()) == 'h000' or GetUnitTypeId(GetTriggerUnit()) == Network_GetDummyId() then
           
                call UnitData(GetUnitUserData(GetTriggerUnit())).recieve(GetSpellAbilityId())
            endif
        endfunction
       
       
       
        private function init takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST )
            call TriggerAddAction( t, function onAbil )
            set t = null
            set dummyUnit = Network_GetDummy(Player(0))
            call UnitAddAbility(dummyUnit, B_ALL)
            call Network_RemoveDummy(dummyUnit)
           // call IntegerPacket.create(15,Player(0)).broadcast()
            set ORDERS[0] = O0
            set ORDERS[1] = O1
            set ORDERS[2] = O2
            set ORDERS[3] = O3
            set ABILS[0] = A0
            set ABILS[1] = A1
            set ABILS[2] = A2
            set ABILS[3] = A3
            set timerData = Table.create()
        endfunction
       
    endlibrary
    //old StringPacket, binary
    /*struct StringPacket extends array
            implement Alloc
            player p

            Table data
            integer length
            boolean hasRecievedLength
            boolean hasRecievedData
            IntegerQueuePacket lengthPacket
            IntegerQueuePacket dataPacket
            integer dataIndex
           
            public method pop takes nothing returns string
                set dataIndex = dataIndex + 1
                return data.string[dataIndex - 1]
            endmethod
           
            private method broadcastData takes nothing returns nothing
                local integer i = length
                local integer ib = 0
                local string bc
                local integer add = 0
                local boolean b = GetLocalPlayer() == p
                local integer len
                set dataPacket = IntegerQueuePacket.create(p)
                loop
                    exitwhen ib == dataIndex
                    set bc = data.string[ib]
                    set i = 0
                    set len = (lengthPacket.pop() - 1)/ 4 + 1
                    loop
                        exitwhen len == 0
                        set len = len - 1
                       
                        if b then
                            set add = S2A(SubString(bc, 0, 4))
                            set bc = SubString(bc, 4, StringLength(bc))
                        else
                            set add = 0
                        endif
                       
                        call dataPacket.add(add)
                       
                    endloop
                    call dataPacket.add(' #^Z')
                    set ib = ib + 1
                endloop
                    call dataPacket.add(' #^Q')
                call lengthPacket.destroy()
                call dataPacket.broadcast()
            endmethod
           
            private method compileData takes nothing returns nothing
                local integer i = length
                local integer da
                local boolean b = false
                call data.flush()
                set dataIndex = 0
                loop
                    set da = dataPacket.pop()
                    exitwhen da == ' #^Q' or (b and da == 0)
                    set b = da == 0
                    if da == ' #^Z' then
                        set dataIndex = dataIndex + 1
                    else
                        set data.string[dataIndex] = data.string[dataIndex] + A2S(da)
                    endif
                endloop
                set dataIndex = 0
                call dataPacket.destroy()
            endmethod
           
            public method destroy takes nothing returns nothing
                set p = null
                call deallocate()
            endmethod
           
            public method wait takes boolean pause returns boolean
                if not hasRecievedLength then
                    if lengthPacket.wait(false) then
                        set hasRecievedLength = true
                        call broadcastData()
                        set dataIndex = 0
                    endif
                elseif not hasRecievedData then
                    if dataPacket.wait(false) then
                        set hasRecievedData = true
                        call compileData()
                    endif
                endif
               
                   
                   
                if pause then
                    call TriggerSyncStart()
                    call TriggerSyncReady()
                endif
                return hasRecievedData
            endmethod
            integer compDataLength
            public method broadcast takes nothing returns nothing
                call lengthPacket.broadcast()
            endmethod
           
            public method add takes string s returns nothing
                call lengthPacket.add(StringLength(s))
                set data.string[dataIndex] = s
                set dataIndex = dataIndex + 1
            endmethod
           
            public static method create takes player pFor returns thistype
                local thistype this = thistype.allocate()
                set compDataLength = 0
                set p = pFor
                set data = Table.create()
                set lengthPacket = IntegerQueuePacket.create(p)
               
                return this
            endmethod
           
        endstruct*/


    obviously this isnt the entire system nor is it completed or optimized
     
  8. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Fixed ; P, mixed up the nicks, my bad =)
     
  9. Arhowk

    Arhowk

    Joined:
    Aug 8, 2007
    Messages:
    2,752
    Resources:
    0
    Resources:
    0
    :p

    unless things REALLY change, i'll be out of the wc3 modding scene for ~10 years except for weekends so my shitty undocumented research is still with me if someone wants it or to just start from scratch using the same reasoning.
     
    Last edited: Sep 14, 2014
  10. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    In other news, forgot to mention this, but Alloc will be getting an update to use Ruk's algorithm by default :). He will also get credits for his work in documentation.

    I still gotta clean up whatevet modules people asked me to clean up too for UnitIndexer and/or DDS :).

    No API changes planned for the foresseable future.

    UnitEvent also needs some loving so that it works with latest UnitIndexer, but i found a lot of new hidden flaws in it :(.

    So much to do and no coders willing to help for the overall betterment if the community :(.

    Who knows when I'll get to coding AttackIndexer. It's a revolutionairy system complete with solution. Free DC in Spells section to whoever codes it, lol.
     
  11. gorillabull

    gorillabull

    Joined:
    Jul 17, 2011
    Messages:
    1,368
    Resources:
    2
    Spells:
    2
    Resources:
    2
    could u elaborate what attack indexer should do
     
  12. Arhowk

    Arhowk

    Joined:
    Aug 8, 2007
    Messages:
    2,752
    Resources:
    0
    Resources:
    0
    so instead of doing 12-14 dmg, you actually do 1 damage and that would deal damage[1] = 13 dmg or etc

    sounds like a neat idea in theory but I see no way to control the damage that a unit deals without using bonus to add 1291293 dmg etc

    also inb4 damage is a real
     
    Last edited: Sep 14, 2014