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

[vJASS] I hit the op limit, a little help here

Status
Not open for further replies.
Level 16
Joined
Mar 3, 2006
Messages
1,564
I am making this full screen inventory for the sake of learning, it uses too many nested loops and it hit the op limit so I split the code into different threads.

JASS:
    globals

        string BIG_MSG
        integer opLim = 0
        integer MAX_OP_LIM = 1444
        
        // Carry-Over (CO) variables
        integer CO_pid = 0
        integer CO_r   = 0
        integer CO_c   = 0
        integer CO_i   = 0
        integer CO_track_id = 0
        real    CO_x   = 0.
        real    CO_x1  = 0.
        real    CO_y   = 0.
        real    CO_y1  = 0.

        integer PLAYER_INGAME_COUNT = 2

        hashtable Data   = InitHashtable()

        string TRACK_MODEL        = "war3mapImported\\Track75.mdx"
        integer INV_ABILITY_ID    = 'I000'
        integer BASE_MODEL_ID     = 'B000'
        integer SELECTOR_MODEL_ID = 'B001'

        integer MAX_ROW_COUNT = 22
        integer MAX_COL_COUNT = 23
        integer MAX_SIZE      = MAX_ROW_COUNT * MAX_COL_COUNT
        integer MAX_ITEMS

        integer rowKey  = 1
        integer colKey  = 21
        integer trackKey = 41
        integer itemTableKey = -100

        real OFFSET_X = 83.75
        real OFFSET_Y = OFFSET_X//84.00
        real BORDER_SIZE = 100.00
        real ICON_WIDTH = 80.00
        real ICON_HEIGHT = 80.00
        real BASE_X =  - 2816
        real BASE_Y =    2816

        real H = 1.2 * RMaxBJ(( OFFSET_X * ( MAX_COL_COUNT - 1 ) )+ICON_WIDTH , ( OFFSET_Y * ( MAX_ROW_COUNT - 1 ) )+ICON_HEIGHT )

        trigger onClick  = CreateTrigger()
        trigger onTrack  = CreateTrigger()
        trigger onOpen   = CreateTrigger()
        trigger onAquire = CreateTrigger()

        timer cameraLockTimer = CreateTimer()

        integer array groundItemId
        integer array itemIcon
        integer array itemType
        ability array itemEffect
        string  array itemName
        string  array itemDescription

        boolean     array IsAnySlotSelected
        boolean     array IsInventoryOpened
        integer     array pRow
        integer     array pCol
        integer     array prevTrackId
        integer     array globalUnitId
        camerasetup array inventoryCamera
        camerasetup array initialCamera
    endglobals



    function itemDatabase takes nothing returns nothing
        local integer i
        set i = 1
        set itemType[i] = i
        set itemIcon[i] = 'Z000'
        set groundItemId[i] = 'P000'
        set itemName[i] = "Shaman Claw"
        set itemDescription[i] = ""
        set itemEffect[i] = null
        call SaveInteger( Data , itemTableKey , groundItemId[i] , i )

        set i = i + 1
        set itemType[i] = i
        set itemIcon[i] = 'Z001'
        set groundItemId[i] = 'P001'
        set itemName[i] = "Amulet"
        set itemDescription[i] = ""
        set itemEffect[i] = null
        call SaveInteger( Data , itemTableKey , groundItemId[i] , i )

        set i = i + 1
        set itemType[i] = i
        set itemIcon[i] = 'Z002'
        set groundItemId[i] = 'P002'
        set itemName[i] = "Orb of Fire"
        set itemDescription[i] = ""
        set itemEffect[i] = null
        call SaveInteger( Data , itemTableKey , groundItemId[i] , i )

        set i = i + 1
        set itemType[i] = i
        set itemIcon[i] = 'Z003'
        set groundItemId[i] = 'P003'
        set itemName[i] = "Orb of Frost"
        set itemDescription[i] = ""
        set itemEffect[i] = null
        call SaveInteger( Data , itemTableKey , groundItemId[i] , i )

        /*
        set i = i + 1
        set itemType[i] = i
        set itemIcon[i] = 'Z003'
        set groundItemId[i] = 'dust'
        set itemName[i] = "Dust of Appearance"
        set itemDescription[i] = ""
        set itemEffect[i] = null
        call SaveInteger( Data , itemTableKey , groundItemId[i] , i )
        */

        set MAX_ITEMS = i
    endfunction



    function showInterface takes integer itemId , integer slotId returns nothing
        local destructable d = LoadDestructableHandle( Data , itemId , slotId )
        call ShowDestructable( d , true )
    endfunction



    function hideInterface takes integer itemId , integer slotId returns nothing
        local destructable d = LoadDestructableHandle( Data , itemId , slotId )
        if itemId != -1 then
            call ShowDestructable( d , false )
        endif
    endfunction



    function initiateInventoryForUnit takes unit whichUnit returns nothing
        local integer r
        local integer c
        local integer trackId
        local integer unitId = GetHandleId(whichUnit)
        local player p = GetOwningPlayer(whichUnit)
        local integer pid = GetPlayerId(p)

        call UnitAddAbility( whichUnit , INV_ABILITY_ID )

            set r = 1
            loop
                exitwhen r > MAX_ROW_COUNT
                set c = 1
                loop
                    exitwhen c > MAX_COL_COUNT
                    set trackId = LoadInteger( Data , -pid - trackKey , r * MAX_SIZE + c )
                    call SaveInteger( Data , unitId , trackId , -1 )
                    set c = c + 1
                endloop
                set r = r + 1
            endloop

    endfunction



    function loadInventoryForUnit takes unit whichUnit returns nothing
        local integer r
        local integer c
        local integer trackId
        local integer itemId
        local integer unitId = GetHandleId(whichUnit)
        local player p = GetOwningPlayer(whichUnit)
        local integer pid = GetPlayerId(p)

            set r = 1
            loop
                exitwhen r > MAX_ROW_COUNT
                set c = 1
                loop
                    exitwhen c > MAX_COL_COUNT
                    set trackId = LoadInteger( Data , -pid - trackKey , r * MAX_SIZE + c )
                    set itemId = LoadInteger( Data , unitId , trackId )
                    call showInterface( itemId , trackId )
                    set c = c + 1
                endloop
                set r = r + 1
            endloop

    endfunction



    function onClick_Actions takes nothing returns nothing
        local integer unitId
        local integer trackId
        local integer pid
        local trackable trigTrack
        local player trigPlayer
        local integer row
        local integer col
        local integer previousItemId
        local integer currentItemId
        local destructable selector

        set trigPlayer = GetLocalPlayer()
        set pid        = GetPlayerId( trigPlayer )
        set trigTrack  = GetTriggeringTrackable()
        set trackId    = GetHandleId( trigTrack )
        set unitId     = globalUnitId[pid]
        set row        = LoadInteger( Data , -pid - rowKey , trackId )
        set col        = LoadInteger( Data , -pid - colKey , trackId )

        if IsAnySlotSelected[pid] == false then
            set pRow[pid] = row
            set pCol[pid] = col
            set prevTrackId[pid] = trackId
            // Show Selector
            set selector = LoadDestructableHandle( Data , -2 , trackId )
            call ShowDestructable( selector , true )
            set IsAnySlotSelected[pid] = true
        else
            // Get item Id in slot pRow,pCol
            set previousItemId = LoadInteger( Data , unitId , prevTrackId[pid] )
            // Get item Id in slot r,c
            set currentItemId  = LoadInteger( Data , unitId , trackId )
            // swap slot item ids data
            if previousItemId != currentItemId and previousItemId != -1 then
                call SaveInteger( Data , unitId , trackId          , previousItemId )
                call SaveInteger( Data , unitId , prevTrackId[pid] , currentItemId  )
                // Showing and Hiding Interfaces
                call showInterface(previousItemId,trackId)
                call showInterface(currentItemId,prevTrackId[pid])
                call hideInterface(previousItemId,prevTrackId[pid])
                call hideInterface(currentItemId,trackId)
            endif

            // Hide Selector
            set selector = LoadDestructableHandle( Data , -2 , prevTrackId[pid] )
            call ShowDestructable( selector , false )
            set IsAnySlotSelected[pid] = false
        endif
    endfunction



    function onTrack_Actions takes nothing returns nothing
    endfunction



    function onOpen_Actions takes nothing returns nothing
        local unit inventoryUnit = GetTriggerUnit()
        local integer unitId = GetHandleId( inventoryUnit )
        local player p = GetOwningPlayer( inventoryUnit )
        local integer pid = GetPlayerId( p )

        if ( GetLocalPlayer() == p ) then
            set globalUnitId[pid] = unitId // a global variable that will be used in the 'onClick' and 'onTrack' function
            if IsInventoryOpened[pid] == false then
                set IsInventoryOpened[pid] = true
                set initialCamera[pid] = GetCurrentCameraSetup()
                call CameraSetupApplyForceDuration(inventoryCamera[pid] , true , 0 )
                call loadInventoryForUnit( inventoryUnit )
            else
                set IsInventoryOpened[pid] = false
                call CameraSetupApplyForceDuration(initialCamera[pid] , true , 0 )
            endif
        endif
    endfunction



    function fullInventory takes integer powerupId , unit aquiringUnit , integer pid returns nothing
        local real x = GetUnitX( aquiringUnit )
        local real y = GetUnitY( aquiringUnit )
        call CreateItem(powerupId,x,y)
        call SimError(Player(pid) , "Backpack Inventory is Full" )
    endfunction



    function getNextEmptySlot takes integer pid , integer unitId returns integer
        local integer r
        local integer c
        local integer trackId
        local integer itemId

        set r = 1
        loop
            exitwhen r > MAX_ROW_COUNT
            set c = 1
            loop
                exitwhen c > MAX_COL_COUNT

                set trackId = LoadInteger( Data , -pid - trackKey , r * MAX_SIZE + c )
                set itemId  = LoadInteger( Data , unitId , trackId )

                if itemId == -1 then
                    return trackId
                endif

                set c = c + 1
            endloop
            set r = r + 1
        endloop

        return -1
    endfunction



    function onAquire_Actions takes nothing returns nothing
        local item aquiredItem = GetManipulatedItem()
        local integer powerupId = GetItemTypeId( aquiredItem )
        local integer i = LoadInteger( Data , itemTableKey , powerupId )
        local unit aquiringUnit = GetTriggerUnit()
        local integer unitId = GetHandleId(aquiringUnit)
        local player p = GetOwningPlayer(aquiringUnit)
        local integer pid = GetPlayerId(p)
        local integer emptySlotId

        set emptySlotId = getNextEmptySlot( pid , unitId)
        if emptySlotId != -1 then
            call SaveInteger( Data , unitId , emptySlotId , itemType[i] )
            call showInterface( itemType[i] , emptySlotId )
        else
            call fullInventory( powerupId , aquiringUnit , pid )
        endif
    endfunction



    function itemsConstruction takes nothing returns nothing
        local integer i
        local real x  = CO_x
        local real y  = CO_y
        local integer track_id = CO_track_id
        local destructable temp_destruct
        
        set i = 1
        loop // Creating the dummy destructables for all available items
            exitwhen i > MAX_ITEMS
            set temp_destruct = CreateDestructable( itemIcon[i] , x , y , 0 , 1 , 0 )
            call SaveDestructableHandle( Data , itemType[i] , track_id , temp_destruct )
            call ShowDestructable( temp_destruct , false )
            //set opLim = opLim + 1

            // Check for operation limit of the thread
            /*if opLim >= MAX_OP_LIM then
                // Passing variables values to the Carry-Over variables
                set CO_pid = pid
                set CO_r   = r
                set CO_c   = c
                set CO_i   = i
                return
            endif*/
            set i = i + 1
        endloop
    endfunction
    
    
    
    function slotConstruction takes nothing returns nothing
        local integer pid = CO_pid
        local real x1 = CO_x1
        local real y1 = CO_y1
        local real x  = CO_x
        local real y  = CO_y
        local integer r = 1
        local integer c
        local integer track_id
        local trackable slotBase
        local destructable temp_destruct
    

        loop
            exitwhen r > MAX_ROW_COUNT
            set c = 1
            loop
                exitwhen c > MAX_COL_COUNT
                set x = x1 + ( OFFSET_X * ( c - 1 ) )
                set y = y1 - ( OFFSET_Y * ( r - 1 ) )
                set slotBase = CreateTrackable( TRACK_MODEL , x , y , 0 )
                set track_id = GetHandleId( slotBase )

                //call TriggerSleepAction(0.0)
                set BIG_MSG = "Player_ID: |cffFFCC00" + I2S(pid) +/*
                */ "|r, Row#: |cffFFCC00" + I2S(r) +/*
                */ "|r, Col#: |cffFFCC00" + I2S(c) +/*
                */ "|r,Trackable_ID: |cffFFCC00" + I2S(track_id) + "|r"
                call DisplayTimedTextToPlayer(Player(0),0,0,60,BIG_MSG)

                call SaveInteger( Data , -pid - rowKey  , track_id , r)
                call SaveInteger( Data , -pid - colKey  , track_id , c)
                call SaveInteger( Data , -pid - trackKey , r * MAX_SIZE + c , track_id )
                call TriggerRegisterTrackableHitEvent  ( onClick , slotBase )
                call TriggerRegisterTrackableTrackEvent( onTrack , slotBase )
                set temp_destruct = CreateDestructable( BASE_MODEL_ID , x , y , 0 , 1 , 0 )
                call SaveDestructableHandle( Data , -1 , track_id , temp_destruct )
                set temp_destruct = CreateDestructable( SELECTOR_MODEL_ID , x , y , 0 , 1 , 0 )
                call SaveDestructableHandle( Data , -2 , track_id , temp_destruct )
                call ShowDestructable( temp_destruct , false )

                // Passing variables values to the Carry-Over variables
                set CO_x   = x
                set CO_y   = y
                set CO_track_id = track_id
                // Start a new thread
                call ForForce(bj_FORCE_PLAYER[0],function itemsConstruction)
                
                // Test Counter
                set opLim = opLim + 1

                set c = c + 1
            endloop
            set r = r + 1
        endloop
        //call BJDebugMsg("Construction Complete")
        call DisplayTimedTextToPlayer(Player(0),0,0,60,I2S(opLim))
    endfunction



    function baseLayoutConstruction takes nothing returns nothing
        local integer pid
        local real x1
        local real y1
        local real x
        local real y
        local camerasetup temp_cam

        //call BJDebugMsg(R2S(H)) // Displays the value that will be applied to Camera Field: Target Distance
        set pid = 0
        loop
            exitwhen pid >= PLAYER_INGAME_COUNT
            set x1 = BASE_X + pid * (( MAX_COL_COUNT * OFFSET_X) + BORDER_SIZE)
            set y1 = BASE_Y //- pid * (( MAX_ROW_COUNT * OFFSET_Y) + BORDER_SIZE)

            // Creating camera setups
            set x = x1 + (( OFFSET_X * ( MAX_COL_COUNT - 1 ) )/2)
            set y = y1 - (( OFFSET_Y * ( MAX_ROW_COUNT - 1 ) )/2)

            set temp_cam = CreateCameraSetup()
            call CameraSetupSetField( temp_cam, CAMERA_FIELD_ZOFFSET        ,   0.0 , 0.0)
            call CameraSetupSetField( temp_cam, CAMERA_FIELD_ROTATION       ,  90.0 , 0.0)
            call CameraSetupSetField( temp_cam, CAMERA_FIELD_ANGLE_OF_ATTACK, 270.0 , 0.0)
            call CameraSetupSetField( temp_cam, CAMERA_FIELD_TARGET_DISTANCE,  H    , 0.0)
            call CameraSetupSetField( temp_cam, CAMERA_FIELD_ROLL           ,   0.0 , 0.0)
            call CameraSetupSetField( temp_cam, CAMERA_FIELD_FIELD_OF_VIEW  , 120.0 , 0.0)
            call CameraSetupSetField( temp_cam, CAMERA_FIELD_FARZ           , 5000.0, 0.0)
            call CameraSetupSetDestPosition(temp_cam, x , y , 0.0)
            set inventoryCamera[pid] = temp_cam

            // Passing variables values to the Carry-Over variables
            set CO_pid = pid
            set CO_x   = x
            set CO_x1  = x1
            set CO_y   = y
            set CO_y1  = y1
            // Start a new thread
            call ForForce(bj_FORCE_PLAYER[0],function slotConstruction)

            set pid = pid + 1
        endloop
    endfunction



    function misc takes nothing returns nothing
        call FogModifierStart(CreateFogModifierRect(Player(0),FOG_OF_WAR_VISIBLE,bj_mapInitialPlayableArea,true,false))
    endfunction



function actn takes nothing returns nothing
    if ( GetUnitTypeId(GetFilterUnit()) == 'Hpal' ) then
        call initiateInventoryForUnit( GetEnumUnit() )
    endif
endfunction

function init_units takes nothing returns nothing
    set bj_wantDestroyGroup = true
    call ForGroupBJ( GetUnitsInRectMatching(GetPlayableMapRect(), null), function actn )
endfunction



    function InitTrig_FSI takes nothing returns nothing
        call TriggerRegisterAnyUnitEventBJ( onOpen, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerRegisterAnyUnitEventBJ( onAquire , EVENT_PLAYER_UNIT_PICKUP_ITEM )
        call TriggerAddAction( onClick  , function onClick_Actions  )
        call TriggerAddAction( onTrack  , function onTrack_Actions  )
        call TriggerAddAction( onOpen   , function onOpen_Actions   )
        call TriggerAddAction( onAquire , function onAquire_Actions )
        call misc()
        call itemDatabase()
        call ForForce(bj_FORCE_PLAYER[0],function baseLayoutConstruction)
        //call baseLayoutConstruction()

        // initiate an empty inventory for an example unit
        call initiateInventoryForUnit( gg_unit_Hpal_0012 )
        call init_units()
        call SelectUnit(gg_unit_Hpal_0012, true)

    endfunction

But I need to make some sort of a loop or a general routine that split automatically for any number of rows and/or columns.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
A timer opens a new independent thread. Well, I see you have already outsourced the loop and passed globals. So you only need to add the counter and start the function anew (and pass parameters anew) at the end:

JASS:
    function slotConstruction takes nothing returns nothing
        local integer pid = CO_pid
        local real x1 = CO_x1
        local real y1 = CO_y1
        local real x  = CO_x
        local real y  = CO_y
        local integer r = CO_r
        local integer c = CO_c
        local integer track_id
        local trackable slotBase
        local destructable temp_destruct
        local integer threadIteration = 1
   

        loop
            exitwhen r > MAX_ROW_COUNT

            if c > MAX_COL_COUNT then
                set c = 1
            endif

            loop
                exitwhen c > MAX_COL_COUNT
                set x = x1 + ( OFFSET_X * ( c - 1 ) )
                set y = y1 - ( OFFSET_Y * ( r - 1 ) )
                set slotBase = CreateTrackable( TRACK_MODEL , x , y , 0 )
                set track_id = GetHandleId( slotBase )

                set BIG_MSG = "Player_ID: |cffFFCC00" + I2S(pid) +/*
                */ "|r, Row#: |cffFFCC00" + I2S(r) +/*
                */ "|r, Col#: |cffFFCC00" + I2S(c) +/*
                */ "|r,Trackable_ID: |cffFFCC00" + I2S(track_id) + "|r"
                call DisplayTimedTextToPlayer(Player(0),0,0,60,BIG_MSG)

                call SaveInteger( Data , -pid - rowKey  , track_id , r)
                call SaveInteger( Data , -pid - colKey  , track_id , c)
                call SaveInteger( Data , -pid - trackKey , r * MAX_SIZE + c , track_id )
                call TriggerRegisterTrackableHitEvent  ( onClick , slotBase )
                call TriggerRegisterTrackableTrackEvent( onTrack , slotBase )
                set temp_destruct = CreateDestructable( BASE_MODEL_ID , x , y , 0 , 1 , 0 )
                call SaveDestructableHandle( Data , -1 , track_id , temp_destruct )
                set temp_destruct = CreateDestructable( SELECTOR_MODEL_ID , x , y , 0 , 1 , 0 )
                call SaveDestructableHandle( Data , -2 , track_id , temp_destruct )
                call ShowDestructable( temp_destruct , false )

                // Passing variables values to the Carry-Over variables
                set CO_x   = x
                set CO_y   = y
                set CO_track_id = track_id
                // Start a new thread
                call ForForce(bj_FORCE_PLAYER[0],function itemsConstruction)
               
                // Test Counter
                set opLim = opLim + 1

                set c = c + 1

                set threadIteration = threadIteration + 1
                exitwhen threadIteration > MAX_ITERATIONS_PER_THREAD
            endloop
            set r = r + 1
        endloop

        if threadIteration > MAX_ITERATIONS_PER_THREAD and (r <= MAX_ROW_COUNT or c <= MAX_COL_COUNT) then
            set CO_pid = pid
            set CO_x   = x
            set CO_x1  = x1
            set CO_y   = y
            set CO_y1  = y1
            set CO_r = r
            set CO_c = c
            // Start a new thread
            call ForForce(bj_FORCE_PLAYER[0],function slotConstruction)
        endif
    endfunction

edit: Wait a sec... Thought you had done so before, but you need to pass the current row/column positions as well. Initialize them by your caller.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
The overview is not online anymore. A thread can do up to 300k microoperations but really like everything counts to it: Reading variables, setting variables, with, without array, calling a function, comparisons and control structures, which is why you cannot quite insert debug stuff without altering it. They also have different prices. Your inner function calls might have iterations or selections itself, in which case their cost varies.
 
Status
Not open for further replies.
Top