HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

I need help from experts

03-28-2010, 06:25 AM#1
Tom_Kazansky
sorry that I can't write a more descriptive title

I have something that bugged me, more like "not sure", here are they:
  1. I want a "custom regeneration" system, that do the regeneration of units manually, so I add units to a group and use a 0.1s static timer to do the regeneration, but I got lag if there are too many units (about 40 units, I think)

    I think my method is not efficient so I think using AIDS and T32 would be better. Yea, T32 add a period timer to AIDS struct, and AIDS struct hold the unit's data. I only need 0.1s period for this.
    So will I be able to have more units before the lag ?
    (I know the lag would depend on what I do with each period, but assume that I do the same things with my method and with T32 )

    (I know this can be self-tested but currently, my remake map is in terraining so I can't test it myself)

  2. I make a filter system (for group enuming):

    Collapse JASS:
    scope CustomFilter
    
    globals
        private real X
        private real Y
        private real RANGE
        private unit GB_U = null
        private group GB_G = null
        private integer GB_ID = 0
        private integer array GB_Filter
    endglobals
    
    private function IsUnitTypeElite takes unit u returns boolean
        return IsUnitType(u, UNIT_TYPE_ANCIENT) and IsUnitType(u, UNIT_TYPE_GIANT )
    endfunction
    
    private function IsUnitTypeChampion takes unit u returns boolean
        return IsUnitType(u, UNIT_TYPE_SAPPER) and IsUnitType(u, UNIT_TYPE_TAUREN)
    endfunction
    
    private function IsUnitInvisibleEx takes unit u, player p returns boolean //thank to Flare
        local real ux = GetUnitX(u)
        local real uy = GetUnitY(u)
        local boolean invisible = false
        if IsUnitFogged(u,p) or IsUnitMasked(u,p) then
            call SetUnitX(u, tj_VisibleCheckerX )
            call SetUnitY(u, tj_VisibleCheckerY )
            set invisible = IsUnitInvisible(u,p)
            call SetUnitX(u, ux)
            call SetUnitY(u, uy )
        else
            set invisible = IsUnitInvisible(u,p)
        endif
        return invisible
    endfunction
    
    private function CustomBoolExprFilter takes nothing returns boolean
        local unit f = GetFilterUnit()
        local boolean array b
        local boolean ok = true
        local integer i
        
        if GetUnitAbilityLevel(f,NoNeedToCheck)>0 then //units that have "NoNeedToCheck" ability will never be enumed
            set f = null
            return false  
        endif
        set b[0] = not IsUnitInGroup(f,GB_G)
        set b[1] = GetUnitAbilityLevel(f,GB_ID) == 0
        set b[2] = not IsUnitInvulnerable(f) //check 'Avul' and data to detect the "SetUnitInvulnerable"
        set b[3] = (IsUnitIllusion(f) == false)
        set b[4] = not ( GetUnitState(f,UNIT_STATE_MAX_MANA) == 0 )
        set b[5] = (IsUnitType(f,UNIT_TYPE_MELEE_ATTACKER)==true)
        set b[6] = (IsUnitType(f,UNIT_TYPE_GROUND)==true)
        set b[7] = (IsUnitType(f,UNIT_TYPE_DEAD)==false)
        set b[8] = IsUnitEnemy(f,GetOwningPlayer(GB_U))
        set b[9] = not IsUnitTypeElite(f)
        set b[10] = not IsUnitTypeChampion(f)
        set b[11] = (IsUnitType(f,UNIT_TYPE_HERO)==false)
        set b[12] = (IsUnitType(f,UNIT_TYPE_MECHANICAL)==false)
        set b[13] = (IsUnitType(f,UNIT_TYPE_STRUCTURE)==false)
        set b[14] = (IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE)==false)
        set b[15] = (IsUnitType(f,UNIT_TYPE_ETHEREAL)==false)
        set b[16] = (GetUnitAbilityLevel(f,tj_IsWardCheck)==0) //an ability that all wards has
        set b[17] = (IsUnitFogged(f,GetOwningPlayer(GB_U))==false and IsUnitMasked(f,GetOwningPlayer(GB_U))==false)
        set b[18] = (IsUnitInvisibleEx(f,GetOwningPlayer(GB_U))==false)
        
        set i = 0
        loop
            exitwhen i > 18
            if not ( ( GB_Filter[i] == 0 ) or ( (GB_Filter[i] == 1) and b[i] ) or ( (GB_Filter[i] == 2) and not b[i] ) ) then
                set ok = false
            endif
            set i = i + 1
        endloop
        set f = null
        return ok
    endfunction
    
    private function CustomBoolExprFilterTrue takes nothing returns boolean
        return true
    endfunction
    
    function CustomBoolExprGet takes unit ufilter,integer buffid, group gfilter, string filter returns boolexpr
        local integer i = 0
        if filter == "" or filter == null then
            return Condition( function CustomBoolExprFilterTrue )
        endif
        loop
            exitwhen i > 18
            set GB_Filter[i] = S2I(SubString(filter,i,i+1))
            set i = i + 1
        endloop
        set GB_G = gfilter
        set GB_U = ufilter
        set GB_ID = buffid
        return Condition( function CustomBoolExprFilter )
    endfunction
    
    endscope

    so, when I want to enum units that are: has 'B000' buff, not invulnerable , alive, enemy of unitA, non-structure, non-magic immue, non-ward
    I will get boolexpr: CustomBoolExprGet( A, 'B000', null, "0110000110000110100" )
    I have once told that boolexpr must be optimized as much as possible, but it's inconvenient for me (ermm... I'm lazy) to create filter for each spell (or for each group enum) so I use this CustomFilter, it's convenient for me but is it good for the game ?
    (I don't really need "good", I only need "not bad" or even "not too bad" )

  3. How to calculate the maximum height of an arc projectile ? the height that projectile will reach when it fired at X range and its arc=Y.
    e.g: I have a projectile fired at 1000 range and arc = 0.15 => what is the maximum height ?
    I think I have seen this function before but I can't remember when/where so I will just ask.

thank you for reading and for the (later) answers
03-28-2010, 06:45 AM#2
Earth-Fury
  1. Stupid systems like AIDS and T32 won't help you. You need to optimize the actual code that is run many times a second better. I can not help you with that without the actual code you have now.
  2. http://www.wc3c.net/showthread.php?t=109109#11
    If you are too lazy to actually do what you need to do, you need to stop now and find something else to do. Maybe try origami, I hear that's pretty fun.
    Write your damn filters manually.
  3. arc * distance, I do believe.
03-28-2010, 11:02 AM#3
Tom_Kazansky
thanks for the reply
---
here is the code for units regeneration.

code


Collapse JASS:
function IsUnitDisabled takes unit u, integer typeattack returns boolean
    local boolean b = false
    if typeattack == 0 then //spells
        set b = ( GetUnitAbilityLevel(u,'B005') > 0  or GetUnitAbilityLevel(u,'B012') > 0 or GetUnitAbilityLevel(u,'B01D') > 0 or GetUnitAbilityLevel(u,'B02O') > 0 )
    endif
    if typeattack == 1 then //special
        set b = IsUnitType(u,UNIT_TYPE_POLYMORPHED)
    endif
    if typeattack == 2 then //melee + range
        set b = GetUnitAbilityLevel(u,tj_AttackDisabler) > 0
    endif
    return b
endfunction

function EtherealExtra takes unit c returns real
    local real ex = 0.
    if GetUnitAbilityLevel( c, 'B00L' ) > 0 then
        set ex = 0.5
    endif
    return ex
endfunction

function UnitRestoreUnit takes unit c, unit a, real life, real mana, integer restp, boolean checkEth, boolean show returns nothing
    local tjunit ad
    local real ex = 0
    local string text = ""
    local real x
    local real y
    local integer int = 0
    local string lifecolor = "|c0020C000"
    if GetWidgetLife(a) <= 0.405 then
        return
    endif
    
    set ad = GetUnitUserData(a)
    if ad.healeff < 0 then
        return
    endif
    
    // dmgtp == 2 : Fire Damage
    // dmgtp == 3 : Cold Damage
    // dmgtp == 4 : Nature Damage
    // dmgtp == 5 : Earth Damage
    // dmgtp == 6 : Holy Damage
    // dmgtp == 7 : Shadow Damage
    
    set life = life * ad.healeff
    set mana = mana //* ad.healeff
    
    set ex = ex + ElementExtra( restp, ad.element , true )
    
    if checkEth and IsUnitType(a,UNIT_TYPE_ETHEREAL) then
        set ex = ex + EtherealExtra( a )
        //set mana = mana * ( 1 + ex )
    endif
    
    set life = life * ( 1 + ex )
    
    if life != 0 or ( life == 0 and ad.healeff == 0. ) then
        call SetUnitState(a, UNIT_STATE_LIFE, GetUnitState(a,UNIT_STATE_LIFE) + life )
        set text = text + lifecolor+StringCond("+","",life > 0 )+I2S( R2I(life) )+"|r"
    endif
    if mana != 0 and GetUnitState(a,UNIT_STATE_MAX_MANA) > 0 then
        call SetUnitState(a,UNIT_STATE_MANA, GetUnitState(a, UNIT_STATE_MANA) + mana )
        set text = text + StringCond( "/", "" , text != "" )+ "|c000042FF"+StringCond("+","",mana > 0 )+I2S( R2I(mana) )+"|r"
    endif
    if show and text != "" then
        set x = GetUnitX(a)-25
        set y = GetUnitY(a)
        call CheckTextTagVisibility( NewTextTag( text, 10, x, y,GetUnitFlyHeight(a)+ad.unitconst.pimpact*2.,160,90,2,1 ), x, y )
    endif
    
endfunction

function CheckAssisstanceStatus takes unit u returns nothing
    local tjunit ad = GetUnitUserData(u)
    local integer id = 0
    local integer int
    if ad.priority != 3 then // non-heroes
        return
    endif
    loop
        exitwhen id > 11
        set int = GetTableInt( ad.tablelabel, "AssisstanceSystem_AssisstFrom"+I2S(id))
        if int > 0 then
            call SetTableInt( ad.tablelabel, "AssisstanceSystem_AssisstFrom"+I2S(id), int + 1 )
        endif
        set id = id + 1
    endloop
endfunction

Collapse JASS:
globals
    group array tj_UnitRegeneration
    integer array tj_UnitRegenerationCount
    integer tj_UnitRegenerationIndex = 0
endglobals

function AddUnitRegeneration takes unit u returns nothing
    local integer i = 1
    local boolean add = false
    loop
        exitwhen i > tj_UnitRegenerationIndex
        if tj_UnitRegenerationCount[i] < 20 then
            call GroupAddUnit(tj_UnitRegeneration[i],u)
            set tj_UnitRegenerationCount[i] = tj_UnitRegenerationCount[i] + 1
            set add = true
            exitwhen true
        endif
        set i = i + 1
    endloop
    if not add then
        set tj_UnitRegenerationIndex = tj_UnitRegenerationIndex + 1
        set tj_UnitRegeneration[tj_UnitRegenerationIndex] = NewGroup()
        set tj_UnitRegenerationCount[tj_UnitRegenerationIndex] = 1
        call GroupAddUnit(tj_UnitRegeneration[tj_UnitRegenerationIndex],u)
    endif
endfunction

function RemoveUnitRegeneration takes unit u returns nothing
    local integer i = 1
    local integer j
    loop
        exitwhen i > tj_UnitRegenerationIndex
        if IsUnitInGroup(u,tj_UnitRegeneration[i]) then
            call GroupRemoveUnit(tj_UnitRegeneration[i],u)
            set tj_UnitRegenerationCount[i] = tj_UnitRegenerationCount[i] - 1
            if tj_UnitRegenerationCount[i] == 0 then
                call ReleaseGroup(tj_UnitRegeneration[i])
                set tj_UnitRegenerationIndex = tj_UnitRegenerationIndex - 1
                set j = i
                loop
                    exitwhen j > tj_UnitRegenerationIndex
                    set tj_UnitRegeneration[j] = tj_UnitRegeneration[j+1]
                    set j = j + 1
                endloop
            endif
            exitwhen true
        endif
        set i = i + 1
    endloop
    
endfunction

function GetUnitRegenerationState takes unit e, boolean life returns real
    local tjunit ud = GetUnitUserData(e)
    local integer lvl
    local real r1
    local real r2
    local real regen = 0.
    local boolean disabled = IsUnitDisabled( e, 1 )
    if life then
        set r1 = ud.liferegen
        set r2 = ud.liferegenp
        //--
        if not disabled then
            
        endif
        //--
        if ud.unitconst.ishero then
             set r1 = r1 + (ud.herodata.str + ud.herodata.strbonus)*0.05
        endif 
        set regen = r1 * ( 1 + r2/100. ) 
        if ud.lifemaxregen != 0 then
            set regen = regen+ GetUnitState(e,UNIT_STATE_MAX_LIFE) * ( ud.lifemaxregen / 100. )
        endif
        
        if GetUnitAbilityLevel(e,'AI08') > 0 then
            set r1 = GetUnitState(e,UNIT_STATE_LIFE)
            if r1 <= 35 then
                set regen = regen - r1 + 1
            else
                set regen = regen - 35
            endif
        endif
        
        set lvl = GetUnitAbilityLevel(e,'AB1R')
        if lvl > 0 then
            set regen = regen * ( 1 - 0.2*lvl)
        endif
        
        if GetUnitAbilityLevel(e,'B010') > 0 then
            set regen = regen - 30.
        endif
        
        if GetUnitAbilityLevel(e,'A01X') > 0 then
            set regen = regen + (ud.herodata.str + ud.herodata.strbonus) * 0.2
        endif
    else
        set r1 = ud.manaregen
        set r2 = ud.manaregenp
        //--
        if not disabled then
            
        endif
        
        //--
        if ud.unitconst.ishero then
             set r1 = r1 + (ud.herodata.ene + ud.herodata.enebonus)*0.05
        endif
        set regen = r1 * ( 1 + r2/100. )
        
        if GetUnitAbilityLevel(e,'B007') > 0 then
            set regen = regen - (10+5*ud.spell.unholyshieldlvl)
        endif
        if GetUnitAbilityLevel(e,'B02L') > 0 then
            set regen = regen - (20+5*ud.spell.shadowformlvl)
        endif
        
        if ud.manamaxregen != 0 then
            set regen = regen + GetUnitState(e,UNIT_STATE_MAX_MANA) * ( ud.manamaxregen / 100. )
        endif
    endif
    
    return regen
endfunction

function UnitsRegenerationLoopE takes nothing returns nothing
    local unit e = GetEnumUnit()
    local tjunit cd
    local real lfre = 0.
    local real mnre = 0.
    local real mp
    local integer lvl
    //¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    if IsUnitType(e,UNIT_TYPE_DEAD) then
        set e = null
        return
    endif
    set cd = GetUnitUserData(e)
    //---
    call CheckAssisstanceStatus( e )
    // --- life ---
    if GetWidgetLife(e) > 0.405 and not IsUnitIllusion(e) then
    
    set lfre = GetUnitRegenerationState(e,true) / 10.
    if ( GetUnitAbilityLevel(e,'B038') > 0 or GetUnitAbilityLevel(e,tj_BuffId_Vileness) > 0 ) and lfre > 0 then
        set lfre = 0.
    endif
    // --- mana ---
    set mnre = GetUnitRegenerationState(e,false) / 10.
    if ( GetUnitAbilityLevel(e,tj_BuffId_Vileness) > 0 ) and mnre > 0 then
        set mnre = 0.
    endif
    //----- Regen ---
    call UnitRestoreUnit( null, e , lfre, mnre, 0, true, false )
    
    endif
    //----- Check ability required mana -----
    set mp = GetUnitState(e,UNIT_STATE_MANA)
    
    set lvl = GetUnitAbilityLevel(e,'A01Q')
    if GetUnitAbilityLevel(e,'B007') > 0 and mp <= 15+5*lvl then
        call IssueImmediateOrder(e,"manashieldoff")
    endif
    if GetUnitAbilityLevel(e,'B02L') > 0 and mp <= 25+5*lvl then
        call IssueImmediateOrder(e,"manashieldoff")
    endif
    //----- In Combat state -----
    if cd.incombat > 0 then
        set cd.incombat = cd.incombat - 1
        if cd.incombat == 0 then
            call KelenDaggerState.execute(null , e, false )//re-enable Kelen's Dagger
        endif
    endif
    //----- Cooldown of passive ability -----
    if cd.spell.unholyshieldcool > 0 then
        set cd.spell.unholyshieldcool = cd.spell.unholyshieldcool - 1
    endif
    if cd.spell.defiancecool > 0 then
        set cd.spell.defiancecool = cd.spell.defiancecool - 1
        if cd.spell.defiancecool == 0 then
            call UnitAddAbility(e,'AB1W')
        endif
    endif
    //___________
    
    set e = null
endfunction

function UnitsRegenerationLoop takes nothing returns boolean
    local integer i = 1
    loop
        exitwhen i > tj_UnitRegenerationIndex
        call ForGroup( tj_UnitRegeneration[i], function UnitsRegenerationLoopE )
        set i = i + 1
    endloop
    return false
endfunction


it's just calculating, check buffs and set life/mana
---
maybe I have too many unnecessary calls or something
if you think those code can be optimized, please help
---
p.s: I have tried origami, I can't really say that I love it but, well, it's fun
03-28-2010, 01:10 PM#4
Earth-Fury
Quote:
Originally Posted by Tom_Kazansky
here is the code for units regeneration.
[hiddenjass] tags.
  • Collapse JASS:
    function IsUnitDisabled takes unit u, integer typeattack returns boolean
        local boolean b = false
        if typeattack == 0 then //spells
            set b = ( GetUnitAbilityLevel(u,'B005') > 0  or GetUnitAbilityLevel(u,'B012') > 0 or GetUnitAbilityLevel(u,'B01D') > 0 or GetUnitAbilityLevel(u,'B02O') > 0 )
        endif
        if typeattack == 1 then //special
            set b = IsUnitType(u,UNIT_TYPE_POLYMORPHED)
        endif
        if typeattack == 2 then //melee + range
            set b = GetUnitAbilityLevel(u,tj_AttackDisabler) > 0
        endif
        return b
    endfunction
    1. elseif
    2. If you don't mind making something as ugly as the baby from Seinfeld, combine that in to a single return statement, like so:

      return (typeattack == 0 and (<stuff>)) or (typeattack == 1 and (<stuff>)) // etc

      Make sure the most likely/common conditions come first. JASS uses short circuit boolean operators, which means:

      A() and B() // If A() returns false, B() will not be called
      A() or B() // If A() returns true, B() will not be called

      Zinc is good for such things, as it allows you to break such massive (but fast to execute) lines up in to multiple code lines.
  • Collapse JASS:
    function EtherealExtra takes unit c returns real
        local real ex = 0.
        if GetUnitAbilityLevel( c, 'B00L' ) > 0 then
            set ex = 0.5
        endif
        return ex
    endfunction

    Could be better written as:
    Collapse JASS:
    if GetUnitAbilityLevel(c, 'B00L') > 0 then
        return 0.5
    endif
    return 0

    Notice the lack of a local, and the fact that you return immediately instead of executing the rest of the function when the return value is known.
  • Learn more vJass and use more vJass. Read the JASS Helper manual in full.
  • Your code is improperly indented in some places. Indent everything between a statement or definition line, and it's corresponding "end" line. Always. (With the possible exception of vJass libraries, as generally a library wraps all the code in a file/trigger.)
  • Your code is causing my brain to bleed, my eyes to gloss over with cataracts, and my brain to cheese muffins burnt toast.
  • I am presuming that UnitsRegenerationLoop is the function being called periodically, as that's the only way it seems to make sense... If I'm wrong, then see previous point.
  • I could spend the next 2 hours reading and understanding all that code. But I won't. Instead, I shall offer this sagely advice in closing:

    You are doing WAY too fucking much in a periodic timer!

    The _ONLY_ thing you should be doing in a periodic timer is looping over a set of units, and applying things to them.

    More verbosely:
    If you want to apply 10 units base health regeneration, except on tuesday, but double it if he's carrying Jimmy's Left Nut, your periodic timer's callback will look something like this:
    Collapse JASS:
    globals
        unit array people
        integer people_count
    endglobals
    
    function DoStuffPeriodic takes nothing returns nothing
        local unit u
        local SomeStruct ss
        local integer i = 0
        
        loop
            exitwhen i == people_count
            set u = people[i]
            set ss = GetStructThroughSomeAttachmentMethod(u)
            
            call SetUnitState(u, UNIT_STATE_LIFE, GetUnitState(u, UNIT_STATE_LIFE) + ss.lifeRegen)
            call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MANA) + ss.manaRegen)
    
            set i = i + 1
        endloop
        set u = null
    endfunction

    If, on the other hand, you want to apply a +5 mana bonus except when there's a full moon, doubling it if the unit's mother was a whore, but halving it if Jimmy still has his left nut, then the function that executes once a second will look EXACTLY THE FUCKING SAME. :)

    Now, for real examples.

    Lets say you don't ever want to apply a regeneration bonus to undead units...

    Well, do this:

    Collapse JASS:
    struct SomeStruct
        private unit unitIAmAttachedTo
        private real lifeRegen = 0.0
        public method SetLifeRegen takes real r returns nothing
            if (/* is unitIAmAttachedTo is _not_ undead? */) then
                set this.lifeRegen = r
            endif
        endmethod
    endstruct

    You check if the unit is undead ONCE, instead of every second.

    More complex constraints, like adding a +10/s life regen boost for 20 seconds is done basically the same way:
    Collapse JASS:
    call ss.SetLifeRegen(ss.GetLifeRegen() + 10)
    call AttachShitToTimerSomehow(t, ss)
    call TimerStart(t, 20, false, function CallbackExample)
    
    //...
    
    function CallbackExample takes nothing returns nothing
        local SomeStruct ss = GetTimerAttachedDataStufff()
        call ss.SetLifeRegen(ss.GetLifeRegen() - 10)
    endfunction

    The basic model for fast periodic events like this is simple:
    Do as many calculations as possible non-periodically, cache the result, apply the result periodically.

  • Avoid unit groups. In the example I gave above, I used an array of units. This is a great way to do things.

    "But how do I remove a unit from the middle?!"
    Collapse JASS:
    set yourArray[unitsIndexInTheArray] = yourArray[yourArray_size - 1]
    set yourArray_size = yourArray_size - 1

    This requires attaching a unit's index in the array to the unit somehow, of course.

  • Go to the scripts section (or use some of the links in my signature) to look up AutoIndex and TimerUtils.

    AutoIndex gives each unit a unique ID that can be used as an array index. This allows you to store an arbitrary amount of data on a unit with great ease:
    Collapse JASS:
    globals
        SomeStructure array someStructs
    endglobals
    
    // ...
    
    set someStruct[GetUnitId(u)] = ss
    
    // ...
    
    local SomeStruct ss = someStruct[GetUnitId(u)]

    TimerUtils allows you to attach an integer to any timer.

Hope this helps you some.
03-28-2010, 01:37 PM#5
darkwulfv
@Earth-Fury
Who do you think you are, Pyrogasm?
03-29-2010, 07:55 AM#6
Ignitedstar
That's really mean, darkwulfv. Earth-Fury spent all of that time trying to help him and you're criticizing it? He even went in depth, doing way more that he needed to. Anyone who gets a response like that should be grateful.
03-29-2010, 07:57 AM#7
Tom_Kazansky
@Earth-Fury, thank you very much

since I know about vJass, I only use structs for storing data and nothing else.
I will learn more vJass

@Ignitedstar, you're right

I have nothing to complain about since I asked him to look through my **** code.
03-29-2010, 09:25 AM#8
Earth-Fury
Quote:
Originally Posted by Ignitedstar
That's really mean, darkwulfv. Earth-Fury spent all of that time trying to help him and you're criticizing it? He even went in depth, doing way more that he needed to. Anyone who gets a response like that should be grateful.
I hope you're being facetious o.O

Pyrogasm was known for posting giant helpful posts like the one I posted in this thread. For the longest time, I linked to a few of them in my signature with the caption "Pyrogasm needs to get laid". Thus darkwulfv was simply joking around in a friendly way, not attempting to insult or criticize.
03-29-2010, 09:45 AM#9
Tom_Kazansky
I don't even know what "Pyrogasm" mean
-----
@Earth-Fury, I get the periodic stuff, I shouldn't do much stuffs per period

but now is it ok that I add:

Collapse JASS:
globals
    unit array people
    integer people_count
endglobals

function DoStuffPeriodic takes nothing returns nothing
    local unit u
    local SomeStruct ss
    local integer i = 0
    
    loop
        exitwhen i == people_count
        set u = people[i]
        set ss = GetStructThroughSomeAttachmentMethod(u)
        
        call SetUnitState(u, UNIT_STATE_LIFE, GetUnitState(u, UNIT_STATE_LIFE) + ss.lifeRegen)
        call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MANA) + ss.manaRegen)

        //add theses
        set ss.currentX = GetUnitX(u)
        set ss.currentY = GetUnitY(u)

        set i = i + 1
    endloop
    set u = null
endfunction

I want to save the current position of units and in other functions, check if a unit is moving or not.

and also, is it still ok if I use period lower than 0.1 ? (e.g: 0.04, 0.03125, 0.025 )
03-29-2010, 10:15 AM#10
Earth-Fury
0.025 is the lowest you will realistically need for anything, ever. You will only even need such a low period if you are moving units with SetUnitX/Y. Most other things will work pretty much as well with a period more like 1/20, or even 1/10. (1/20 = 0.05. 1/40 = 0.025. 1/executions per second = period)

------------------

Caching units positions like that makes no sense. Any code which reads ss.currentX will have to itself be running off a timer to read it at multiple times to see how it changes over time. So why not grab the position in the other timer?

Of course, checking if a unit is moving in the periodic itself makes some sense. Namely:
Collapse JASS:
        set x = ss.currentX - GetUnitX(u)
        set y = ss.currentY - GetUnitY(u)
        set ss.squaredDistanceMoved = x*x + y*y
Apply a SquareRoot to squaredDistanceMoved to get the actual distance moved between two executions of the periodic timer.

Note that it only makes sense to do this if you will be using it a lot. If you're making a single spell that uses it, and only a single spell, you'd be better off with a different method.
Say you're making a spell that stops when a unit moves, you'd be better off having a separate 1/4 period timer that you start when the spell is cast, checking if the unit's position is the same as it was when the spell started. When the spell is over, you'd release the timer.

Doing everything for everything in a single function makes no sense, especially considering the fact that many things can execute at a much lower period and still give a good effect. Using separate timers also means you will not be executing code 10 to 20 times a second, even when any spell/ability/etc that uses it is not in the process of being cast/used/etc.
03-29-2010, 10:44 AM#11
Tom_Kazansky
I usually use period 0.04, now I'm starting to use 0.025 (because someone said 0.04 is not smooth enough )


thanks, again
03-29-2010, 10:53 AM#12
Kueken
Usually, 0.025 works fine, if you do not do stupid things in your periodic functions. However, this is also a matter of taste. Rising_Dusk likes to use 0.05 afaik (at least his knockback systems default that interval), many people prefer 0.03125 (32fps).
I prefer 0.025, too, it looks more smooth for me (however 0.04 works in most cases, too).

Just try some values and take the one, which gives you the most satisfaction ;)
03-29-2010, 06:45 PM#13
Ignitedstar
Quote:
Originally Posted by Earth-Fury
0.025 is the lowest you will realistically need for anything, ever. You will only even need such a low period if you are moving units with SetUnitX/Y. Most other things will work pretty much as well with a period more like 1/20, or even 1/10. (1/20 = 0.05. 1/40 = 0.025. 1/executions per second = period)

I can run a timer this frequently and my computer won't freak out? Awesome.
03-29-2010, 06:50 PM#14
Earth-Fury
Quote:
Originally Posted by Ignitedstar
I can run a timer this frequently and my computer won't freak out? Awesome.

1/40 is the period Grim001's physics system ran on by default. His main function was... hmnnn... When compiled, I think it actually passed 1000 lines in length. That function was run 40 times a second, most of which in a loop which executed n times per call. (n being the number of physics objects. If I recall correctly, his system had a realistic limit of something like 200-300 physics objects at a time.)

Warcraft 3 can handle a hell of a lot if you know what you are doing.

Of course, if you don't know what you are doing, it will grind to a halt if you even glance at it slightly wrong.
03-29-2010, 08:09 PM#15
darkwulfv
Quote:
That's really mean, darkwulfv. Earth-Fury spent all of that time trying to help him and you're criticizing it? He even went in depth, doing way more that he needed to. Anyone who gets a response like that should be grateful.
I was only kidding. As Earth-Fury stated, Pyrogasm was well-known for posting very huge, helpful posts. I was implying in a joking manner that Earth-Fury was being a copycat. :P