1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. We have recently started the 16th edition of the Mini Mapping Contest. The theme is mini RPG. Do check it out and have fun.
    Dismiss Notice
  4. Dismiss Notice
  5. The Highway to Hell has been laid open. Come along and participate in the 5th Special Effect Contest.
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Timers and Waits

Discussion in 'Triggers & Scripts' started by VadamLoke, Jul 17, 2018.

Tags:
  1. VadamLoke

    VadamLoke

    Joined:
    Mar 26, 2018
    Messages:
    6
    Resources:
    0
    Resources:
    0
    Hello Hive

    I'm struggling to choose timer or wait to implement my solution. I have gone through the forum and read mixed claims about both of them. That they can cause desync themselves(which i doubt), one is more accurate than other and opposite. I don't want to choose one without consideration and wait for my map to fail during play. I would appreciate if anyone could make this clear to me.

    What are my requirements?
    They must work inside loop to pause the code for 1 second with at least 25% accuracy
    No desync and leaks
     
  2. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,683
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    Neither one causes a desync if used properly. I pretty much always try to use timers for a few reasons.
    • Waits send a packet over the network each time they are called. The more waits your map uses the more network traffic it will use.
    • Waits are inaccurate in multiplayer.
    • Waits are unable to pause for less than the latency of the match making low frequency operations impossible.
    • Waits are partially responsible for weird behavior like the handle stack corruption bug.
    Unfortunately with timers you are forced to create a new function (trigger/action in GUI) which separates the data from your local scope. This isn't really a problem if you are using GUI without any locals but it's still less convenient than Waits. Because of this timers do not work inside of loops, instead you will have to learn how to use periodic timers.
     
  3. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,426
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    ^+1 to everything TH said.

    What are you trying to implement? We might be able to give you an example that'll work to your needs. Timers are a little tough to get started with, but they are really worth it. Here is a guide if you'd like it:
    Visualize: Dynamic Indexing
     
  4. Kaijyuu

    Kaijyuu

    Joined:
    Jun 2, 2004
    Messages:
    848
    Resources:
    0
    Resources:
    0
    I still use waits for very simple operations that don't happen very often. No need for fancy timers if you're doing something as simple as displaying a list of messages over time.
     
  5. MyPad

    MyPad

    Spell Reviewer

    Joined:
    May 9, 2014
    Messages:
    1,333
    Resources:
    7
    Models:
    1
    Icons:
    2
    Spells:
    3
    JASS:
    1
    Resources:
    7
    Basically, what creates handles should be for timers. Messages are okay with waits.
     
  6. VadamLoke

    VadamLoke

    Joined:
    Mar 26, 2018
    Messages:
    6
    Resources:
    0
    Resources:
    0
    I'm trying to create a periodical (reinforce) trigger which checks state of specific units and if they have less than max HP, then creates request for manpower from players cities, waits specific amount of time from 3 to 15 seconds depending on technology


    This is city class, it has its own trigger to update state
    Code (vJASS):

    struct City extends array [1024]
        static integer TotalCities = 0
        static integer MaxIndex = 0
        integer id
        boolean exists
        boolean is_occupied
     
        integer real_owner
        integer owner
        real ground_pop_modifier // extra growth depends on tiles
     
        integer city_level
        real city_level_growth_modifier
     
        unit ucity
     
        integer population
        integer educated // from population
     
        // both from population
        integer free_workers // available - depends on law ( mod)
        integer used_workers // used in any way
        integer total_workers // how many in total
     
        // same principe
        integer free_manpower
        integer used_manpower
        integer total_manpower
     
        // Buildings
        boolean has_granary
        unit ugranary
     
        boolean has_barracks
        unit ubarracks
     
        boolean has_market
        unit umarket
     
        boolean has_university
        unit uuniversity
     
        boolean has_bunker
        unit ubunker
     
        //and more... + many methods
     
       endstruct
     
     

    This is class for units which im working with
    Code (vJASS):

    struct CombatUnit extends array [3144]
        static integer TotalUnits = 0
        static integer MaxIndex = 0
     
        boolean exists
        unit uunit
        integer owner
        real reinforces_on_way
     
        //+ methods

    endstruct
     

    This is the Trigger i'm working on
    Code (vJASS):

    function Trig_globalV2_Actions takes nothing returns nothing
     
         
    local integer i = 0
    local integer unitcount = 0
    local integer array reinforces
    local integer requests_count = 0
    // search for losses - CombatUnit
        loop
            exitwhen unitcount >= CombatUnit.TotalUnits or i >= 2048
         
            if GetUnitState(CombatUnit[i].uunit, UNIT_STATE_LIFE) > 0 then
                set unitcount = unitcount + 1
             
                if GetUnitState(CombatUnit[i].uunit,UNIT_STATE_LIFE) + CombatUnit[i].reinforces_on_way < I2R(BlzGetUnitMaxHP(CombatUnit[i].uunit)) then
                 
                    set requests_count = requests_count + 1
                    set reinforces[i] = BlzGetUnitMaxHP(CombatUnit[i].uunit) - R2I(GetUnitState(CombatUnit[i].uunit,UNIT_STATE_LIFE)) - CombatUnit[i].reinforces_on_way
                    set CombatUnit[i].reinforces_on_way = BlzGetUnitMaxHP(CombatUnit[i].uunit) - R2I(GetUnitState(CombatUnit[i].uunit,UNIT_STATE_LIFE))
                 
                endif
         
            endif
            set i = i + 1
        endloop
     
     
        set i = 0
        set unitcount = 0
     
        // problem - is timer or wait more appropriate for this?
        // loop max 15 times
        // wait 1 second every iteration
        // loop through requests and check if reinforce rate (in seconds) of player is lower or equals total elapsed time
        // if yes try to request reinforces > increase HP else do nothing
        // remove request
        // continue until there are no requests left or iterated 15 times

       // this trigger runs every second so im using globals to make sure there are not multiple requests for
       // same amount of losses for unit
     
    endfunction
    //===========================================================================
    function InitTrig_globalV2 takes nothing returns nothing
        set gg_trg_globalV2 = CreateTrigger(  )
        call TriggerRegisterTimerEventPeriodic( gg_trg_globalV2, 1.00 )
        call TriggerAddAction( gg_trg_globalV2, function Trig_globalV2_Actions )
    endfunction
     

    And this is the manpower request function
    Code (vJASS):

    function reinforces_requesst_manpower takes unit u, integer needed_mp, integer iplayer returns boolean
    local boolean fulfilled = false  
    local integer icity = 0
    local integer city_count = 0
    local integer array temp_mp
    local integer collected_mp = 0
    local integer temp = 0
    local integer i = 0
        loop
         
            if City[icity].exists and City[i].owner == iplayer then
                set city_count = city_count + 1
             
                if City[icity].free_manpower > 0 then
             
                    if City[icity].free_manpower > needed_mp - collected_mp - 1 then
                     
                        set temp = needed_mp - collected_mp
                        set collected_mp = collected_mp + temp
                     
                        //take mp from cities          
                        set City[icity].total_manpower = City[icity].total_manpower - temp
                        set City[icity].free_manpower = City[icity].free_manpower - temp
                        set City[icity].used_manpower = City[icity].used_manpower + temp
                 
                        set temp_mp[icity] = temp
                        set temp = 0
                     
                    else
                 
                        set temp = City[iplayer].free_manpower
                        set collected_mp = collected_mp + temp
                 
                        //take mp from cities
                        set City[icity].total_manpower = City[icity].total_manpower - temp
                        set City[icity].free_manpower = City[icity].free_manpower - temp
                        set City[icity].used_manpower = City[icity].used_manpower + temp
                 
                        set temp_mp[icity] = temp
                        set temp = 0
                 
             
                    endif
         
                endif
             
            endif
         
            set icity = icity + 1
            exitwhen icity > 255 or city_count >= PlayerData[iplayer].total_cities or collected_mp >= needed_mp
        endloop
     
     
        set u = null
     
        if collected_mp >= needed_mp then
            return true
     
        else
     
            set city_count = 0
            loop
             
                if temp_mp[i] > 0 then
                    set city_count = city_count + 1
                endif
         
                        set City[i].total_manpower = City[i].total_manpower + temp_mp[i]
                        set City[i].free_manpower = City[i].free_manpower + temp_mp[i]
                        set City[i].used_manpower = City[i].used_manpower - temp_mp[i]
                 
                set i = i + 1
                exitwhen i > 1024 or city_count >= PlayerData[iplayer].total_cities
            endloop
     
            return false
        endif
    endfunction

     

    I also thought about using Damage Detection System but i would'nt need that for anything escept this

    I'm sorry if i made any mistake in grammar or spelling, english is not my first language
     
    Last edited: Jul 18, 2018
  7. VadamLoke

    VadamLoke

    Joined:
    Mar 26, 2018
    Messages:
    6
    Resources:
    0
    Resources:
    0
    I have found different and more efficient solution without the need of timers and waits for my problem.
    Please terminate this thread