• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] Filtering and UnitGroup Help PLEASE

Status
Not open for further replies.
Level 6
Joined
May 15, 2008
Messages
146
OK, I'm doing some systems for wave-like spells and I need these things cleared up.

Q1 - After trying various ways to save a unit group to a hashtable I found out eventualy that

JASS:
call SaveGroupHandle(Hashtable, Pkey, Ckey, ExampleGroup)

does not work under any circumstances. Or maybe the LoadGroupHashtable doesn't work but I cannot really know which one is if I cannot load the saved content. Problem is that it's (I guess) inefficient to make a timer for each unit affected by spell and then run it than to cycle through one group using one timer. I thought of a way to work around this but it's somewhat complex than just saving so I would like to know if this functions can be get to work??

Q2 - I need the filtering thingie cleared up, and I cannot seem to find a proper tutorial/thread about that case, under the filtering I mean a functions that filters if a unit is enemy, if it's alive and organic.
The main problem I have here is the thing with Condition1 And Condition2 thing, can I make something with more than 2 "and"s in the same line but with using parenthesis to make it in for of Cond1 and Cond2 (Cond1 and (Cond2 and Cond3)) instead of Cond1 and Cond2 and Cond3?? Also do I write and with small or capital "A"?

Thanks in advance :thumbs_up:
 
Level 26
Joined
Mar 19, 2008
Messages
3,140
#2.
JASS:
local unit u = unitTocheck
local player p = playerToCheck
if IsUnitEnemy(unitTocheck, playerToCheck) and (GetWidgetLife(unitTocheck) > 0.405) and not IsUnitType(unitTocheck, UNIT_TYPE_STRUCTURE) and not IsUnitType(unitTocheck, UNIT_TYPE_MECHANICAL) then
    // stuff
endif
set u = null
set p = null
Native IsUnitEnemy checks is unit 'unitTocheck' in an enemy to player 'playerTocheck'. Rest you probably understand.

#1 Post whole script?
Meaby global group usage can help you.
 
Level 6
Joined
May 15, 2008
Messages
146
About Q1 here is the script, I used to try to save the unit groups to hashtable in GUI for wave type spells so I can store already damaged units, but I couldn;t get it to work there also.

Here is the test script where I've tried to see if the func work, it has nothing to do with ability:

JASS:
function TestGroupHashtable takes nothing returns nothing
    local group g = GetUnitsInRectAll(gg_rct_Region_000)
    local group g2
    local unit u
    call SaveGroupHandle(udg_Hashtable, 1, 1, g)
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        call BJDebugMsg(GetUnitName(u))
        call GroupRemoveUnit(g, u)
    endloop
    call GroupClear(g)
    call TriggerSleepAction(5.00)
    set g2 = LoadGroupHandle(udg_Hashtable, 1, 1)
    call BJDebugMsg("loaded group units:")
    loop
        set u = FirstOfGroup(g2)
        exitwhen u == null
        call BJDebugMsg(GetUnitName(u))
        call GroupRemoveUnit(g2, u)
    endloop
endfunction

//=======================

function InitTrig_Test takes nothing returns nothing
    local trigger T = CreateTrigger()
    call TriggerRegisterPlayerChatEvent(T, Player(0), "-test", true)
    call TriggerAddAction(T, function TestGroupHashtable)
    set T = null
endfunction

I didn't removed leaks no need to point me to that this is just for testing, in the Region I have 5 units and first loop show all of their names, the Hashtable is initialized, I'm using the same for some other systems and spells and they all work.
Where do I do it wrong?

Thanks for the help. :thumbs_up:

:fp: EDIT: Oh yeah Spinnaker thanks for the filtering code you rulez ^^ :thumbs_up:
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
1-In first loop you are removing every unit one by one from group, when loop ends the group is empty.

2-After first loop, next line you are clearing an empty group, which does nothing.

3-
JASS:
//You are loading an empty group now.
set g2 = LoadGroupHandle(udg_Hashtable, 1, 1)
 
Level 6
Joined
May 15, 2008
Messages
146
OK I've overnoticed that thingie with clear group function my bad.

But wtf that sucks if I saved GroupHandle into hashtable shouldn't that info remain there even if I change the group g because it's uhm "saved"? That works with unit you set a unit save it and you can change that.

I mean my point of view is like this, having a wave spell which goes and has dunno 200 AoE for example, if I move it 50, by 50 distance the units in the starting point will remain there roughly 4 times, and if I damage every time when the moving is done ('cuz of the new units), I'll deal 4 time dmg to picked ones. I want to damage a unit then add it to a group and than save that group into a hastable, so I can load it on the next damage and check if the picked unit is already damaged. I could do that with a global group, but what if I have two of the same waves going after each other or crossroading, only one wave would deal dmg??
 
Level 6
Joined
May 15, 2008
Messages
146
So no need to clear the group? I mean I clear it on the end of the wave spell along with destroying?

Or I do it at the end of function or combine it with a small wait??

EDIT: Uhm I've removed the removing of units in the loop but if I remove that, the loop goes infinite since there will be no exitwhen u == null since no units are removed.

Also I don't get it what you think under "you can still stick with hashtable method", SaveGroupHandle is Hashtable metod it saves the group into hashtable. :vw_wtf:
 
Level 26
Joined
Mar 19, 2008
Messages
3,140
You saw my script above?
Just make sure you save untouched group. If you want to add units into this group you can either:
JASS:
set g2 = LoadGroupHandle(udg_Hashtable, 1, 1)
call GroupAddUnit(g2, someunit)

// Or
call GroupAddUnit(LoadGroupHandle(udg_Hashtable, 1, 1), someunit)
set g2 = LoadGroupHandle(udg_Hashtable, 1, 1)
It's best to save empty group into hashtable and just add units with time (wave moves further):
JASS:
call SaveGroupHandle(udg_Hashtable, 1, 1, CreateGroup())
Now whenever you want to add units just set saved group to local (to omit spamming LoadGroupHandle()), and add those.
 
Last edited:
Level 6
Joined
May 15, 2008
Messages
146
So what's the way to save the content of a group if not this one?
Isn't a group a content of units?
How does that work for a single unit than, I mean if saving it to hashtable means saving it's handle..., uhm I'm too confused now :vw_wtf:

Don't getting this also if I dont clear up and destroy the group and null the variable, wouldn't it leak on each execution of Exe Function?

I'm currently doing the code, will check if it works if not I'll post it here in hope of solving the issue.

Thanks Maker :thumbs_up:


EDIT: OK here is the code, but now I can't get the wave dummy unit to move, I really don't know what's the problem, I did yesterday a code like this just without damage and it worked??
Thanks in advance for help.

JASS:
[HIDDEN="Code"]
//==========//
// WAVE     //
//==========//

function Wave_Exe takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local integer counter = LoadInteger(udg_Hashtable, id, 1)
    local real angle = LoadReal(udg_Hashtable, id, 2)
    local real damage = LoadReal(udg_Hashtable, id, 3)
    local unit Wave = LoadUnitHandle(udg_Hashtable, id, 4)
    local group Damaged = LoadGroupHandle(udg_Hashtable, id, 5)
    local location p = GetUnitLoc(Wave)
    local group g = GetUnitsInRangeOfLocAll(200.0, p)
    local unit u
    call BJDebugMsg("Runned")
    if counter <= 11 then
        call SaveInteger(udg_Hashtable, id, 1, counter+1)
        call SetUnitX(Wave, PolarProjectionX(GetUnitX(Wave), 50, angle))
        call SetUnitY(Wave, PolarProjectionY(GetUnitY(Wave), 50, angle))
        loop
            exitwhen u == null
            set u = FirstOfGroup(g)
            if IsUnitInGroup(u, Damaged) == false then
                call UnitDamageTarget(Wave, u, damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS) 
                call DestroyEffect(AddSpecialEffectTarget("Mana Wave.mdx", u, "chest"))
                call GroupAddUnit(Damaged, u)
                call SaveGroupHandle(udg_Hashtable, id, 5, Damaged)
            endif
            call GroupRemoveUnit(g, u)
        endloop
    else
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Hashtable, id)
        call KillUnit(Wave)
    endif
    call DestroyGroup(g)
    call DestroyGroup(Damaged)
    call RemoveLocation(p)
    set u = null
    set Wave = null
    set g = null
    set Damaged = null
    set p = null
    set t = null       
endfunction

function Wave_Start takes nothing returns nothing
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)
    local integer counter = 0
    local real angle = GetUnitFacing(GetTriggerUnit())
    local location p = GetUnitLoc(GetTriggerUnit())
    if GetSpellAbilityId() == 'A00L' then
        set bj_lastCreatedUnit = CreateUnitAtLoc(GetOwningPlayer(GetTriggerUnit()), 'h008', p, GetUnitFacing(GetTriggerUnit()))
        call SaveUnitHandle(udg_Hashtable, id, 4, bj_lastCreatedUnit)    
        call SaveInteger(udg_Hashtable, id, 1, counter)
        call SaveReal(udg_Hashtable, id, 2, angle)
        call SaveReal(udg_Hashtable, id, 3, 100.0)
        call SaveGroupHandle(udg_Hashtable, id, 5, CreateGroup())
        call TimerStart(t, 0.4, true, function Wave_Exe)
        set t = null
    endif
    call RemoveLocation(p)
    set p = null
endfunction

//===================================

function InitTrig_Wave_Test takes nothing returns nothing
    local trigger T = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(T, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(T, function Wave_Start)
    set T = null
endfunction[/HIDDEN]
 
Last edited:
Level 6
Joined
May 15, 2008
Messages
146
Maker can u explain me how does the code with the upper mentioned hashtable save/load works for units then, I mean unit is handle?

Ive tested this short code and it shows two time the name of the unit even when I nulled the variable.

JASS:
function Test takes nothing returns nothing
    local unit u = gg_unit_Hblm_0038
    call SaveUnitHandle(udg_Hashtable, 1, 1, u)
    call BJDebugMsg(GetUnitName(u))
    set u = null
    call TriggerSleepAction(5.00)
    set u = LoadUnitHandle(udg_Hashtable, 1, 1)
    call BJDebugMsg(GetUnitName(u))
endfunction

//==================

function InitTrig_Opaa_Z takes nothing returns nothing
    local trigger T = CreateTrigger()
    call TriggerRegisterPlayerChatEvent(T, Player(0), "-opa", true)
    call TriggerAddAction(T, function Test)
    set T=null
endfunction

Any help with the upper code, I still haven't figured it out?
 
Level 26
Joined
Mar 19, 2008
Messages
3,140
Yeah you have nulled it and set again to loadunithandle value. In this case unit 'u' has been set to unit stored into hashtable, thus it's name will be displayed.
You have to execute RemoveUnit(u) to make sure it's same won't be displayed.
Saving any value in hashtable doesn't create additional object, it's just a reference to existing one. This reference is pointing at given object, and if somehow the pointed value gets removed the savedvalue will store nothing usefull.

ClearingGroup/Removing units from it works in similar way, yet still you can display savedgroup id since group exists, but it's empty. Unless you destroy it, the group's id can be shown. Destroying group in this case can be compared to displaying removed unit's name.
 
Status
Not open for further replies.
Top