• 🏆 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!

How to add Group Damage to that code

Status
Not open for further replies.
Level 3
Joined
Nov 26, 2009
Messages
35
JASS:
function Trig_WolfGirlDash_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction

function Trig_WolfGirlDashes takes nothing returns nothing
    local timer timerOne = GetExpiredTimer()
    local unit caster = LoadUnitHandleBJ(1, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local real range = 20
    local real angle = LoadRealBJ(2, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local real distance = LoadRealBJ(3, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local location movePointSecond
    local location movePoint
     if (distance > 0.00  == true and IsUnitAliveBJ(caster) == true) then
             set movePointSecond = GetUnitLoc(caster)
             set movePoint = PolarProjectionBJ(movePointSecond, range, angle)
             call CreateNUnitsAtLoc( 1, 'h007', GetOwningPlayer(caster), movePoint, angle )
             call SetUnitPositionLoc( caster, movePoint )
             call RemoveLocation(movePointSecond)
             call RemoveLocation(movePoint)
             set  distance = distance - range
             call SaveRealBJ(distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
        else
            set movePointSecond = GetUnitLoc(caster)
            call CreateNUnitsAtLoc( 1, 'h008', GetOwningPlayer(caster), movePointSecond, angle )
            call PauseTimer(timerOne)
            call DestroyTimer(timerOne)
            set timerOne = null
        endif
    


endfunction

function Trig_WolfGirlDash_Actions takes nothing returns nothing
    local unit caster
    local location casterPoint
    local location targetPoint
    local real angle
    local real range
    local timer timerOne
    local real distance
    set caster = GetSpellAbilityUnit()
    set udg_WolfGirlCaster = GetSpellAbilityUnit()
    set targetPoint = GetSpellTargetLoc()
    set casterPoint = GetUnitLoc(caster)
    set range = 50
    set angle = AngleBetweenPoints(casterPoint, targetPoint)
    set distance = DistanceBetweenPoints(casterPoint, targetPoint)
    set timerOne = CreateTimer()
    call SaveUnitHandleBJ( caster, 1, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( angle, 2, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call TimerStart(timerOne, 0.003, true, function Trig_WolfDashes)
    call RemoveLocation(casterPoint)
    call RemoveLocation(targetPoint)
    set caster = null
endfunction


//===========================================================================
function InitTrig_WolfGirlDash takes nothing returns nothing
    set gg_trg_WolfGirlDash = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_WolfGirlDash, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_WolfGirlDash, Condition( function Trig_WolfGirlDash_Conditions ) )
    call TriggerAddAction( gg_trg_WolfGirlDash, function Trig_WolfGirlDash_Actions )
endfunction

I know about leaks and i will clear them later.
What i want is:
Pick every unit matching condition(enemy, is a live, not in a group damagedGroup) around a caster and do damage

But groups in jass is...pain, for me.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,535

JASS:
    function Enumerate takes nothing returns nothing
        local group g = CreateGroup()
        local real range = 300
        local unit caster = GetTriggerUnit()
        local unit u // Picked unit
        local real x = GetUnitX(caster)
        local real y = GetUnitY(caster)
        call GroupEnumUnitsInRange(g,x,y,Filter(func)) // You don't NEED a Filter (set it to Null if so)
        // Faster than ForGroup
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            // Do stuff with unit u (here is where you would deal damage to the Picked unit)
            call GroupRemoveUnit(g,u)
        endloop
        call DestroyGroup(g)
        set g = null
        set caster = null
    endfunction
 
Last edited:

Wrda

Spell Reviewer
Level 26
Joined
Nov 18, 2012
Messages
1,887
Note that uncle's mentioned method is only good if you're going to use this group once. If you wanted to use it more than once with this method, you'd have to re-do it, as in: enumerate and loop afterwards.
So the best method if you want to use it more than once is to use the ForGroup.
Also if you use a filter, you have to clean it later.
 
Level 3
Joined
Nov 26, 2009
Messages
35
Tried to do like this but failed :ogre_rage:
JASS:
function Trig_WolfGirlDash_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction
                

function Trig_WolfDashes takes nothing returns nothing
    local timer timerOne = GetExpiredTimer()
    local unit caster = LoadUnitHandleBJ(1, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local unit target
    local real range = 100
    local real aoe = 250
    local real angle = LoadRealBJ(2, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local real distance = LoadRealBJ(3, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local location movePointSecond
    local location movePoint
    local real casterX
    local real casterY
    local group damagedGroup = CreateGroup()
    local group damageTo = CreateGroup()
    set damagedGroup = LoadGroupHandleBJ(4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
     if (distance > 0.00  == true and IsUnitAliveBJ(caster) == true) then
             set movePointSecond = GetUnitLoc(caster)
             set movePoint = PolarProjectionBJ(movePointSecond, range, angle)
             set casterX = GetUnitX(caster)
             set casterY = GetUnitY(caster)
             call CreateNUnitsAtLoc( 1, 'h007', GetOwningPlayer(caster), movePoint, angle )
             call SetUnitPositionLoc( caster, movePoint )
             call GroupEnumUnitsInRange(damageTo, casterX,casterY, range, null)
             loop
              set target = FirstOfGroup(damageTo)
                exitwhen target == null
                if (IsUnitEnemy(target, GetOwningPlayer(caster)) == true and IsUnitAliveBJ(target) == true and IsUnitInGroup(target, damagedGroup) == false ) then
                    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
                    call GroupAddUnit(damagedGroup, target)
                    call GroupRemoveUnit(damageTo, target)
                else
                    call GroupRemoveUnit(damageTo, target)
                endif   
             endloop
             call SaveGroupHandleBJ(damagedGroup, 4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
             call RemoveLocation(movePointSecond)
             call RemoveLocation(movePoint)
             set  distance = distance - range
             call SaveRealBJ(distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
        else
            set movePointSecond = GetUnitLoc(caster)
            call CreateNUnitsAtLoc( 1, 'h008', GetOwningPlayer(caster), movePointSecond, angle )
            call PauseUnitBJ( false, caster )
            call PauseTimer(timerOne)
            call DestroyTimer(timerOne)
            set timerOne = null
        endif
        call DestroyGroup(damageTo)
        call DestroyGroup(damagedGroup)
        set caster = null
        set target = null
endfunction

function Trig_WolfGirlDash_Actions takes nothing returns nothing
    local unit caster
    local location casterPoint
    local location targetPoint
    local real angle
    local timer timerOne
    local real distance
    set caster = GetSpellAbilityUnit()
    set targetPoint = GetSpellTargetLoc()
    set casterPoint = GetUnitLoc(caster)
    set angle = AngleBetweenPoints(casterPoint, targetPoint)
    set distance = DistanceBetweenPoints(casterPoint, targetPoint)
    set timerOne = CreateTimer()
    call SaveUnitHandleBJ( caster, 1, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( angle, 2, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call PauseUnitBJ( true, caster )
    call SetUnitAnimationByIndex ( caster , 18 )
    call TimerStart(timerOne, 0.005, true, function Trig_WolfDashes)
    call RemoveLocation(casterPoint)
    call RemoveLocation(targetPoint)
    set caster = null
endfunction


//===========================================================================
function InitTrig_WolfGirlDash takes nothing returns nothing
    set gg_trg_WolfGirlDash = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_WolfGirlDash, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_WolfGirlDash, Condition( function Trig_WolfGirlDash_Conditions ) )
    call TriggerAddAction( gg_trg_WolfGirlDash, function Trig_WolfGirlDash_Actions )
endfunction
 
Level 24
Joined
Jun 26, 2020
Messages
1,852
vJASS:
if (IsUnitEnemy(target, GetOwningPlayer(caster)) == true and IsUnitAliveBJ(target) == true and IsUnitInGroup(target, damagedGroup) == false ) then
    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
    call GroupAddUnit(damagedGroup, target)
    call GroupRemoveUnit(damageTo, target)
else
    call GroupRemoveUnit(damageTo, target)
endif
Is wrong, look the @Uncle example again, the unit must be removed yes or yes not only if that condition is false, it must be like this:
vJASS:
if (IsUnitEnemy(target, GetOwningPlayer(caster)) == true and IsUnitAliveBJ(target) == true and IsUnitInGroup(target, damagedGroup) == false ) then
    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
    call GroupAddUnit(damagedGroup, target)
    call GroupRemoveUnit(damageTo, target)
endif
call GroupRemoveUnit(damageTo, target)
You need learn more how to work in JASS to save more text than you are using, and you are doing some other errors.
First: You are destroying the group "damagedGroup"
vJASS:
call DestroyGroup(damagedGroup)
a group that you are saving to use it in the next instance:
vJASS:
call SaveGroupHandleBJ(damagedGroup, 4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
So you can't use it again, you must destroy it when you won't use it more, and you have to create it in your actions function (the first), like this:
vJASS:
call SaveGroupHandleBJ(CreateGroup(), 4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
Second:
vJASS:
local group damagedGroup = CreateGroup()
set damagedGroup = LoadGroupHandleBJ(4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
You don't need to create a group if after you are loading it (in fact you are doing an object leak, because you overwrite the variable and lose the reference to the created group), change it to this:
vJASS:
local group damagedGroup = LoadGroupHandleBJ(4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)

So your code should look like this (but it would look better):
vJASS:
function Trig_WolfGirlDash_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction
           

function Trig_WolfDashes takes nothing returns nothing
    local timer timerOne = GetExpiredTimer()
    local unit caster = LoadUnitHandleBJ(1, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local unit target
    local real range = 100
    local real aoe = 250
    local real angle = LoadRealBJ(2, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local real distance = LoadRealBJ(3, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local location movePointSecond
    local location movePoint
    local real casterX
    local real casterY
    local group damagedGroup = CreateGroup()
    local group damageTo = CreateGroup()
    set damagedGroup = LoadGroupHandleBJ(4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
     if (distance > 0.00  == true and IsUnitAliveBJ(caster) == true) then
             set movePointSecond = GetUnitLoc(caster)
             set movePoint = PolarProjectionBJ(movePointSecond, range, angle)
             set casterX = GetUnitX(caster)
             set casterY = GetUnitY(caster)
             call CreateNUnitsAtLoc( 1, 'h007', GetOwningPlayer(caster), movePoint, angle )
             call SetUnitPositionLoc( caster, movePoint )
             call GroupEnumUnitsInRange(damageTo, casterX,casterY, range, null)
             loop
              set target = FirstOfGroup(damageTo)
                exitwhen target == null
                if (IsUnitEnemy(target, GetOwningPlayer(caster)) == true and IsUnitAliveBJ(target) == true and IsUnitInGroup(target, damagedGroup) == false ) then
                    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
                    call GroupAddUnit(damagedGroup, target)
                    call GroupRemoveUnit(damageTo, target)
                endif
                call GroupRemoveUnit(damageTo, target)
             endloop
             call SaveGroupHandleBJ(damagedGroup, 4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
             call RemoveLocation(movePoint)
             set  distance = distance - range
             call SaveRealBJ(distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
        else
            set movePointSecond = GetUnitLoc(caster)
            call CreateNUnitsAtLoc( 1, 'h008', GetOwningPlayer(caster), movePointSecond, angle )
            call PauseUnitBJ( false, caster )
            call PauseTimer(timerOne)
            call DestroyTimer(timerOne)
            call DestroyGroup(damagedGroup)
            call FlushChildHashtable(udg_HeroesHashTable , GetHandleIdBJ(timerOne)) //You have to clear the used parts of your hashtable
        endif
        call DestroyGroup(damageTo)
        call RemoveLocation(movePointSecond) //You are using it in the if and else part
        set caster = null
        set target = null
        set movePointSecond = null
        set movePoint = null
        set damagedGroup = null
        set damageTo = null
        set timerOne = null
        //You miss this reference leaks
endfunction

function Trig_WolfGirlDash_Actions takes nothing returns nothing
    local unit caster
    local location casterPoint
    local location targetPoint
    local real angle
    local timer timerOne
    local real distance
    set caster = GetSpellAbilityUnit()
    set targetPoint = GetSpellTargetLoc()
    set casterPoint = GetUnitLoc(caster)
    set angle = AngleBetweenPoints(casterPoint, targetPoint)
    set distance = DistanceBetweenPoints(casterPoint, targetPoint)
    set timerOne = CreateTimer()
    call SaveUnitHandleBJ( caster, 1, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( angle, 2, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveGroupHandleBJ( CreateGroup(), 4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    call PauseUnitBJ( true, caster )
    call SetUnitAnimationByIndex ( caster , 18 )
    call TimerStart(timerOne, 0.005, true, function Trig_WolfDashes)
    call RemoveLocation(casterPoint)
    call RemoveLocation(targetPoint)
    set caster = null
    set casterPoint = null
    set targetPoint = null
    set timerOne = null
    //Locations, groups and timers are also agents, so you have to null them too
endfunction


//===========================================================================
function InitTrig_WolfGirlDash takes nothing returns nothing
    set gg_trg_WolfGirlDash = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_WolfGirlDash, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_WolfGirlDash, Condition( function Trig_WolfGirlDash_Conditions ) )
    call TriggerAddAction( gg_trg_WolfGirlDash, function Trig_WolfGirlDash_Actions )
endfunction
Edit: Oh
I know about leaks and i will clear them later.
 
Last edited:
Level 3
Joined
Nov 26, 2009
Messages
35
vJASS:
if (IsUnitEnemy(target, GetOwningPlayer(caster)) == true and IsUnitAliveBJ(target) == true and IsUnitInGroup(target, damagedGroup) == false ) then
    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
    call GroupAddUnit(damagedGroup, target)
    call GroupRemoveUnit(damageTo, target)
else
    call GroupRemoveUnit(damageTo, target)
endif
Is wrong, look the @Uncle example again, the unit must be removed yes or yes not only if that condition is false, it must be like this:
vJASS:
if (IsUnitEnemy(target, GetOwningPlayer(caster)) == true and IsUnitAliveBJ(target) == true and IsUnitInGroup(target, damagedGroup) == false ) then
    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
    call GroupAddUnit(damagedGroup, target)
    call GroupRemoveUnit(damageTo, target)
endif
call GroupRemoveUnit(damageTo, target)
You need learn more how to work in JASS to save more text than you are using, and you are doing some other errors.
First: You are destroying the group "damagedGroup"
vJASS:
call DestroyGroup(damagedGroup)
a group that you are saving to use it in the next instance:
vJASS:
call SaveGroupHandleBJ(damagedGroup, 4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
So you can't use it again, you must destroy it when you won't use it more, and you have to create it in your actions function (the first), like this:
vJASS:
call SaveGroupHandleBJ(CreateGroup(), 4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
Second:
vJASS:
local group damagedGroup = CreateGroup()
set damagedGroup = LoadGroupHandleBJ(4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
You don't need to create a group if after you are loading it (in fact you are doing an object leak, because you overwrite the variable and lose the reference to the created group), change it to this:
vJASS:
local group damagedGroup = LoadGroupHandleBJ(4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)

So your code should look like this (but it would look better):
vJASS:
function Trig_WolfGirlDash_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction
        

function Trig_WolfDashes takes nothing returns nothing
    local timer timerOne = GetExpiredTimer()
    local unit caster = LoadUnitHandleBJ(1, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local unit target
    local real range = 100
    local real aoe = 250
    local real angle = LoadRealBJ(2, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local real distance = LoadRealBJ(3, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local location movePointSecond
    local location movePoint
    local real casterX
    local real casterY
    local group damagedGroup = CreateGroup()
    local group damageTo = CreateGroup()
    set damagedGroup = LoadGroupHandleBJ(4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
     if (distance > 0.00  == true and IsUnitAliveBJ(caster) == true) then
             set movePointSecond = GetUnitLoc(caster)
             set movePoint = PolarProjectionBJ(movePointSecond, range, angle)
             set casterX = GetUnitX(caster)
             set casterY = GetUnitY(caster)
             call CreateNUnitsAtLoc( 1, 'h007', GetOwningPlayer(caster), movePoint, angle )
             call SetUnitPositionLoc( caster, movePoint )
             call GroupEnumUnitsInRange(damageTo, casterX,casterY, range, null)
             loop
              set target = FirstOfGroup(damageTo)
                exitwhen target == null
                if (IsUnitEnemy(target, GetOwningPlayer(caster)) == true and IsUnitAliveBJ(target) == true and IsUnitInGroup(target, damagedGroup) == false ) then
                    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
                    call GroupAddUnit(damagedGroup, target)
                    call GroupRemoveUnit(damageTo, target)
                endif
                call GroupRemoveUnit(damageTo, target)
             endloop
             call SaveGroupHandleBJ(damagedGroup, 4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
             call RemoveLocation(movePoint)
             set  distance = distance - range
             call SaveRealBJ(distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
        else
            set movePointSecond = GetUnitLoc(caster)
            call CreateNUnitsAtLoc( 1, 'h008', GetOwningPlayer(caster), movePointSecond, angle )
            call PauseUnitBJ( false, caster )
            call PauseTimer(timerOne)
            call DestroyTimer(timerOne)
            call DestroyGroup(damagedGroup)
            call FlushChildHashtable(udg_HeroesHashTable , GetHandleIdBJ(timerOne)) //You have to clear the used parts of your hashtable
        endif
        call DestroyGroup(damageTo)
        call RemoveLocation(movePointSecond) //You are using it in the if and else part
        set caster = null
        set target = null
        set movePointSecond = null
        set movePoint = null
        set damagedGroup = null
        set damageTo = null
        set timerOne = null
        //You miss this reference leaks
endfunction

function Trig_WolfGirlDash_Actions takes nothing returns nothing
    local unit caster
    local location casterPoint
    local location targetPoint
    local real angle
    local timer timerOne
    local real distance
    set caster = GetSpellAbilityUnit()
    set targetPoint = GetSpellTargetLoc()
    set casterPoint = GetUnitLoc(caster)
    set angle = AngleBetweenPoints(casterPoint, targetPoint)
    set distance = DistanceBetweenPoints(casterPoint, targetPoint)
    set timerOne = CreateTimer()
    call SaveUnitHandleBJ( caster, 1, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( angle, 2, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveGroupHandleBJ( CreateGroup(), 4, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    call PauseUnitBJ( true, caster )
    call SetUnitAnimationByIndex ( caster , 18 )
    call TimerStart(timerOne, 0.005, true, function Trig_WolfDashes)
    call RemoveLocation(casterPoint)
    call RemoveLocation(targetPoint)
    set caster = null
    set casterPoint = null
    set targetPoint = null
    set timerOne = null
    //Locations, groups and timers are also agents, so you have to null them too
endfunction


//===========================================================================
function InitTrig_WolfGirlDash takes nothing returns nothing
    set gg_trg_WolfGirlDash = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_WolfGirlDash, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_WolfGirlDash, Condition( function Trig_WolfGirlDash_Conditions ) )
    call TriggerAddAction( gg_trg_WolfGirlDash, function Trig_WolfGirlDash_Actions )
endfunction
Edit: Oh

Ah if forgot about theme. I already created it , thanks guys.

JASS:
function Trig_WolfGirlDash_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction
function WolfGirlQ_Clear takes nothing returns nothing
    local timer groupClearT = GetExpiredTimer()
    local unit caster = LoadUnitHandleBJ(1, GetHandleIdBJ(groupClearT), udg_HeroesHashTable)
    local unit dummy
    local integer playerId = GetConvertedPlayerId(GetOwningPlayer(caster))
        loop
            set dummy = FirstOfGroup(udg_WolfGirlQDummyGroup[playerId])
            call RemoveUnit(dummy)
            call GroupRemoveUnit(udg_WolfGirlQDummyGroup[playerId], dummy)
            exitwhen dummy == null
        endloop
    call ResetUnitAnimation( caster ) 
    set caster = null
    call GroupClear(udg_WolfGirlQDummyGroup[playerId])
    call PauseTimer(groupClearT)
    call DestroyTimer(groupClearT)
    set groupClearT = null
endfunction
            

function Trig_WolfDashes takes nothing returns nothing
    local timer timerOne = GetExpiredTimer()
    local unit caster = LoadUnitHandleBJ(1, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local unit target
    local real range = 100
    local real aoe = 250
    local real angle = LoadRealBJ(2, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local real distance = LoadRealBJ(3, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local location movePointSecond
    local real casterY = GetUnitY(caster)
    local real casterX = GetUnitX(caster)
    local group damageTo = CreateGroup()
    local location movePoint
    local integer playerId = GetConvertedPlayerId(GetOwningPlayer(caster))
    local timer groupClearT
     if (distance > 0.00  == true and IsUnitAliveBJ(caster) == true) then
             set movePointSecond = GetUnitLoc(caster)
             set movePoint = PolarProjectionBJ(movePointSecond, range, angle)
             call CreateNUnitsAtLoc( 1, 'h007', GetOwningPlayer(caster), movePoint, angle )
             call GroupAddUnit(udg_WolfGirlQDummyGroup[playerId], GetLastCreatedUnit())
             call SetUnitPositionLoc( caster, movePoint )

             call RemoveLocation(movePointSecond)
             call RemoveLocation(movePoint)
             set  distance = distance - range
             call SaveRealBJ(distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
             call GroupEnumUnitsInRange(damageTo ,casterX, casterY, aoe,  null)
            loop
            set target = FirstOfGroup(damageTo)
            exitwhen target == null
                if (IsUnitAlly(target, GetOwningPlayer(caster)) == false and IsUnitInGroup(target, udg_WolfGirlQGroup[playerId]) == false) then
                    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
                    call GroupAddUnit(udg_WolfGirlQGroup[playerId],target)
                    call GroupRemoveUnit(damageTo ,target)
                else
                    call GroupRemoveUnit(damageTo ,target)
                endif
            endloop
        else
            set movePointSecond = GetUnitLoc(caster)
            call CreateNUnitsAtLoc( 1, 'h008', GetOwningPlayer(caster), movePointSecond, angle )
            call GroupAddUnit(udg_WolfGirlQDummyGroup[playerId], GetLastCreatedUnit())
            call GroupEnumUnitsInRange(damageTo ,casterX, casterY, aoe,  null)
            loop
            set target = FirstOfGroup(damageTo)
            exitwhen target == null
                if (IsUnitAlly(target, GetOwningPlayer(caster)) == false) then
                    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
                    call GroupRemoveUnit(damageTo ,target)
                else
                    call GroupRemoveUnit(damageTo ,target)
                endif
            endloop
            call PauseUnitBJ( false, caster )
            call UnitRemoveAbility(caster, 'A006' )
            call PauseTimer(timerOne)
            call DestroyTimer(timerOne)
            set timerOne = null
            set groupClearT = CreateTimer()
            call SaveUnitHandleBJ( caster, 1, GetHandleIdBJ(groupClearT), udg_HeroesHashTable )
            call TimerStart(groupClearT, 0.3, false, function WolfGirlQ_Clear  )
            call GroupClear(udg_WolfGirlQGroup[playerId])
        endif
        set caster = null
        set target = null
        call DestroyGroup(damageTo)
        set groupClearT = null
endfunction

function Trig_WolfGirlDash_Actions takes nothing returns nothing
    local unit caster = GetSpellAbilityUnit()
    local location casterPoint = GetUnitLoc(caster)
    local location targetPoint = GetSpellTargetLoc()
    local real angle =  AngleBetweenPoints(casterPoint, targetPoint)
    local timer timerOne = CreateTimer()
    local real distance = DistanceBetweenPoints(casterPoint, targetPoint)
    local integer playerId = GetConvertedPlayerId(GetOwningPlayer(caster))
    call UnitAddAbility(caster, 'A006')
    call GroupClear(udg_WolfGirlQGroup[playerId])
    call SaveUnitHandleBJ( caster, 1, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( angle, 2, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call PauseUnitBJ( true, caster )
    call SetUnitAnimationByIndex ( caster , 18 )
    call TimerStart(timerOne, 0.02, true, function Trig_WolfDashes)
    call RemoveLocation(casterPoint)
    call RemoveLocation(targetPoint)
    set caster = null
endfunction


//===========================================================================
function InitTrig_WolfGirlDash takes nothing returns nothing
    set gg_trg_WolfGirlDash = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_WolfGirlDash, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_WolfGirlDash, Condition( function Trig_WolfGirlDash_Conditions ) )
    call TriggerAddAction( gg_trg_WolfGirlDash, function Trig_WolfGirlDash_Actions )
endfunction

global group variable(massive) solved problem :)
 
Level 24
Joined
Jun 26, 2020
Messages
1,852
Well, just in case I will give you a tips to smooth your code

The comparisions are actually booleans, so instead of comparing booleans you can use them directly
The part of:
vJASS:
function Trig_WolfGirlDash_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction
Can be replaced with
vJASS:
function Trig_WolfGirlDash_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A005'
endfunction
You can replace all of your
vJASS:
if Condition == true then
For
vJASS:
if Condition then
And
vJASS:
if Condition == false then
For
vJASS:
if not Condition then

Try to avoid some unnecessary BJ functions because some of them are just extra unnecessary steps, example instead of
vJASS:
call SaveUnitHandleBJ( caster, 1, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
set unit = LoadUnitHandleBJ( 1, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
Use
vJASS:
call SaveUnitHandle( udg_HeroesHashTable, GetHandleId(timerOne), 1, caster )
set unit = LoadUnitHandle( udg_HeroesHashTable, GetHandleId(timerOne), 1)
Also to save memory when you end use
vJASS:
call FlushChildHashtable( udg_HeroesHashTable, GetHandleId(timerOne) )

If you end of use the timer, you can reuse it again, is not necessary create another, I mean, instead of
vJASS:
call PauseTimer(timerOne)
call DestroyTimer(timerOne)
set timerOne = null
set groupClearT = CreateTimer()
call TimerStart(groupClearT, 0.3, false, function WolfGirlQ_Clear  )
Just do
vJASS:
call TimerStart(timerOne, 0.3, false, function WolfGirlQ_Clear  )

And this is wrong
vJASS:
loop
    set dummy = FirstOfGroup(udg_WolfGirlQDummyGroup[playerId])
    call RemoveUnit(dummy)
    call GroupRemoveUnit(udg_WolfGirlQDummyGroup[playerId], dummy)
    exitwhen dummy == null
endloop
It should be like this
vJASS:
loop
    set dummy = FirstOfGroup(udg_WolfGirlQDummyGroup[playerId])
    exitwhen dummy == null
    call RemoveUnit(dummy)
    call GroupRemoveUnit(udg_WolfGirlQDummyGroup[playerId], dummy)
endloop
Because in the last instance the functions "RemoveUnit" and "GroupRemoveUnit" are working with a null value and that can cause errors and bugs.

To end, your local variables must be nulled always in every run, so you have to put that set timerOne = null outside the if/then/else block, and also you have to null locations too they also cause reference leak, and you don't need null the variable "target" because if you only use it for your group loops the variable is already null because the only way the process ends is if target is equal to null.
 
Last edited:
Level 3
Joined
Nov 26, 2009
Messages
35
Well, just in case I will give you a tips to smooth your code

The comparisions are actually booleans, so instead of comparing booleans you can use them directly
The part of:
vJASS:
function Trig_WolfGirlDash_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction
Can be replaced with
vJASS:
function Trig_WolfGirlDash_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A005'
endfunction
You can replace all of your
vJASS:
if Condition == true then
For
vJASS:
if Condition then
And
vJASS:
if Condition == false then
For
vJASS:
if not Condition then

Try to avoid some unnecessary BJ functions because some of them are just extra unnecessary steps, example instead of
vJASS:
call SaveUnitHandleBJ( caster, 1, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
set unit = LoadUnitHandleBJ( 1, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
Use
vJASS:
call SaveUnitHandle( udg_HeroesHashTable, GetHandleId(timerOne), 1, caster )
set unit = LoadUnitHandle( udg_HeroesHashTable, GetHandleId(timerOne), 1)
Also to save memory when you end use
vJASS:
call FlushChildHashtable( udg_HeroesHashTable, GetHandleId(timerOne) )

If you end of use the timer, you can reuse it again, is not necessary create another, I mean, instead of
vJASS:
call PauseTimer(timerOne)
call DestroyTimer(timerOne)
set timerOne = null
set groupClearT = CreateTimer()
call TimerStart(groupClearT, 0.3, false, function WolfGirlQ_Clear  )
Just do
vJASS:
call TimerStart(timerOne, 0.3, false, function WolfGirlQ_Clear  )

And this is wrong
vJASS:
loop
    set dummy = FirstOfGroup(udg_WolfGirlQDummyGroup[playerId])
    call RemoveUnit(dummy)
    call GroupRemoveUnit(udg_WolfGirlQDummyGroup[playerId], dummy)
    exitwhen dummy == null
endloop
It should be like this
vJASS:
loop
    set dummy = FirstOfGroup(udg_WolfGirlQDummyGroup[playerId])
    exitwhen dummy == null
    call RemoveUnit(dummy)
    call GroupRemoveUnit(udg_WolfGirlQDummyGroup[playerId], dummy)
endloop
Because in the last instance the functions "RemoveUnit" and "GroupRemoveUnit" are working with a null value and that can cause errors and bugs.

To end, your local variables must be nulled always in every run, so you have to put that set timerOne = null outside the if/then/else block, and also you have to null locations too they also cause reference leak, and you don't need null the variable "target" because if you only use it for your group loops the variable is already null because the only way the process ends is if target is equal to null.

And again thanks. Just today was read that hashtables also need to be cleared :)
vJASS:
function Trig_WolfGirlDash_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A005'
endfunction
function WolfGirlQ_Clear takes nothing returns nothing
    local timer timerOne = GetExpiredTimer()
    local unit caster = LoadUnitHandleBJ(1, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local unit dummy
    local integer playerId = GetConvertedPlayerId(GetOwningPlayer(caster))
        loop
            set dummy = FirstOfGroup(udg_WolfGirlQDummyGroup[playerId])
            exitwhen dummy == null
            call RemoveUnit(dummy)
            call GroupRemoveUnit(udg_WolfGirlQDummyGroup[playerId], dummy)
        endloop
    call ResetUnitAnimation( caster )
    call FlushChildHashtableBJ(GetHandleIdBJ(timerOne), udg_HeroesHashTable)      
    set caster = null
    call GroupClear(udg_WolfGirlQDummyGroup[playerId])
    call PauseTimer(timerOne)
    call DestroyTimer(timerOne)
    set timerOne = null
endfunction
             

function Trig_WolfDashes takes nothing returns nothing
    local timer timerOne = GetExpiredTimer()
    local unit caster = LoadUnitHandle( udg_HeroesHashTable, GetHandleId(timerOne), 1)
    local unit target
    local real range = 100
    local real aoe = 250
    local real angle = LoadRealBJ(2, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local real distance = LoadRealBJ(3, GetHandleIdBJ(timerOne), udg_HeroesHashTable)
    local location movePointSecond
    local real casterY = GetUnitY(caster)
    local real casterX = GetUnitX(caster)
    local group damageTo = CreateGroup()
    local location movePoint
    local integer playerId = GetConvertedPlayerId(GetOwningPlayer(caster))
     if (distance > 0.00 and IsUnitAliveBJ(caster)) then
             set movePointSecond = GetUnitLoc(caster)
             set movePoint = PolarProjectionBJ(movePointSecond, range, angle)
             call CreateNUnitsAtLoc( 1, 'h007', GetOwningPlayer(caster), movePoint, angle )
             call GroupAddUnit(udg_WolfGirlQDummyGroup[playerId], GetLastCreatedUnit())
             call SetUnitPositionLoc( caster, movePoint )
             call RemoveLocation(movePointSecond)
             call RemoveLocation(movePoint)
             set  distance = distance - range
             call SaveRealBJ(distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
             call GroupEnumUnitsInRange(damageTo ,casterX, casterY, aoe,  null)
            loop
            set target = FirstOfGroup(damageTo)
            exitwhen target == null
                if ( not IsUnitAlly(target, GetOwningPlayer(caster)) and  not IsUnitInGroup(target, udg_WolfGirlQGroup[playerId])) then
                    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
                    call GroupAddUnit(udg_WolfGirlQGroup[playerId],target)
                    call GroupRemoveUnit(damageTo ,target)
                else
                    call GroupRemoveUnit(damageTo ,target)
                endif
            endloop
        else
            set movePointSecond = GetUnitLoc(caster)
            call CreateNUnitsAtLoc( 1, 'h008', GetOwningPlayer(caster), movePointSecond, angle )
            call GroupAddUnit(udg_WolfGirlQDummyGroup[playerId], GetLastCreatedUnit())
            call GroupEnumUnitsInRange(damageTo ,casterX, casterY, aoe,  null)
            loop
            set target = FirstOfGroup(damageTo)
            exitwhen target == null
                if (IsUnitAlly(target, GetOwningPlayer(caster)) == false) then
                    call UnitDamageTargetBJ( caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
                    call GroupRemoveUnit(damageTo ,target)
                else
                    call GroupRemoveUnit(damageTo ,target)
                endif
            endloop
            call PauseUnitBJ( false, caster )
            call UnitRemoveAbility(caster, 'A006' )
            call TimerStart(timerOne, 0.3, false, function WolfGirlQ_Clear  )
            call GroupClear(udg_WolfGirlQGroup[playerId])
        endif
        set caster = null
        call DestroyGroup(damageTo)
endfunction

function Trig_WolfGirlDash_Actions takes nothing returns nothing
    local unit caster = GetSpellAbilityUnit()
    local location casterPoint = GetUnitLoc(caster)
    local location targetPoint = GetSpellTargetLoc()
    local real angle =  AngleBetweenPoints(casterPoint, targetPoint)
    local timer timerOne = CreateTimer()
    local real distance = DistanceBetweenPoints(casterPoint, targetPoint)
    local integer playerId = GetConvertedPlayerId(GetOwningPlayer(caster))
    call UnitAddAbility(caster, 'A006')
    call GroupClear(udg_WolfGirlQGroup[playerId])
    call SaveUnitHandle( udg_HeroesHashTable, GetHandleId(timerOne), 1, caster )
    call SaveRealBJ( angle, 2, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call SaveRealBJ( distance, 3, GetHandleIdBJ(timerOne), udg_HeroesHashTable )
    call PauseUnitBJ( true, caster )
    call SetUnitAnimationByIndex ( caster , 18 )
    call TimerStart(timerOne, 0.02, true, function Trig_WolfDashes)
    call RemoveLocation(casterPoint)
    call RemoveLocation(targetPoint)
    set caster = null
endfunction


//===========================================================================
function InitTrig_WolfGirlDash takes nothing returns nothing
    set gg_trg_WolfGirlDash = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_WolfGirlDash, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_WolfGirlDash, Condition( function Trig_WolfGirlDash_Conditions ) )
    call TriggerAddAction( gg_trg_WolfGirlDash, function Trig_WolfGirlDash_Actions )
endfunction

Also any tips on how to remove there only collision with units?
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,535
The Ghost ability and Wind Walk give that "phasing" effect to units.

Alternatively, you can use the SetUnitX/Y functions to move a unit while ignoring collision. That will will ignore all collision though so you'd want to couple it with a pathing system that checks to see if each point is pathable before moving the unit.

You could optimize this code a lot by taking advantage of SetUnitX/Y in addition to removing all locations and replacing all BJ functions. There's some other functions in that could be improved like CreateNUnitsAtLoc -> CreateUnit.
 
Status
Not open for further replies.
Top