• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[vJASS] Hashtables Learning

Status
Not open for further replies.
Level 16
Joined
Mar 3, 2006
Messages
1,564
If I make a nova that works like this
JASS:
            loop
                exitwhen i >= NOVA_SIZE
                set inst.Nova[i] = CreateUnit( inst.Player , UNIT_ID , inst.X , inst.Y , A )
                set A = A + dA
                set i = i + 1
            endloop
then later I move with this
JASS:
                loop
                    exitwhen j >= NOVA_SIZE
                    set x = inst.X + inst.expand * Cos( a * bj_DEGTORAD )
                    set y = inst.Y + inst.expand * Sin( a * bj_DEGTORAD )
                    call SetUnitX( inst.Nova[j] , x )
                    call SetUnitY( inst.Nova[j] , y )
                    set j = j + 1
                    set a = a + dA
                endloop
Which is better the previous or a hashtable. If hashtable how do I use it ?

Note:
I never used hashtables before, so I decided to learn how to use them but in JASS directly (I will not learn in GUI then JASS)
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
idk in vjass but i too work on nova but in jass, i do this way with hashtable

JASS:
function Trig_HolyNova_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A004'
endfunction

function HolyNovaTimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local integer cv
    local unit pu
    local unit dummy
    local unit u = LoadUnitHandle(udg_Spell_Table, id, 1)
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real nx 
    local real ny 
    local real distance = LoadReal(udg_Spell_Table, id, 3) - 35
    local real dmg = LoadReal(udg_Spell_Table, id, 2)
    local integer nr = LoadInteger(udg_Spell_Table, id, 4)
    local real g = 360/nr
    local integer a = 0

    if distance > 0 then
        call SaveReal(udg_Spell_Table, id, 3, distance)
    loop
    exitwhen a > nr
      set dummy = LoadUnitHandle(udg_Spell_Table, id, a+5)
      set nx = GetUnitX(dummy) + 35 * Cos(a*g)  
      set ny = GetUnitY(dummy) + 35 * Sin(a*g) 

      call SetUnitPosition(dummy, nx, ny)
    set a = a + 1
    endloop

    set dummy = null

        call TimerStart(t, 0.03, false, function HolyNovaTimer)
    else

    loop
    exitwhen a > nr
      set dummy = LoadUnitHandle(udg_Spell_Table, id, a+5)
      //call RemoveUnit(dummy)
      call KillUnit(dummy)
    set a = a + 1
    endloop

        call GroupEnumUnitsInRange(udg_UG, x, y, 550, null)
        loop
            set pu = FirstOfGroup(udg_UG)
            exitwhen (pu==null)
            if IsUnitEnemy(pu, GetOwningPlayer(u)) then
                set cv = GetUnitUserData(pu)
                if LoadInteger(udg_Misc_Table, id, cv) == 0 then
                    call UnitDamageTarget(u, pu, dmg, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                endif
                call SaveInteger(udg_Misc_Table, id, cv, 1)
            endif
            call GroupRemoveUnit(udg_UG, pu)
        endloop

        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Spell_Table, id)
        call FlushChildHashtable(udg_Misc_Table, id)
    endif

    set t = null
    set u = null
endfunction


function Trig_HolyNova_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)
    local real d2 = 350.00
    local real dmg = 100
    local integer a = 0
    local integer d1 = 150
    local integer fnr = 48
    local real g = 360/fnr
    local real r
    local real x1
    local real y1
    local real xt
    local real yt
    local player p = GetTriggerPlayer()

    call SaveUnitHandle(udg_Spell_Table, id, 1, u)
    call SaveReal(udg_Spell_Table, id, 2, dmg)
    call SaveReal(udg_Spell_Table, id, 3, d2)
    call SaveInteger(udg_Spell_Table, id, 4, fnr)


        loop
           exitwhen a > fnr
            set x1 = x + 150 * Cos(a*g)  
            set y1 = y + 150 * Sin(a*g) 
            set xt = x + d2 * Cos(a*g)  
            set yt = y + d2 * Sin(a*g) 
            set r = bj_RADTODEG * Atan2(yt - y1, xt - x1)
            set u = CreateUnit (p, 'h004', x1 , y1, r)
            call SaveUnitHandle(udg_Spell_Table, id, a+5, u)
            call SetUnitPathing( u, false ) 
           set a = a + 1
        endloop

    call TimerStart(t, 0.05, false, function HolyNovaTimer)


set u = null
set t = null
set p = null
endfunction

//===========================================================================
function InitTrig_Explosive_nova takes nothing returns nothing
    set gg_trg_Explosive_nova = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Explosive_nova, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Explosive_nova, Condition( function Trig_HolyNova_Conditions ) )
    call TriggerAddAction( gg_trg_Explosive_nova, function Trig_HolyNova_Actions )
endfunction
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
What is this line, why do we need to get the ID of Handle (t) ?

local
integer id = GetHandleId(t)

t = timer
every timer got a unque integer id (so even running more timer same time but each timer got different id)

why usefull this ?

because unique its mean and be overwrited like when u use custom value or avility id etc etc, so unique for identify for 1st key.
when i create a timer and get the created timer id then i save every data like this

key1:timerid,key2:asuwant,value:asuwant

when i make single shot timer then i can get the timerid again (with GetHandleId(GetExpiredTimer())) so i call directly that data where this handle id is the key1 and when spell is over then i flush everything where is the primary key this timer id
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
u cant, i use this for fast spells, for longer spell linked list is good

for fast spell u get the id via restart the timer and get again the expired timer id so its mean for each cast u need 1 timer, but since we can use for fast thing like knockback, fireout a missile unit etc this dont matter because dont run a ton timer in same time
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Are those changes right ?

from
call SetUnitX( Nova[(dat-1)*NOVA_SIZE + j] , x )
to
call SetUnitX(LoadUnitHandle( NovaU , dat , j),x)

and also this,

set Nova[(dat-1)*NOVA_SIZE + i] = CreateUnit( dat.Owner , N_UNIT_ID , dat.Cx , dat.Cy , A ) became
JASS:
set u = CreateUnit( dat.Owner , N_UNIT_ID , dat.Cx , dat.Cy , A )
call SaveUnitHandle( NovaU , dat , i , u )
and for the destroy part,
JASS:
loop
exitwhen j >= NOVA_SIZE
   call KillUnit(LoadUnitHandle( NovaU , dat , j))
   @set Nova[(dat-1)*NOVA_SIZE + j] = null@    // this was the previous code I used
   set dat.expand = 0
set j = j + 1
endloop

call FlushChildHashtable( NovaU , dat )
 
Last edited:
Level 17
Joined
Nov 13, 2006
Messages
1,814
i will show tommorow how i made 1 timer for buffs but each unit in unit array can get more buff (so attached more special effect & number)

i remade my buff system, now it is linked list inside linked list with hashtable

header functions
JASS:
function RemoveUnitBuff takes integer id, integer index returns nothing
    local integer cv = GetUnitUserData( udg_Buff_Unit[id] )
    local integer buffid = LoadInteger( udg_Buff_Index_Table, cv, index )
    local real spd
    local integer amount = LoadInteger( udg_Buff_Amount, cv, buffid ) * -1
    local integer t =  LoadInteger( udg_Buff_Index_Table, cv, buffid )
    local unit u = udg_Buff_Unit[id]

	if index != udg_Buff_Unit_Index[cv] then
	   call SaveInteger( udg_Buff_Index_Table, cv, index, LoadInteger( udg_Buff_Index_Table, cv, udg_Buff_Unit_Index[cv] ) )
	endif
	
	set udg_Buff_Unit_Index[cv] = udg_Buff_Unit_Index[cv] - 1
	call DestroyEffect ( LoadEffectHandle(udg_Buff_EffectTable, cv, buffid))	

    call SaveInteger( udg_Buff_Timer, cv, buffid, 0 )
    call SaveInteger( udg_Buff_Amount, cv, buffid, 0 )
    if buffid==1 then
        set udg_B_Crit[cv] = udg_B_Crit[cv] + amount
    elseif buffid==2 then
        set udg_B_CritDmg[cv] = udg_B_CritDmg[cv] + amount
    elseif buffid == 3 then
        set udg_B_Eva[cv] = udg_B_Eva[cv] + amount
     endif


    if udg_Buff_Unit_Index[cv] == 0 then
          set udg_Buff_Unit_Id[cv] = 0
       if id != udg_Buff_Index then
          set udg_Buff_Unit[id] = udg_Buff_Unit[udg_Buff_Index]
          set udg_Buff_Unit_Id[GetUnitUserData(udg_Buff_Unit[id])] = id
       else

       endif
        set udg_Buff_Index = udg_Buff_Index - 1
        call FlushChildHashtable(udg_Buff_Index_Table, cv)
        call FlushChildHashtable(udg_Buff_EffectTable, cv)
        call FlushChildHashtable(udg_Buff_Timer, cv)
        call FlushChildHashtable(udg_Buff_Amount, cv)
    endif

//    call DisplayTextToPlayer( Player(0), 0, 0, "|cffffff00Remove buff a="+I2S(amount)+" array index" + I2S(udg_Buff_Index+1)+" C.Index" + I2S(id) +" buff index"+I2S(udg_Buff_Unit_Index[cv]) + " time" +I2S(t)+GetUnitName(u)+"|r")
set u = null
endfunction

function AddUnitBuff takes unit u, integer buffid, integer amount, integer dur, integer effectid, string apoint returns nothing
    local integer cv = GetUnitUserData(u)
    local integer times = LoadInteger( udg_Buff_Timer, cv, buffid )
    local integer oldv = LoadInteger( udg_Buff_Amount, cv, buffid )
    local integer diff = amount - oldv
    local integer pl = GetPlayerId(GetOwningPlayer(u)) + 1
    local real spd

    if udg_Buff_Unit_Id[cv] == 0 then
	set udg_Buff_Index = udg_Buff_Index + 1
        set udg_Buff_Unit[udg_Buff_Index] = u
        set udg_Buff_Unit_Id[cv] = udg_Buff_Index
    
    endif

    if times == 0 then
	    set udg_Buff_Unit_Index[cv] = udg_Buff_Unit_Index[cv] + 1
		call SaveInteger( udg_Buff_Index_Table, cv, udg_Buff_Unit_Index[cv], buffid )
		
       if effectid > - 1 then
	    call SaveEffectHandle(udg_Buff_EffectTable, cv, buffid, AddSpecialEffectTarget( udg_Effects[effectid], u, apoint ))
        endif
    endif
	
    call SaveInteger( udg_Buff_Amount, cv, buffid, amount )
    call SaveInteger( udg_Buff_Timer, cv, buffid, dur )

//    call DisplayTextToPlayer( Player(0), 0, 0, "dur=" + I2S(dur) + " amount="+I2S(amount)+" unit index in unit array" + I2S(udg_Buff_Index) +" unit buff index"+I2S(udg_Buff_Unit_Index[cv]))

    if buffid == 1 and oldv == 0 then
        set udg_B_CritDmg[cv] = udg_B_CritDmg[cv] + diff
    elseif buffid == 2 and oldv == 0  then
       set udg_B_Crit[cv] = udg_B_Crit[cv] + diff
    elseif buffid == 3 then
        set udg_B_Eva[cv] = udg_B_Eva[cv] + diff
    endif
    call DisplayTextToPlayer( Player(0), 0, 0, "|cffff0000b.id=" + I2S(buffid) + " diff="+I2S(diff)+" array index"+I2S(udg_Buff_Index)+" b amount"+I2S(udg_Buff_Unit_Id[cv])+"|r")

endfunction

timer trigger action
JASS:
    local integer i = 1
    local integer ii = 1
    local integer pv = 0
    local integer cc
    local integer po = 0
    local integer cv
    local integer buffid = 0
    local integer times = 0
    local integer vigor = 0
    loop
        exitwhen i > udg_Buff_Index
        set cv = GetUnitUserData(udg_Buff_Unit[i])
        if IsUnitType(udg_Buff_Unit[i], UNIT_TYPE_DEAD) or udg_Buff_Purge[cv] then
            //call ClearUnitBuff (i) not done but easy to do it with loop
        else
            loop
                exitwhen ii > udg_Buff_Unit_Index[cv]
                set buffid = LoadInteger(udg_Buff_Index_Table, cv, ii)
                set times = LoadInteger(udg_Buff_Timer, cv, buffid)
                 if times == 0 then
                     call RemoveUnitBuff (i, ii)
                else
                    call SaveInteger(udg_Buff_Timer, cv, buffid, times - 1)
                endif
                set ii = ii + 1
            endloop
            set ii = 1
            set udg_Buff_Purge[cv] = false
        endif
        set i = i + 1
    endloop
 
Status
Not open for further replies.
Top