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

Run global function from local player blocks!

Status
Not open for further replies.
Level 24
Joined
Aug 1, 2013
Messages
4,657
After messing around with my UI system, I suddenly had a few nice ideas for my UIButton, which lead me to a bothersome situation where I had an if statement that checked some data of a local player but had to execute an event for all players (as a button click could essentially be buying/selling an item, learning/leveling an ability, joining/leaving a team, selecting a unit (hero), or whatever).

I didnt end up having to use this script to make it work, but I think it is still pretty neat to have:
JASS:
//! novjass
struct Function
    public static method create takes code execution returns thistype
    public method run takes nothing returns nothing
//! endnovjass

For example a camera position event...
Sending actual data is not done by this script.
JASS:
struct Function
    ////////////////////////////////////////////////////////
    // BE AWARE NOT TO CALL .run() AS TRIGGER EVALUATION! //
    ////////////////////////////////////////////////////////
  
    private static constant group SELECTION = CreateGroup()
  
    private static constant player DUMMY_OWNER = Player(15)
    private static constant integer DUMMY_TYPE = 'h000'
    private static constant real DUMMY_X = -2560
    private static constant real DUMMY_Y = -2560
  
    private unit dummy
    private trigger trig
  
    public static method create takes code execution returns thistype
        local thistype this = .allocate()
      
        // create dummy, link struct instance, add ghost and remove pathing.
        // create trigger and add execution as Condition().
      
        set .dummy = CreateUnit(.DUMMY_OWNER, .DUMMY_TYPE, .DUMMY_X, .DUMMY_Y, 0)
        call SetUnitUserData(.dummy, this)
        call UnitAddAbility(.dummy, 'Aeth')
        call SetUnitPathing(.dummy, false)
      
        set .trig = CreateTrigger()
        call TriggerAddCondition(.trig, Condition(execution))
      
        return this
    endmethod
  
    public method run takes nothing returns nothing
        local unit FoG
      
        // save previous selection
        // select dummy
        // re-select previous selection
      
        call GroupEnumUnitsSelected(.SELECTION, GetLocalPlayer(), null)
        call ClearSelection()
        call SelectUnit(.dummy, true)
        call ClearSelection()
        loop
            set FoG = FirstOfGroup(.SELECTION)
            exitwhen FoG == null
            call GroupRemoveUnit(.SELECTION, FoG)
          
            call SelectUnit(FoG, true)
        endloop
    endmethod
  
    private static method onSelect takes nothing returns boolean
        local unit u = GetTriggerUnit()
        local thistype this
        if GetUnitTypeId(u) == .DUMMY_TYPE then
            set this = GetUnitUserData(u)
            call TriggerEvaluate(.trig)
        endif
        set u = null
        return false
    endmethod
  
    private static method onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SELECTED)
        call TriggerAddCondition(t, Condition(function thistype.onSelect))
    endmethod
  
endstruct
JASS:
struct FunctionTest
  
    private static boolean isInside = false // local data (aka, can and will be different for different players)
    private static Function func
  
    private static method onActivated takes nothing returns nothing
        call BJDebugMsg("Camera entered region for player "+GetPlayerName(GetTriggerPlayer())+"("+I2S(GetPlayerId(GetTriggerPlayer()))+").")
    endmethod
  
    private static method onInterval takes nothing returns nothing
        local real x = GetCameraTargetPositionX()
        local real y = GetCameraTargetPositionY()
      
        if RectContainsCoords(gg_rct_Region_000, x, y) then
            if not .isInside then
                set .isInside = true
                //entered region
                call .func.run()
            endif
        else
            if .isInside then
                set .isInside = false
                //left region
            endif
        endif
    endmethod
  
    private static method onInit takes nothing returns nothing
        set .func = Function.create(function thistype.onActivated)
        call TimerStart(CreateTimer(), 0.03, true, function thistype.onInterval)
    endmethod
  
endstruct
 
Status
Not open for further replies.
Top