- Joined
- Feb 27, 2007
- Messages
- 5,578
I want to select a unit for a player and immediately force a UI key once it's selected so the player just has to click a point and then it casts a spell. Problem is it seems like the key force doesn't work until 1 frame passes to update the UI (logical). So how can I slightly delay the execution of the code until the next frame is drawn? Just picking a number and delaying by that amount doesn't seem like a good idea because it's affected by latency and the actual GPU/CPU lag of the player. However, that's the method I'm using right now; the lowest number I've found to work is 0.025. Below 0.025 it only works if the unit to cast the spell is already selected by the player, which happens instantaneously.
JASS:
library ForceCast initializer Init requires GroupUtils
private keyword KeyPress
globals
private constant real ADD_DELAY = 0.05
private constant real CLEAN_DELAY = 0.50
private constant real LOOP_PERIOD = 0.025
private integer LP
private boolexpr CountBE
private integer count
private timer clock
private integer instances
private boolean running
private KeyPress array stack
endglobals
private struct KeyPress
unit u
integer pN
player p
integer a
integer lvl
integer lprev
string k
group select
static method create takes unit u, player p, integer a, integer l, integer lprev, string k returns thistype
local thistype new = thistype.allocate()
set new.u = u
set new.p = p
set new.pN = GetPlayerId(p)
set new.a = a
set new.lvl = l
set new.lprev = lprev
set new.k = k
set new.select = NewGroup()
return new
endmethod
method onDestroy takes nothing returns nothing
if .lprev == 0 then
call UnitRemoveAbility(.u, .a)
elseif .lvl != .lprev then
call SetUnitAbilityLevel(.u, .a, .lprev)
endif
endmethod
endstruct
private function CountGroup takes nothing returns boolean
set count = count+1
return true
endfunction
private function DelayedPress takes nothing returns nothing
local integer i = 0
local KeyPress kp
loop
set kp = stack[i]
if IsUnitSelected(kp.u, kp.p) then
if LP == kp.pN then
call ForceUIKey(kp.k)
call BJDebugMsg("success?")
//only if the delay is < 0.025
endif
set instances = instances-1
if instances < 1 then
set running = false
call PauseTimer(clock)
set stack[0] = 0
exitwhen true
else
set stack[i] = stack[instances]
set stack[instances] = 0
set i = i-1
endif
endif
set i = i+1
exitwhen i>=instances
endloop
endfunction
function ForcePlayerUnitSpellcast takes unit caster, player castPlayer, integer abilityID, integer level, string hotkey returns nothing
local integer lprev = GetUnitAbilityLevel(caster, abilityID)
local boolean isSelect = IsUnitSelected(caster, castPlayer)
local boolean didAdd = false
local boolean didSelect = false
local KeyPress kp = KeyPress.create(caster, castPlayer, abilityID, level, lprev, hotkey)
set count = 0
call GroupEnumUnitsSelected(kp.select, castPlayer, CountBE)
if not isSelect or (isSelect and count>1) then
set didSelect = true
if LP == kp.pN then
call ClearSelection()
call SelectUnit(caster, true)
endif
endif
if lprev == 0 then
set didAdd = UnitAddAbility(caster, abilityID)
endif
if level != 1 and lprev != level then
call SetUnitAbilityLevel(caster, abilityID, level)
endif
if didSelect then//or didAdd then
set stack[instances] = kp
set instances = instances+1
if not running then
set running = true
call TimerStart(clock, LOOP_PERIOD, true, function DelayedPress)
call BJDebugMsg("wait")
endif
else
if LP == kp.pN then
call ForceUIKey(kp.k)
call BJDebugMsg("forced")
endif
endif
if not (didSelect or didAdd) then
// call TimerStart(kp.t, CLEAN_DELAY, false, function Cleanup)
endif
endfunction
private function Init takes nothing returns nothing
set LP = GetPlayerId(GetLocalPlayer())
set CountBE = Filter(function CountGroup)
set clock = NewTimer()
set instances = 0
set running = false
endfunction
endlibrary