• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Linked list (how can i make special effect group)

Status
Not open for further replies.
Level 17
Joined
Nov 13, 2006
Messages
1,814
my question is: can i use linked list system for make something like special effect group (not exist but i mean something what work like unit group, just with special effect)
because i dont understanded well, so i got its replace 1 hole, but what happen when suddenly have lets say 10 hole (destroy 10 special effect) and later in another trigger i create another (lets say 7) special effect, then 1st effect get 1 from 10 hole but another special effect?
i give a example:
f[0]= a special effect
f[1]= a special effect
f[2]= a special effect
f[3]= a special effect
f[4]= a special effect

if i destroy 1,2,3 and create 4 special effect then
index will be 1,2,3,5 or 1,5,6,7?




Dynamic Indexing is a process that finds a new index for you to use in the data arrays.

This is how it's done in Jass:

You need 2 variables:
JASS:
integer array nextRecycle
integer iCount = 0

Instead of hashtables, we're going to use arrays.
So, declare arrays for anything you need:

unit array caster
real array heal
integer array level
etc...

When a unit casts a spell, the first thing we're going to do is get a special index:

JASS:
local integer index = nextRecycle[0]

// if the index is null
if index == 0 then
    // nothing in the recycler, so we just add instances from the top
    set iCount = iCount + 1
    set index = iCount
else
    // we set the next instance to be recycled
    set nextRecycle[0] = nextRecycle[this]
endif

After this, index is going to be equal to the index that we're going to use in our arrays.

Now, since we're going to use only one timer, we need a way to put all the instances in a list for the timer to loop over.

Let's do a linked list then ^_^
You can lookup linked lists on Google if you don't know what they are ;p

Here's how it works:
You need 2 integer arrays (next and prev)

When we want to put something in a linked list, we do this:

JASS:
// We set the next one in the list to 0
set next[index] = 0
// We set the one behind it to the last added instance
set prev[index] = prev[0]
// We set the next of the one behind it to this
set next[prev[0]] = index
// We set the last added instance to this
set prev[0] = index

This is what we should after allocating an instance (index)

After we do this, we should declare another variable called "amount"
This integer variable is going to be increased by one every time we cast the spell and decreased by 1 every time we end the spell.

Now we get to the easy part:

We set the data:

JASS:
set caster[index] = GetTriggerUnit()
set duration[index] = bleh
set ble[index] = bla

etc..


Then we should check if amount == 1.
If it does, we start the timer.


The timer will call a function that loops over the list like this:

JASS:
function Loop takes nothing returns nothing
    local integer this = next[0] // get the first instance in the list
    
    loop
        // Exit when we hit a null instance (the end of the list)
        exitwhen this == 0
        
        // do spell loop actions using "this" as the index for the arrays

        // we go to the next one in the list
        set this = next[this]
    endloop
endfunction

Now when a unit finishes casting a spell, we have to do 3 things:


First, let's deallocate the index.

To deallocate an index, we do this:


JASS:
// Set the one that we have to recycle after this to the one that we were just going to recycle
set nextRecycle[INDEX] = nextRecycle[0]
// Set the one that we're going to recycle now to this
set nextRecycle[0] = INDEX

Next, we're going to remove it from the list so we dont keep looping over it again and again:

JASS:
set next[prev[INDEX]] = next[INDEX]
set prev[next[INDEX]] = prev[INDEX]

Finally, we decrease the amount:


set amount = amount - 1

Then, to wrap it all up (OUTSIDE of that loop in the timer function):


JASS:
if amount == 0 then
    call PauseTimer(timer)
endif

Done! :)


or this

http://www.hiveworkshop.com/forums/...array-linked-list-stack-queue-dequeue-188528/
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
my question is: can i use linked list system for make something like special effect group (not exist but i mean something what work like unit group, just with special effect)
because i dont understanded well, so i got its replace 1 hole, but what happen when suddenly have lets say 10 hole (destroy 10 special effect) and later in another trigger i create another (lets say 7) special effect, then 1st effect get 1 from 10 hole but another special effect?
i give a example:
f[0]= a special effect
f[1]= a special effect
f[2]= a special effect
f[3]= a special effect
f[4]= a special effect

if i destroy 1,2,3 and create 4 special effect then
index will be 1,2,3,5 or 1,5,6,7?







or this

http://www.hiveworkshop.com/forums/...array-linked-list-stack-queue-dequeue-188528/

In my example that I've send you through PM you can see how the "holes" can be removed.
And how you can separate the effects into different non-existing groups with a condition.

JASS:
local integer i
local integer i2
set i = 1
//here we loop through all the indexes of the array to execute specific functions for each effect individually
loop
   exitwhen i > udg_index
   //create an if here to specify which effects you want to be destroyed "non-existing group"
   if somecondition == true then
      //Here we destroy the effect and remove the effect from the array:
      call DestroyEffect(udg_effect[i])
      set udg_effect[i] = null
      //so lets say i = 5 and udg_index = 23
      //now we loop from 5-22 in order to move all the other values in the array 1 index down so that the array doesn't contain any gaps.
      set i2 = i //this is to make sure that local integer i doesn't get changed for the loop it's currently in.
      loop
         exitwhen i2 == udg_index //exitwhen i2 == 23
         set udg_effect[i2] = udg_effect[i2 + 1] //set udg_effect[5] = udg_effect[6]
         set udg_effect[i2 +1] = null //set udg_effect[6] = null
         set i2 = i2 + 1 //repeat untill udg_effect[22] = udg_effect[23] and udg_effect[23] = null
      endloop
      set udg_index = udg_index - 1 //decrease the index by 1 since the last index is now 22
   endif
endloop

I hope you can comprehend this ^.^

if i destroy 1,2,3 and create 4 special effect then
index will be 1,2,3,5 or 1,5,6,7?

With my example if you destroy 1, 2, 3 and create special effect 4 then special effect 4 is 1

so lets say you have 1, 2, 3, 4, 5, 6 and destroy 3, 4, 5 then when you create a new special effect the array would be 1, 2, 3, 4
the effect that was stored in array 6 will now be in array 3 and the newly created special effect will now be in array 4.

EDIT: If you want to destroy them in a different trigger, then you would have to use the loop again to move the effects down in the array.
You can create a function for this and call it whenever you need to clean up the array.

So lets say for example you do something like this:

call DestroyEffect(udg_effect[2])
set udg_effect[2] = null
call cleanEffectArray(2)
JASS:
function cleanEffectArray takes integer whichIndex returns nothing
      loop
         exitwhen whichIndex == udg_index
         set udg_effect[whichIndex] = udg_effect[whichIndex + 1]
         set udg_effect[whichIndex + 1] = null
         set whichIndex = whichIndex + 1
      endloop
      set udg_index = udg_index - 1
endfunction
To create a new effect you simply do:
set udg_index = udg_index + 1
set udg_effect[udg_index] = my effect


This method can be used to group any type of handle.
Respectively you can even create a second variable to store information on the handles that are being stored.

So for example:

set udg_index = udg_index + 1
set udg_effect[udg_index] = my effect
set udg_effectPosition[udg_index] = position of my effect

This way you can link any information to the effect that is being stored, however you do have to make sure that you clean the array of the second variable too... ;)
But I guess this can easily be integrated into the function I posted above.

Have fun.
 
Last edited:
Level 17
Joined
Nov 13, 2006
Messages
1,814
ok but problem is if it is changed by destroying then its too dynamic, so i mean example i have a unit group and i want link the special effects with unit, like each buff=1special effect

(was a bit hard the pm in night time for my dead brain but mainly i noticed this

If the unit has 2 buffs set the custom value to 2.
You can use any if to indicate in which type of group it needs to belong to.

i use CV for attach buff amount to unit via hashtable(key is cv & buff id) but even that have many potentional combination so i think about make something like this
buff 1 value=1
buff 2 value=2
buff 3 value=4
buff 4 value=8
buff 5 value=16
buff 6 value=32
buff 7 value=64
buff 8 value=128
buff 9 value=256
buff 10 value=512

so if unit have buff 10 and buff 1 then it is 513, so can calculate what buff got the unit
)

so i save to hashtable the effect index the keys are unit custom value and buff id

so with a single group i try handle this combined buff thing.

if unit cast a trigger buff:
-i add to unit group every buffed unit
-save to hashtable effect index where keys are unit CV & my Buff id (hashtable 1)
-save to hashtable the time remaing value where key is CV & my Buff id (hashtable 2)
-save to hashtable the buff value value where key is CV & my Buff id (hashtable 3)
-periodic trigger check every unit in unit group and check if unit alive or got purge if yes then destroy effect, do some action set time/buff value to 0
if unit alive and not purged then decrease time by 1

but if example i detroy effect[3] and its automatical replaced with next index so effect[4] after destroying the effect 3 will be 3 then the saved effect index in hashtable is invalid coz index 4 is 3, so cant destroy that effect what was the 4th index before.

example
i add to unit a shadowstrike effect, lets say it is index 5, i destroy 3, then 5 will be 4 and i cant destroy the original shadowstrike effect if it is expired.

so anyway if i use a loop and new effect get same index than the 1st destroyed but i let existing index same as it was then its not noticeable in cpu usage even it is lets say a loop with 1000 integer checking and replaceing, right?
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
You don't nessecarely have to use hashtables for this. As I have explained in my edit, it is possible to link information to any handle that is stored.

So for example:

Create 2 arrays for the buffs.
Then at initialization do something like:
set udg_buffType[1] = buffID of buff 1
set udg_buffType[2] = buffID of buff 2
set udg_buffType[3] = buffID of buff 3
set udg_buffType[4] = buffID of buff 4
set udg_buffType[5] = buffID of buff 5
set udg_buffType[6] = buffID of buff 6
set udg_buffType[7] = buffID of buff 7
set udg_buffType[8] = buffID of buff 8
set udg_buffType[9] = buffID of buff 9
set udg_buffType[10] = buffID of buff 10
set udg_buff[1]=1
set udg_buff[2]=2
set udg_buff[3]=4
set udg_buff[4]=8
set udg_buff[5]=16
set udg_buff[6]=32
set udg_buff[7]=64
set udg_buff[8]=128
set udg_buff[9]=256
set udg_buff[10]=512

Now in the trigger where you create the unit you do this:
set udg_index = udg_index + 1
set udg_unit[udg_index] = create your unit

Now in the trigger where you check if the unit has a buff do this:
JASS:
function checkUnitBuff takes nothing returns nothing
local integer i = 1 //This will loop through the units
local integer i2 = 1 //This will loop through the buff types and buff values
local integer buffCounter = 0 //This will count the buff values in order to assign it to the unit
loop
   exitwhen i > udg_index //loop through the units
   loop
      exitwhen i2> 10 //loop through the buffs
      if udg_unit[i] has buffType[i2] then //if the unit has a buff of type ... then increase the buffcounter and set it to udg_unitHasBuff
         set buffCounter = buffCounter + udg_buff[i2]
         set udg_unitHasBuff[i] = buffCounter
      endif
      set i2 = i2 + 1
  endloop
  set buffCounter = 0 //set buffCounter back to 0 after looping through the buffs for each unit so that the next unit that gets checked doesn't have the buffcounter from the previous unit that was checked.
  set i = i + 1
endloop
endfunction

Now it is like this:
udg_unit[2] = yourunit
udg_unitHasBuff[2] = 513

So what if the array gets cleaned?
Simple, you make sure unitHasBuff will also be cleaned.

JASS:
function cleanArray takes integer whichIndex returns nothing
      loop
         exitwhen whichIndex == udg_index
         set udg_unit[whichIndex] = udg_unit[whichIndex + 1]
         set udg_unitHasBuff[whichIndex] = udg_unitHasBuff[whichIndex + 1]
         set udg_unit[whichIndex + 1] = null
         set udg_unitHasBuff[whichIndex + 1] = null
         set whichIndex = whichIndex + 1
      endloop
      set udg_index = udg_index - 1
endfunction

Now when the unit needs to be removed from the array you do this:
set udg_unit[2] = null
set udg_unitHasBuff[2] = null
call cleanArray(2)

Congratulations, you have just attached your buff value to your unit!

(actually, you don't even have to null any variable in here, why? because they get overwritten in cleanArray)
If they get overwritten, then why use this inside cleanArray anyways?

JASS:
set udg_unit[whichIndex + 1] = null
set udg_unitHasBuff[whichIndex + 1] = null
Because the last value in the array needs to be nulled, and to prevent any bugs while overwriting it might be usefull to null them.

EDIT: I just realised the last index doesn't have to be nulled because it gets overwritten when the next unit is created. You can remove all the null stuff :p
allthough, if the next unit never gets created then the last index is filled with data for no reason. It's probably best to null it anyways to make sure you're not storing unnessecary data...

It should be really simple to determine which unit has which buff because you can now do:
JASS:
function checkWhichUnitHasWhichBuffs takes nothing returns nothing
local integer i
loop
   exitwhen i > udg_index
   if udg_unitHasBuff[i] == 513 then //so basically what your saying here is: if udg_unit[i] has buff 1 and buff 10 then ...
      do something with udg_unit[i] here
   endif
   set i = i + 1
endloop
endfunction


EDIT 2: I haven't tested any of this, this was all from the top of my head without going into the world editor. If some things won't work, contact me and I'll try to fix it for you ;)
In theory it should work though... If it doesn't I must have overlooked something.
 
Last edited:
Level 17
Joined
Nov 13, 2006
Messages
1,814
i told its trigger buff, not real, not show in ui, its just a data in hashtable like

i save to hashtable 5 (key unit custom value, and physical defence buff{lets say 14})
so this is the buff


after x minute or second i just change it back to 0, ok actually for every buff was attached a special effect to targeted unit

problem is there when i attach special effect to unit coz i cant use this udg_effect[unit custom value] because eahc unit can get more buff, also cant unithasbuff since not a real buff just data in hashtable, also cant use a simple linked list since i dont see the point how can be attached more effect index to a single unit (i try with hashtable)

same with timer

local integer i
local integer i2
set i = 1
//here we loop through all the indexes of the array to execute specific functions for each effect individually
loop
exitwhen i > udg_index
//create an if here to specify which effects you want to be destroyed "non-existing group"
if somecondition == true then
//Here we destroy the effect and remove the effect from the array:
call DestroyEffect(udg_effect)
set udg_effect = null
//so lets say i = 5 and udg_index = 23
//now we loop from 5-22 in order to move all the other values in the array 1 index down so that the array doesn't contain any gaps.
set i2 = i //this is to make sure that local integer i doesn't get changed for the loop it's currently in.
loop
exitwhen i2 == udg_index //exitwhen i2 == 23
set udg_effect[i2] = udg_effect[i2 + 1] //set udg_effect[5] = udg_effect[6]
set udg_effect[i2 +1] = null //set udg_effect[6] = null
set i2 = i2 + 1 //repeat untill udg_effect[22] = udg_effect[23] and udg_effect[23] = null
endloop
set udg_index = udg_index - 1 //decrease the index by 1 since the last index is now 22
endif
endloop
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
Finnally i made it in NORMAL JASS :p, just need few good eye for check if something could be better or no

so over all i made custom buffs without abilities and without unit group with single timer and could attach more special effect/value/timer to single unit with few hashtable and global array

Uploaded the demo map for try it and tell ur opinion about it

so here the code:

Map Header & Map init:

JASS:
function NewEffectIndex takes nothing returns integer
    local integer i = 0
    loop
        exitwhen udg_Buff_Effect[i] == null
        set i = i + 1
    endloop
    return i
endfunction

function NewUnitIndex takes nothing returns integer
    local integer i = 0
    loop
        exitwhen udg_Buff_Unit[i] == null
        set i = i + 1
    endloop
    return i
endfunction

function CountUnitBuff takes integer cv returns integer
    local integer i = 25 //max buff amount on unit
    local integer bv = udg_Buff_Value[cv]
    local integer r = 0
    loop
        exitwhen bv == 0
        if bv > R2I(Pow(2, i)) then
            set bv = bv - R2I(Pow(2, i))
            set r = r + 1
        endif
        set i = i - 1
    endloop
    return r
endfunction

function RemoveUnitBuff takes integer id, integer buffid returns nothing
    local integer cv = GetUnitUserData(udg_Buff_Unit[id])
    local integer e = LoadInteger(udg_Buff_EffectTable, cv, buffid)
    local integer v = LoadInteger(udg_Buff_Amount, cv, buffid)
    set udg_Buff_Value[cv] = udg_Buff_Value[cv] - R2I(Pow(2, buffid))
    call DestroyEffect (udg_Buff_Effect[e])
    call SaveInteger(udg_Buff_EffectTable, cv, buffid, 0)
    call SaveInteger(udg_Buff_Timer, cv, buffid, 0)
    call SaveInteger(udg_Buff_Amount, cv, buffid, 0)
    if udg_Buff_Value[cv] == 0 then
        set udg_Buff_Unit[id] = null
    endif
    if buffid==2 then
            set udg_Critical[cv] = udg_Critical[cv] - v
    endif
    if buffid==3 then
            set udg_Eva[cv] = udg_Eva[cv] - v
    endif
endfunction

function log takes integer n returns integer
    local integer i = 2
    local integer c = 1
    if n == 1 then
        set c = 0
    endif
    loop
        exitwhen i >= n
        set c = c + 1
        set i = i * 2
    endloop
    return c
endfunction
Map init
JASS:
function Trig_Melee_Initialization_Actions takes nothing returns nothing
local integer i = 0
local integer v = 1
set udg_Buff_Timer = InitHashtable()
set udg_Buff_EffectTable = InitHashtable()
set udg_Buff_Amount = InitHashtable()
set udg_Effect[0] = "Abilities\\Spells\\NightElf\\Barkskin\\BarkSkinTarget.mdl"
set udg_Effect[1] = "Abilities\\Spells\\Undead\\Cripple\\CrippleTarget.mdl"
set udg_Buff_Max = 29
//set bufftype(buffvalue) and buffid (bufftype=2^buffid)
    loop
        exitwhen i > 10
        set udg_Buff_Type[i] = v
        set i = i + 1
        set udg_Buff_ID[i] = i
        set v = v * 2
    endloop
endfunction

//===========================================================================
function InitTrig_Map_Initialization takes nothing returns nothing
    set gg_trg_Map_Initialization = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Map_Initialization, function Trig_Melee_Initialization_Actions )
endfunction


Casting Buffs:

JASS:
function Trig_Cast_buff_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A002'
endfunction

function Trig_Cast_buff_Actions takes nothing returns nothing
    local integer buffid = 2 //buff id
    local integer buffvalue = R2I(Pow(2, buffid)) //buffvalue what i add to unit buff value
    local integer dur = 10 //duration in sec
    local unit u = GetTriggerUnit()
    local integer alv = GetUnitAbilityLevel(u, 'A002')
    local unit pu
    local player p = GetTriggerPlayer()
    local integer cv
    local integer nuIndex //new unit array index
    local integer neIndex //new effect array index
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local integer times
    call GroupEnumUnitsInRange(udg_UG, x, y, 350.00, null)
    loop
        set pu = FirstOfGroup(udg_UG)
        exitwhen (pu==null)
        set cv = GetUnitUserData(pu)
        set times = LoadInteger(udg_Buff_Timer, cv, buffid)
        if not IsUnitEnemy(pu, p) and times == 0 then //if unit dont have timer, and unit is not enemy
            set nuIndex = NewUnitIndex()
            set neIndex = NewEffectIndex()
    if udg_Buff_Value[cv] == 0 then            
            set udg_Buff_Unit[nuIndex] = pu
     endif
            set udg_Critical[cv] = udg_Critical[cv] + alv * 15
            set udg_Buff_Value[cv] = udg_Buff_Value[cv] + buffvalue
            set udg_Buff_Effect[neIndex] = AddSpecialEffectTarget( udg_Effect[0], pu, "overhead" )
            call SaveInteger(udg_Buff_EffectTable, cv, buffid, neIndex)
            call SaveInteger(udg_Buff_Amount, cv, buffid, alv * 15)
            call SaveInteger(udg_Buff_Timer, cv, buffid, dur)
            call DisplayTextToForce( GetPlayersAll(), "Buffed unit name:" + GetUnitName(udg_Buff_Unit[nuIndex]) + "  duration:" + I2S(dur) + "  buff id:" + I2S(buffid) + "  effect id:" + I2S(neIndex) + "   buff value:" + I2S(udg_Buff_Value[cv]))
            if nuIndex > udg_index then
                set udg_index = nuIndex
            endif
            
        endif
        call GroupRemoveUnit(udg_UG, pu)
    endloop

    set u = null
    set p = null
    set pu = null
endfunction

//===========================================================================
function InitTrig_Cast_buff takes nothing returns nothing
    set gg_trg_Cast_buff = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Cast_buff, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
    call TriggerAddCondition( gg_trg_Cast_buff, Condition( function Trig_Cast_buff_Conditions ) )
    call TriggerAddAction( gg_trg_Cast_buff, function Trig_Cast_buff_Actions )
endfunction
JASS:
function Trig_Cast_buff2_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A001'
endfunction

function Trig_Cast_buff2_Actions takes nothing returns nothing
    local integer buffid = 3 //buff id
    local integer buffvalue = R2I(Pow(2, buffid)) //buffvalue what i add to unit buff value
    local integer dur = 10 //duration in sec
    local unit u = GetTriggerUnit()
    local integer alv = GetUnitAbilityLevel(u, 'A001')
    local unit pu
    local player p = GetTriggerPlayer()
    local integer cv
    local integer nuIndex //new unit array index
    local integer neIndex //new effect array index
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local integer times
    call GroupEnumUnitsInRange(udg_UG, x, y, 350.00, null)
    loop
        set pu = FirstOfGroup(udg_UG)
        exitwhen (pu==null)
        set cv = GetUnitUserData(pu)
        set times = LoadInteger(udg_Buff_Timer, cv, buffid)
        if not IsUnitEnemy(pu, p) and times == 0 then //if unit dont have timer, and unit is not enemy
            set nuIndex = NewUnitIndex()
            set neIndex = NewEffectIndex()
    if udg_Buff_Value[cv] == 0 then     
            set udg_Buff_Unit[nuIndex] = pu
    endif
            set udg_Eva[cv] = udg_Eva[cv] + alv * 15
            set udg_Buff_Value[cv] = udg_Buff_Value[cv] + buffvalue
            set udg_Buff_Effect[neIndex] = AddSpecialEffectTarget( udg_Effect[1], pu, "chest" )
            call SaveInteger(udg_Buff_EffectTable, cv, buffid, neIndex)
            call SaveInteger(udg_Buff_Amount, cv, buffid, alv * 15)
            call SaveInteger(udg_Buff_Timer, cv, buffid, dur)
            call DisplayTextToForce( GetPlayersAll(), "Buffed unit name:" + GetUnitName(udg_Buff_Unit[nuIndex]) + "  duration:" + I2S(dur) + "  buff id:" + I2S(buffid) + "  effect id:" + I2S(neIndex) + "   buff value:" + I2S(udg_Buff_Value[cv]))
            if nuIndex > udg_index then
                set udg_index = nuIndex
            endif
       
        endif
        call GroupRemoveUnit(udg_UG, pu)
    endloop

    set u = null
    set p = null
    set pu = null
endfunction

//===========================================================================
function InitTrig_Cast_buff2 takes nothing returns nothing
    set gg_trg_Cast_buff2 = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Cast_buff2, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
    call TriggerAddCondition( gg_trg_Cast_buff2, Condition( function Trig_Cast_buff2_Conditions ) )
    call TriggerAddAction( gg_trg_Cast_buff2, function Trig_Cast_buff2_Actions )
endfunction


Timer:

JASS:
function Trig_Timer_Actions takes nothing returns nothing
    local integer buffvalue // R2I(Pow(buffid, 2)) buffvalue what i add to unit buff value
    local integer bv //buff value
    local integer i = 0
    local integer po = 0
    local integer cv
    local integer count = 0
    local integer buffid = 0
    local integer maxbuff = udg_Buff_Max
    local integer times = 0
    loop
        exitwhen i > udg_index
        if udg_Buff_Unit[i] != null then
            set cv = GetUnitUserData(udg_Buff_Unit[i])
            set bv = udg_Buff_Value[cv]
            if bv > 0 then
                loop
                    exitwhen bv == 0
                    set po = R2I(Pow(2, maxbuff - count))
                    if bv >= po then
                        set bv = bv - po
                        set buffid = log(po)//maxbuff - count
                        set times = LoadInteger(udg_Buff_Timer, cv, buffid)
                        if IsUnitType(udg_Buff_Unit[i], UNIT_TYPE_DEAD) or udg_Buff_Purge[cv] then
                             set times = 0
                             set udg_Buff_Purge[cv] = false
                        endif
                    call DisplayTextToForce( GetPlayersAll(), "Unit[" + I2S(i) + "] = " + GetUnitName(udg_Buff_Unit[i]) + ": buff value:" + I2S(bv) + " | Buff id:" + I2S(buffid) + " | Unit custom value:" + I2S(cv) +" | time left:"+I2S(times)  )
                        if times < 1 then
                            call RemoveUnitBuff (i, buffid)
                        else
                            call SaveInteger(udg_Buff_Timer, cv, buffid, times - 1)
                        endif
                    endif
                    set count = count + 1
                endloop
            endif
            set count = 0
        endif
        set i = i + 1
    endloop

endfunction

//===========================================================================
function InitTrig_Timer takes nothing returns nothing
    set gg_trg_Timer = CreateTrigger( )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Timer, 1.00 )
    call TriggerAddAction( gg_trg_Timer, function Trig_Timer_Actions )
endfunction
 

Attachments

  • buff test.w3x
    38.2 KB · Views: 32
Status
Not open for further replies.
Top