wc3campaigns
WC3C Homepage - www.wc3c.netUser Control Panel (Requires Log-In)Engage in discussions with other users and join contests in the WC3C forums!Read one of our many tutorials, ranging in difficulty from beginner to advanced!Show off your artistic talents in the WC3C Gallery!Download quality models, textures, spells (vJASS/JASS), systems, and scripts!Download maps that have passed through our rigorous approval process!

Go Back   Wc3C.net > Warcraft III Modding > Developer's Corner > Triggers & Scripts
User Name
Password
Register Rules Get Hosted! Chat Pastebin FAQ and Rules Members List Calendar



Reply
 
Thread Tools Search this Thread
Old 03-28-2010, 06:25 AM   #1
Tom_Kazansky
User
 
Tom_Kazansky's Avatar
 
Join Date: Apr 2009
Posts: 74

Tom_Kazansky is on a distinguished road (13)

Send a message via Yahoo to Tom_Kazansky
Default I need help from experts

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

Last edited by Tom_Kazansky : 03-28-2010 at 11:20 AM.
Tom_Kazansky is offline   Reply With Quote
Sponsored Links - Login to hide this ad!
Old 03-28-2010, 06:45 AM   #2
Earth-Fury
Two Blue
 
Earth-Fury's Avatar
 
Join Date: Mar 2003
Posts: 2,179

Submissions (7)

Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)

Send a message via MSN to Earth-Fury
Default

  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.
__________________
Useful Links:
My Resources:
Good Resources:
Search
Tutorials
Ability Guide

UnitMaxState
BonusMod

AutoIndex
ARGB
TimerUtils


Last edited by Earth-Fury : 03-28-2010 at 06:46 AM.
Earth-Fury is offline   Reply With Quote
Old 03-28-2010, 11:02 AM   #3
Tom_Kazansky
User
 
Tom_Kazansky's Avatar
 
Join Date: Apr 2009
Posts: 74

Tom_Kazansky is on a distinguished road (13)

Send a message via Yahoo to Tom_Kazansky
Default

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

Last edited by Tom_Kazansky : 03-28-2010 at 11:19 AM.
Tom_Kazansky is offline   Reply With Quote
Old 03-28-2010, 01:10 PM   #4
Earth-Fury
Two Blue
 
Earth-Fury's Avatar
 
Join Date: Mar 2003
Posts: 2,179

Submissions (7)

Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)

Send a message via MSN to Earth-Fury
Default

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.
__________________
Useful Links:
My Resources:
Good Resources:
Search
Tutorials
Ability Guide

UnitMaxState
BonusMod

AutoIndex
ARGB
TimerUtils

Earth-Fury is offline   Reply With Quote
Old 03-28-2010, 01:37 PM   #5
darkwulfv
Alpha Male of Wc3c
 
darkwulfv's Avatar


Official Map Reviewer
 
Join Date: Mar 2006
Posts: 3,646

Submissions (6)

darkwulfv is just really nice (270)darkwulfv is just really nice (270)

Send a message via AIM to darkwulfv
Default

@Earth-Fury
Who do you think you are, Pyrogasm?
__________________
The Spell Request Thread
Quote:
Originally Posted by Joe-Black-5
a dota like map but with unique stuff
(There was no map attached, and that was all the thread said.)
Spells I've Made

Darkwulfv's Lightning Grapple || Tritanis' Lazy Bolt


Last edited by darkwulfv : 03-28-2010 at 01:37 PM.
darkwulfv is offline   Reply With Quote
Old 03-29-2010, 07:55 AM   #6
Ignitedstar
Moderator
 
Ignitedstar's Avatar


RP Section Moderator
 
Join Date: Jul 2005
Posts: 1,755

Ignitedstar has a spectacular aura about (102)Ignitedstar has a spectacular aura about (102)Ignitedstar has a spectacular aura about (102)Ignitedstar has a spectacular aura about (102)

Send a message via MSN to Ignitedstar Send a message via Yahoo to Ignitedstar
Default

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.
__________________
Current Activity: It's a secret, now.
Evaluation: I actually logged in?!?!
"If I speak in the tongues of men and of angels, but have not love,
I am only a resounding gong or a clanging cymbal.
If I have the gift of prophecy and can fathom all mysteries and all knowledge,
and if I have a faith that can move mountains, but have not love, I am nothing."

— 1 Corinthians 13:1-2

Current Works:
None.
Ignitedstar is offline   Reply With Quote
Old 03-29-2010, 07:57 AM   #7
Tom_Kazansky
User
 
Tom_Kazansky's Avatar
 
Join Date: Apr 2009
Posts: 74

Tom_Kazansky is on a distinguished road (13)

Send a message via Yahoo to Tom_Kazansky
Default

@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.

Last edited by Tom_Kazansky : 03-29-2010 at 07:59 AM.
Tom_Kazansky is offline   Reply With Quote
Old 03-29-2010, 09:25 AM   #8
Earth-Fury
Two Blue
 
Earth-Fury's Avatar
 
Join Date: Mar 2003
Posts: 2,179

Submissions (7)

Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)

Send a message via MSN to Earth-Fury
Default

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.
__________________
Useful Links:
My Resources:
Good Resources:
Search
Tutorials
Ability Guide

UnitMaxState
BonusMod

AutoIndex
ARGB
TimerUtils

Earth-Fury is offline   Reply With Quote
Old 03-29-2010, 09:45 AM   #9
Tom_Kazansky
User
 
Tom_Kazansky's Avatar
 
Join Date: Apr 2009
Posts: 74

Tom_Kazansky is on a distinguished road (13)

Send a message via Yahoo to Tom_Kazansky
Default

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 )
Tom_Kazansky is offline   Reply With Quote
Old 03-29-2010, 10:15 AM   #10
Earth-Fury
Two Blue
 
Earth-Fury's Avatar
 
Join Date: Mar 2003
Posts: 2,179

Submissions (7)

Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)

Send a message via MSN to Earth-Fury
Default

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.
__________________
Useful Links:
My Resources:
Good Resources:
Search
Tutorials
Ability Guide

UnitMaxState
BonusMod

AutoIndex
ARGB
TimerUtils

Earth-Fury is offline   Reply With Quote
Old 03-29-2010, 10:44 AM   #11
Tom_Kazansky
User
 
Tom_Kazansky's Avatar
 
Join Date: Apr 2009
Posts: 74

Tom_Kazansky is on a distinguished road (13)

Send a message via Yahoo to Tom_Kazansky
Default

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

Last edited by Tom_Kazansky : 03-29-2010 at 10:45 AM.
Tom_Kazansky is offline   Reply With Quote
Old 03-29-2010, 10:53 AM   #12
Kueken
User
 
Join Date: Mar 2009
Posts: 149

Kueken will become famous soon enough (41)Kueken will become famous soon enough (41)

Default

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 ;)

Last edited by Kueken : 03-29-2010 at 10:53 AM.
Kueken is offline   Reply With Quote
Old 03-29-2010, 06:45 PM   #13
Ignitedstar
Moderator
 
Ignitedstar's Avatar


RP Section Moderator
 
Join Date: Jul 2005
Posts: 1,755

Ignitedstar has a spectacular aura about (102)Ignitedstar has a spectacular aura about (102)Ignitedstar has a spectacular aura about (102)Ignitedstar has a spectacular aura about (102)

Send a message via MSN to Ignitedstar Send a message via Yahoo to Ignitedstar
Default

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.
__________________
Current Activity: It's a secret, now.
Evaluation: I actually logged in?!?!
"If I speak in the tongues of men and of angels, but have not love,
I am only a resounding gong or a clanging cymbal.
If I have the gift of prophecy and can fathom all mysteries and all knowledge,
and if I have a faith that can move mountains, but have not love, I am nothing."

— 1 Corinthians 13:1-2

Current Works:
None.
Ignitedstar is offline   Reply With Quote
Old 03-29-2010, 06:50 PM   #14
Earth-Fury
Two Blue
 
Earth-Fury's Avatar
 
Join Date: Mar 2003
Posts: 2,179

Submissions (7)

Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)

Send a message via MSN to Earth-Fury
Default

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.
__________________
Useful Links:
My Resources:
Good Resources:
Search
Tutorials
Ability Guide

UnitMaxState
BonusMod

AutoIndex
ARGB
TimerUtils

Earth-Fury is offline   Reply With Quote
Old 03-29-2010, 08:09 PM   #15
darkwulfv
Alpha Male of Wc3c
 
darkwulfv's Avatar


Official Map Reviewer
 
Join Date: Mar 2006
Posts: 3,646

Submissions (6)

darkwulfv is just really nice (270)darkwulfv is just really nice (270)

Send a message via AIM to darkwulfv
Default

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
__________________
The Spell Request Thread
Quote:
Originally Posted by Joe-Black-5
a dota like map but with unique stuff
(There was no map attached, and that was all the thread said.)
Spells I've Made

Darkwulfv's Lightning Grapple || Tritanis' Lazy Bolt

darkwulfv is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT. The time now is 10:15 PM.


Affiliates
The Hubb The JASS Vault Clan WEnW Campaign Creations Clan CBS GamesModding Flixreel Videos

Powered by vBulletin (Copyright ©2000 - 2019, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services