Problems With Timer etc

inevit4ble

Well-Known Member
Reaction score
38
Hi Every1,

Ok, the desired effect of this spell is to:
Pause Trigger Unit
Lock camera for owning player to unit
Disable control for player
Create SFX
Display Text
Start Timer for 6 sec

Upon Timer end it is meant to:
Reset camera
Enable control
Destroy SFX
Set Unit HP to 100%
Reset Cooldowns for unit
Display Text
Unpause Unit

Also it needs to check if any enemies are in range, if more than 1 then no effects occur
And if unit has taken damage within the last 20sec, if true then no effects occur
I haven't started on the damage check yet, I wanted to get the rest of the stuff to work first​

So far:
Casting spell triggers script
Unit is paused
SFX is created
Text is displayed

Main Problem == Timer doesn't seem to end/run its handler so I don't know if the second half of the stuff works or not

Other Problems:
How do I order a unit to "stop"?
How do I pan/lock camera to unit?
How do I Enable/Disable Control for Player?
Is there anything else I am doing wrong?

I've tried what I can but wrapped them in " /* " " */ " when I couldn't get it :(

Thanks a lot! :)

JASS:
scope Rest initializer Init
//========================================================
//====================SET UP==============================
globals
    private constant integer rest = 'A02E'
    private constant string ZZZsfx = "Abilities\\Spells\\Other\\CreepSleep\\CreepSleepTarget.mdl"
    private constant integer dmy = 'h00C'
endglobals
//========================================================
//====================END UP==============================     
//========================================================
globals
    private effect array zzz
    private timer array dur
    private group g
    private unit array char
    private boolexpr b
endglobals
//========================================================
    private function RestAoE takes unit u returns boolean
        return (GetWidgetLife(u) > 0.405)
    endfunction
    
    private function pick takes nothing returns boolean
        return RestAoE(GetFilterUnit())
    endfunction

//========================================================
    private function UnitHpAdd takes unit u returns real
        local real max
        local real cur
        
        
        set max = GetUnitState(u, UNIT_STATE_MAX_LIFE)
        set cur = GetUnitState(u, UNIT_STATE_LIFE)
        
        return max - cur
    endfunction
    
    private function restEnd takes nothing returns nothing
        local integer i
        local integer i2 = 1
        local real add
        
        //finds which player is ending rest
        loop
            exitwhen i2 == 5 //Only 4 possible timers
            if GetExpiredTimer() == dur[i2] then
                set i = i2
            endif
            set i2 = i2 + 1
        endloop
        
        //Null Timer
        call PauseTimer(GetExpiredTimer())
        call DestroyTimer(GetExpiredTimer())
        
        //Rest Camera
        
            
        //Destroy SFX
        call DestroyEffect(zzz<i>)
        
        //Reset HP
        set add = UnitHpAdd(char<i>)
        call SetUnitState(char<i>, UNIT_STATE_LIFE, GetUnitState(char<i>, UNIT_STATE_LIFE) + add)
        
        //Reset Cooldowns
        call UnitResetCooldown(char<i>)
        
        //Screen Print &quot;Done Resting!&quot;
        call DisplayTextToPlayer(GetOwningPlayer(char<i>), 0, 0, &quot;Done Resting!&quot;)
        
        //Unpause TriggerUnit()
        call PauseUnit(char<i>, false)
        
        set char <i> = null
    endfunction

//========================================================
    private function check takes nothing returns boolean
        return GetSpellAbilityId() == rest
    endfunction
//========================================================
    private function actions takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local player p = GetOwningPlayer(u)
        local integer e = 0
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local unit f
        
        
        call GroupEnumUnitsInRange(g, x, y, 1500., b)
        
        loop
            set f = FirstOfGroup(g)
            exitwhen f == null
            
            call GroupRemoveUnit(g, f)
            
            if (IsUnitEnemy(f, GetOwningPlayer(u)) == true) then
                set e = e + 1
            endif
        endloop
        
        if e == 0 then
            set char[GetPlayerId(p)] = u
        
            //Stops endless loop bug I had in GUI
            //call IssueTargetOrder(u, &quot;stop&quot;, nothing)
        
            //Pause Unit
            call PauseUnit(u, true)
        
            //Lock camera for player to unit
            /*if (GetLocalPlayer() == p) then
                call CameraSetupApplyForceDuration( lock, false, 0.)
            endif*/
        
            //Create ZZZ SFX on Trigger Unit Head
            set zzz[GetPlayerId(p)] = AddSpecialEffectTarget(ZZZsfx, u, &quot;overhead&quot;)
        
            //Screen Print &quot;Resting...&quot;
            call DisplayTimedTextToPlayer(p, 0., 0., 5.95, &quot;Resting...&quot;)
        
            //Starts Timer to End Resting
            set dur[GetPlayerId(p)] = CreateTimer()
            call TimerStart(dur[GetPlayerId(p)], 6., false, function restEnd )
        else
            call DisplayTimedTextToPlayer(p, 0., 0., 5., &quot;You cannot rest nearby enemies!&quot;)
        endif    
        
        
        call DestroyGroup(g)
        set g = null
        set u = null
        set p = null
        
    endfunction

//========================================================
    private function Init takes nothing returns nothing
        local trigger t
        local integer i = 0
    
        set t = CreateTrigger(  )
        loop
            call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            set i = i + 1
            exitwhen i == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition(t, Condition(function check))
        call TriggerAddAction( t, function actions )
        
        //Globals
        set g = CreateGroup()
        set b = Condition(function pick)
        
        //Preloads
        call Preload(ZZZsfx)
        
        set bj_lastCreatedUnit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), dmy, 0, 0, 0)
        call UnitAddAbility(bj_lastCreatedUnit, rest)
        call KillUnit(bj_lastCreatedUnit)
    endfunction

endscope</i></i></i></i></i></i></i></i>
 

luorax

Invasion in Duskwood
Reaction score
67
Huh, it looks okayish for first - try to add some [ljass]BJDebugMsg()[/ljass] after each important call (like when the timer expires, when the player is found, things like that), that way you can easily debunk the buggy part.

However you should use TimerUtils, that makes your life easier, and it's more effective (actually timer recycling is way more effective than dynamic timers). I can help you improving this if you want, feel free to PM me :)

EDIT: okay, I debugged it: the system fails at retrieving the the expired timer. Because i is not initialized (it's okay, because the loop should give it a value), that unitialized variable crashes the thread.

EDIT2: oh, and I got the error: in JASS, player numbers go from 0 to 11, not like in GUI. So player 1 is Player(0) in GUI.
So this is how the loop should look like:

JASS:
local integer i
local integer i2 = 0
local real add
        
 //finds which player is ending rest
loop
    exitwhen i2 == 4 //Only 4 possible timers
    if GetExpiredTimer() == dur[i2] then
        set i = i2
    endif
    set i2 = i2 + 1
endloop


The way you can order the unit to stop:
JASS:
call IssueImmediateOrder(u,&quot;stop&quot;)


Do this after the unit has been paused.

EDIT3: don't destroy your global group (called g). [ljass]call GroupEnumUnitsInRange(g, x, y, 1500., b)[/ljass] automatically clears it (neither null it). If you destroy it, the spell bugs, and will always return 0 as the enemy count.
 

inevit4ble

Well-Known Member
Reaction score
38
Ok, I've made the changes you suggested:
Changed "stop" order and put if after the pause (not sure how this works cause the unit is paused)
Removed group destroy and null


But I don't follow you on the timer side of things. I thought I was initializing it via
JASS:
//Starts Timer to End Resting
            set dur[GetPlayerId(p)] = CreateTimer()
            call TimerStart(dur[GetPlayerId(p)], 6., false, function restEnd )

And TimerUtils is a system for timers?
And recycling timers lets me use the same timer over and over instead of creating new ones each instance?

Of course it still doesn't run properly so what do I need to do to get it going?

Is there an answer to how I manipulate the camera and control for player? can't seem to fill arguments correctly.

Thanks
 

tooltiperror

Super Moderator
Reaction score
231
>And recycling timers lets me use the same timer over and over instead of creating new ones each instance?
Yes, the point of timer recycling is making a big pile of timers in memory, and when you need a timer, take one ([LJASS]NewTimer()[/LJASS]) instead of making a new one. Then when you're done, send it back to the pile instead of destroying it ([LJASS]ReleaseTimer(timer)[/LJASS])

>Is there an answer to how I manipulate the camera and control for player? can't seem to fill arguments correctly.
JASS:
if (GetLocalPlayer() == Player(0)) then
    // this code will only run for Player(0)
    // including camera actions
endif
 

luorax

Invasion in Duskwood
Reaction score
67
This code worked for me:

JASS:

scope Rest initializer Init
//========================================================
//====================SET UP==============================
globals
    private constant integer rest = &#039;AHtc&#039;
    private constant string ZZZsfx = &quot;Abilities\\Spells\\Other\\CreepSleep\\CreepSleepTarget.mdl&quot;
endglobals
//========================================================
//====================END UP==============================     
//========================================================
globals
    private effect array zzz
    private timer array dur
    private group g
    private unit array char
    private boolexpr b
endglobals
//========================================================
    private function RestAoE takes unit u returns boolean
        return (GetWidgetLife(u) &gt; 0.405)
    endfunction
    
    private function pick takes nothing returns boolean
        return RestAoE(GetFilterUnit())
    endfunction

//========================================================
    private function UnitHpAdd takes unit u returns real
        local real max
        local real cur
        
        
        set max = GetUnitState(u, UNIT_STATE_MAX_LIFE)
        set cur = GetUnitState(u, UNIT_STATE_LIFE)
        
        return max - cur
    endfunction
    
    private function restEnd takes nothing returns nothing
        local integer i
        local integer i2 = 0
        local real add
        
        //finds which player is ending rest
        loop
            exitwhen i2 == 4 //Only 4 possible timers
            if GetExpiredTimer() == dur[i2] then
                set i = i2
            endif
            set i2 = i2 + 1
        endloop
        
        //Null Timer
        call PauseTimer(GetExpiredTimer())
        call DestroyTimer(GetExpiredTimer())
        
        //Rest Camera
        
            
        //Destroy SFX
        call DestroyEffect(zzz<i>)
        
        //Reset HP
        set add = UnitHpAdd(char<i>)
        call SetUnitState(char<i>, UNIT_STATE_LIFE, GetUnitState(char<i>, UNIT_STATE_LIFE) + add)
        
        //Reset Cooldowns
        call UnitResetCooldown(char<i>)
        
        //Screen Print &quot;Done Resting!&quot;
        call DisplayTextToPlayer(GetOwningPlayer(char<i>), 0, 0, &quot;Done Resting!&quot;)
        
        //Unpause TriggerUnit()
        call PauseUnit(char<i>, false)
        
        set char <i> = null
    endfunction

//========================================================
    private function check takes nothing returns boolean
        return GetSpellAbilityId() == rest
    endfunction
//========================================================
    private function actions takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local player p = GetOwningPlayer(u)
        local integer e = 0
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local unit f
        
        call GroupEnumUnitsInRange(g, x, y, 1500., b)
        
        loop
            set f = FirstOfGroup(g)
            exitwhen f == null
            
            call GroupRemoveUnit(g, f)

            
            if (IsUnitEnemy(f, GetOwningPlayer(u)) == true) then
                set e = e + 1
            endif
        endloop
        
        if e == 0 then
            set char[GetPlayerId(p)] = u
        
            //Stops endless loop bug I had in GUI
            //call IssueTargetOrder(u, &quot;stop&quot;, nothing)
        
            //Pause Unit
            call PauseUnit(u, true)
            
            call IssueImmediateOrder(u,&quot;stop&quot;)
            
            //Lock camera for player to unit
            /*if (GetLocalPlayer() == p) then
                call CameraSetupApplyForceDuration( lock, false, 0.)
            endif*/
        
            //Create ZZZ SFX on Trigger Unit Head
            set zzz[GetPlayerId(p)] = AddSpecialEffectTarget(ZZZsfx, u, &quot;overhead&quot;)
        
            //Screen Print &quot;Resting...&quot;
            call DisplayTimedTextToPlayer(p, 0., 0., 5.95, &quot;Resting...&quot;)
        
            //Starts Timer to End Resting
            set dur[GetPlayerId(p)] = CreateTimer()
            call TimerStart(dur[GetPlayerId(p)], 6., false, function restEnd )
        else
            call DisplayTimedTextToPlayer(p, 0., 0., 5., &quot;You cannot rest nearby enemies!&quot;)
        endif    
        
        
        set u = null
        set p = null
        
    endfunction

//========================================================
    private function Init takes nothing returns nothing
        local trigger t
        local integer i = 0
    
        set t = CreateTrigger(  )
        loop
            call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            set i = i + 1
            exitwhen i == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition(t, Condition(function check))
        call TriggerAddAction( t, function actions )
        
        //Globals
        set g = CreateGroup()
        set b = Condition(function pick)
        
        //Preloads
        call Preload(ZZZsfx)

    endfunction

endscope
</i></i></i></i></i></i></i></i>


Note that I've removed the preload part.
TimerUtils is a timer system, yes. It creates some timers at the start (default value is 256), and once you call NewTimer() returns the last available timer. You can attach data to the timer, and if you "destroy" it (ReleaseTimer()), it's simply stopped and recycled for later use. It's slightly faster than creating/destroying them in each run.

The way you pan the camera for the owner:
JASS:

if GetLocalPlayer()==p then
    call PanCameraToTimed(GetUnitX(u),GetUnitY(u),0.)
    call SetCameraTargetController(u, 0., 0., false)
endif

The way you reset it:
JASS:

if GetLocalPlayer()==p then
    call ResetToGameCamera(&lt;DURATION&gt;)
endif
 

inevit4ble

Well-Known Member
Reaction score
38
:) I feel silly now. Was searching your code to find the differences (beside the preload)
I forgot to change i2 = 0 instead of 1....

And I will look into TimerUtils for future use. It sounds like a plan!

Thanks!
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/
  • The Helper The Helper:
    I think we need to add something to the bottom of the front page that shows the Headline News forum that has a link to go to the News Forum Index so people can see there is more news. Do you guys see what I am saying, lets say you read all the articles on the front page and you get to the end and it just ends, no kind of link for MOAR!
  • The Helper The Helper:
    Happy Wednesday!
    +1

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top