• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[vJASS] Delay code execution by 1 frame

Status
Not open for further replies.
Level 45
Joined
Feb 27, 2007
Messages
5,578
Anyone know how to do this? A bug/trick or some special combination of timers and .execute()s or whatever is all fine. If there's a way to hook something into the internal screen refresh call that would be cool. I know I could just use a 0.1 timeout timer or something but I'd like the delay to be as short as possible.

I want to do this because the UI needs 1 frame to update after selecting a unit, enabling a spell for a player, or adding a spell to a unit before it appears on the command card UI and will thus work with ForceUIKey.

JASS:
globals
    unit u = SetSomewhere()
    player p = SetSomewhereElse()
    integer a = 'A000'
    string hky = "f"
endglobals

function myfunc takes nothing returns nothing
    call UnitAddAbility(u, a)
//  Neither works without delaying by 1 frame
//  call SetPlayerAbilityAvailable(p, a, true)
    if GetLocalPlayer() == p then
        call SelectUnit(u, true)
        // This is where it would go
        call DelayByFrames(1)
        // ^^^
        call ForceUIKey(hky)
    endif
endfunction

//
// Something in this vein is also acceptable:
//

globals
    unit u = SetSomewhere()
    player p = SetSomewhereElse()
    integer a = 'A000'
    string hky = "f"
endglobals

function Press takes nothing returns nothing
    if GetLocalPlayer() == p then
        call ForceUIKey(hky)
    endif
endif

function myfunc takes nothing returns nothing
    call UnitAddAbility(u, a)
//  Neither works without delaying by 1 frame
//  call SetPlayerAbilityAvailable(p, a, true)
    if GetLocalPlayer() == p then
        call SelectUnit(u, true)
        // This is where it would go
        call Press.executeAfterFrames(1)
        // ^^^
    endif
endfunction

Thoughts?
 
I would try selecting the unit first (locally), then add the ability (globally), then force the UI key (locally). Like so:
JASS:
if GetLocalPlayer() == p then
    call SelectUnit(u, true)
endif
call UnitAddAbility(u, a)
if GetLocalPlayer() == p then
    call ForceUIKey(hky)
endif

iirc, adding an ability will force-update the unit's command card. Or was it removing it? (if so, try adding/removing a dummy ability) Killing a unit also works for this.

But I don't entirely know if it would work in your case. It is still worth a shot. If that doesn't work, then your best bet is to use a timer and test how low it needs to be (start at 0, which is the minimum possible timeout). Once you get that goldilocks value, you should try testing it in multiplayer to make sure that the delay-requirement isn't related to synching or anything, because then the timer-delay might need to be longer.
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
I would try selecting the unit first (locally), then add the ability (globally), then force the UI key (locally).
I tried doing it all globally before and it didn't work. I'm skeptical that this would affect the outcome here, but I can try playing more with it.
  • Esc
    • Events
      • Player - Player 6 (Orange) skips a cinematic sequence
    • Conditions
    • Actions
      • Custom script: call BJDebugMsg("ESC")
      • Selection - Select No unit for Player 6 (Orange)
      • Selection - Select Far Seer 0014 <gen> for Player 6 (Orange)
      • Unit - Add Flare to Far Seer 0014 <gen>
      • Custom script: call ForceUIKey("f")
iirc, adding an ability will force-update the unit's command card. Or was it removing it? (if so, try adding/removing a dummy ability)
Doesn't work, even if the unit I'm adding the ability to is already selected by the player. Tried this:
  • Esc
    • Events
      • Player - Player 6 (Orange) skips a cinematic sequence
    • Conditions
    • Actions
      • Custom script: call BJDebugMsg("ESC")
      • Unit - Add Flare to Far Seer 0014 <gen>
      • Unit - Add Acid Bomb to Far Seer 0014 <gen>
      • Unit - Remove Acid Bomb from Far Seer 0014 <gen>
      • Custom script: call ForceUIKey("f")
Killing a unit also works for this.
You mean killing the unit I want to force a ui key for? Or killing some other random unit?
Once you get that goldilocks value, you should try testing it in multiplayer to make sure that the delay-requirement isn't related to synching or anything, because then the timer-delay might need to be longer.
I really want to avoid this because if a player is lagging significantly then even a 0.25 timer callback might not take enough time (realize that's 4 fps, but leaky maps do happen and this is for a system). FWIW 0.02 seems to be the minimum reliable time.
 
You mean killing the unit I want to force a ui key for? Or killing some other random unit?

I meant that killing a unit will force-refresh the UI. But if the add/remove ability trick didn't work, then I don't think the issue is related to the UI not being updated. It is probably some other internal thing.

I really want to avoid this because if a player is lagging significantly then even a 0.25 timer callback might not take enough time (realize that's 4 fps, but leaky maps do happen and this is for a system). FWIW 0.02 seems to be the minimum reliable time.

I think it should still work. Timers use game time, not real time, so afaik the fps shouldn't matter. When fps goes down, it'll just drop frames that would've been rendered, but all the unit states and stuff are still calculated. So if you had two computers side-by-side, one with 4 fps and one with 60 fps, and you ran it for a second (and did whatever add + force key thing), it should end up at roughly the same state. The 4 fps one will just be jittery.
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
I don't think the issue is related to the UI not being updated. It is probably some other internal thing.
You're right. It's just some internal delay about adding abilities and hotkeys for them. I just tried
JASS:
call UnitAddAbility(u, 'book') //default spell book with hotkey b
call ForceUIKey('b')
call ForceUIKey('r')
and the unit casts roar just fine. Clearly it doesn't need a frame to change to the spell book but just pressing r myself doesn't activate roar unless I'm already in it (duh). This, however, still doesn't work unless the unit already has 'book' and is selected by the player. Calling SelectUnit(u,true) doesn't change the outcome at all-- it has to be in the player's selection before the function runs.
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
You could try to give the spell book by default, then add other abilities so the spell book is not in the chart any more, then wait until someone activates the channel ability (to target a unit with your script) and then remove the cast ability so the spell book will be in the chart.

IIrc, disabling/enabling it doesnt work either.

But indeed, once you are in the spell book, you dont have to do some wait trick to press the next hotkey.
 
Status
Not open for further replies.
Top