Spell Epicenter

Ghan

Administrator - Servers are fun
Staff member
Reaction score
888
> The filter function is just using the global variable directly.

I know.

> No, because remember locals are only "local" to the function that they're in.

That's why.

See the brilliance of it, though.
We have a local unit in the main function.
It gets set to the global in the main function one time when it's first cast.
Then, the GLOBAL gets set to the LOCAL just before it calls the other function, so it's the correct unit.
No wait in between, so it's MUI.
For the next loop?
Just set the global to the local and do it again.

I think that works, no?
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
888
> It might. Have you tried?

I had one small coding error.
Unrelated. Fixed.
It works.
Here's the new code. Just two lines needed to be swapped:

JASS:
//These three constant functions control the range of the damage and deformation. Just change the values in these functions to alter the trigger.

constant function LargeDamageRange takes nothing returns real
    return 600.00
endfunction

constant function MediumDamageRange takes nothing returns real
    return 400.00
endfunction

constant function SmallDamageRange takes nothing returns real
    return 200.00
endfunction

constant function TimeBetweenRipples takes nothing returns real
    return 0.3
endfunction

constant function EpicenterAbilityCode takes nothing returns integer
    return 'A002'
endfunction

constant function DummyUnitCode takes nothing returns integer
    return 'h000'
endfunction

constant function DummyAbilityCode takes nothing returns integer
    return 'A001'
endfunction

function NumberOfPulses takes unit caster returns integer
    return ( 4 + ( 2 * GetUnitAbilityLevel(caster, EpicenterAbilityCode()) ) )
endfunction

function Matching takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) > 0.405 and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(udg_Epicenter_Caster)) == true
endfunction

function Picked takes nothing returns nothing
    local location unitloc = GetUnitLoc(GetEnumUnit())
    local location Epicenter_Caster_Loc = GetUnitLoc(udg_Epicenter_Caster)
    if ( DistanceBetweenPoints(Epicenter_Caster_Loc, unitloc) <= SmallDamageRange() ) then
        call UnitDamageTarget( udg_Epicenter_Caster, GetEnumUnit(), ( I2R(udg_Epicenter_Damage) + 20.00 ), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
    else
        if ( DistanceBetweenPoints(Epicenter_Caster_Loc, unitloc) <= MediumDamageRange() ) then
            call UnitDamageTarget( udg_Epicenter_Caster, GetEnumUnit(), ( I2R(udg_Epicenter_Damage) - 20.00 ), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
        else
            if ( DistanceBetweenPoints(Epicenter_Caster_Loc, unitloc) <= LargeDamageRange() ) then
                call UnitDamageTarget( udg_Epicenter_Caster, GetEnumUnit(), ( I2R(udg_Epicenter_Damage) - 30.00 ),true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
            else
            endif
        endif
    endif
    call RemoveLocation (unitloc)
    call RemoveLocation (Epicenter_Caster_Loc)
    set unitloc = null
    set Epicenter_Caster_Loc = null 
endfunction

function Trig_Epicenter_Action_Actions takes nothing returns nothing
    local unit caster = udg_Epicenter_Caster
    local integer Epicenter_Pulses = NumberOfPulses(caster)
    local location Epicenter_Caster_Loc
    local group Epicenter_Group
    loop
      exitwhen Epicenter_Pulses == 0
      set udg_Epicenter_Caster = caster
      set Epicenter_Caster_Loc = GetUnitLoc(caster)
      set Epicenter_Group = GetUnitsInRangeOfLocMatching(LargeDamageRange(), Epicenter_Caster_Loc, Condition(function Matching)) 
      call TerrainDeformationCraterBJ( 0.5, false, Epicenter_Caster_Loc, LargeDamageRange()-40.00, 28.00 )
      call CreateNUnitsAtLoc( 1, DummyUnitCode(), GetOwningPlayer(caster), Epicenter_Caster_Loc, bj_UNIT_FACING )
      call UnitAddAbility(GetLastCreatedUnit(), DummyAbilityCode() )
      call IssueImmediateOrder( GetLastCreatedUnit(), "thunderclap" )
      call UnitApplyTimedLife(GetLastCreatedUnit(), 'BTLF', 0.30 )
      call ForGroup( Epicenter_Group, function Picked )
      set Epicenter_Pulses = Epicenter_Pulses-1
      call RemoveLocation (Epicenter_Caster_Loc)
      call DestroyGroup (Epicenter_Group)
      set Epicenter_Caster_Loc = null
      set Epicenter_Group = null
      call PolledWait(TimeBetweenRipples())
    endloop
    set caster = null
endfunction

//===========================================================================
function InitTrig_Epicenter_Action takes nothing returns nothing
    set gg_trg_Epicenter_Action = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Epicenter_Action, function Trig_Epicenter_Action_Actions )
endfunction
 

Tinki3

Special Member
Reaction score
418

Naminator

Coming Back To Life
Reaction score
76
Forgot to mention earlier:
JASS:
GetUnitsInRangeOfLocMatching(LargeDamageRange(), Epicenter_Caster_Loc, Condition(function Matching))

That leaks a boolexpr from the 'Condition(function Matching)'.

All you need to do is...
JASS:
local boolexpr b = Condition(function Matching)
set group = GetUnitsInRangeOfLocMatching(..., ..., ..., b)
//...
call DestroyBoolExpr(b)
set b = null

Fix this part that Tinki3 gave you, and the post the code here Ghan. Thanks both of you. For helping the JASS version. And tell me Tinki3 if someone wrong with the GUI Version.
 

Tinki3

Special Member
Reaction score
418
The GUI version has a few leaks, now that I've looked at it.

- There is no need to set 'Epicenter_Caster_Loc' in the endcast trigger if
it's been set instantly afterwards in the periodic trigger. It is also leaking this
way.
- The custom script for removing the 'Epicenter_Picked_Loc' needs to be outside
the first If-Then-Else statement, and as the last line (also inside the Loop - actions).
 

Naminator

Coming Back To Life
Reaction score
76
The GUI version has a few leaks, now that I've looked at it.

- There is no need to set 'Epicenter_Caster_Loc' in the endcast trigger if
it's been set instantly afterwards in the periodic trigger. It is also leaking this
way.
- The custom script for removing the 'Epicenter_Picked_Loc' needs to be outside
the first If-Then-Else statement, and as the last line (also inside the Loop - actions).

Like this:

Code:
Epicenter Action
    Events
        Time - Every 0.30 seconds of game time
    Conditions
    Actions
        Set Epicenter_Pulses = (Epicenter_Pulses - 1)
        Set Epicenter_Caster_Loc = (Position of Epicenter_Caster)
        Set Epicenter_Group = (Units within 600.00 of Epicenter_Caster_Loc matching ((((Matching unit) belongs to an enemy of (Owner of Epicenter_Caster)) Equal to True) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) is A structure) Equal to False))))
        Environment - Create a 0.50 second Temporary crater deformation at Epicenter_Caster_Loc with radius 560.00 and depth 28.00
        Unit - Create 1 Dummy Unit for (Owner of Epicenter_Caster) at Epicenter_Caster_Loc facing Default building facing degrees
        Unit - Add Epicenter Slow  to (Last created unit)
        Unit - Order (Last created unit) to Human Mountain King - Thunder Clap
        Unit - Add a 0.30 second Generic expiration timer to (Last created unit)
        Unit Group - Pick every unit in Epicenter_Group and do (Actions)
            Loop - Actions
                Set Epicenter_Picked_Loc = (Position of (Picked unit))
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Distance between Epicenter_Caster_Loc and Epicenter_Picked_Loc) Less than or equal to 200.00
                    Then - Actions
                        Unit - Cause Epicenter_Caster to damage (Picked unit), dealing ((Real(Epicenter_Damage)) + 20.00) damage of attack type Spells and damage type Universal
                    Else - Actions
                        Custom script:   call RemoveLocation (udg_Epicenter_Picked_Loc)
                        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            If - Conditions
                                (Distance between Epicenter_Caster_Loc and Epicenter_Picked_Loc) Less than or equal to 400.00
                            Then - Actions
                                Unit - Cause Epicenter_Caster to damage (Picked unit), dealing ((Real(Epicenter_Damage)) - 20.00) damage of attack type Spells and damage type Universal
                            Else - Actions
                                Custom script:   call RemoveLocation (udg_Epicenter_Picked_Loc)
                                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    If - Conditions
                                        (Distance between Epicenter_Caster_Loc and Epicenter_Picked_Loc) Less than or equal to 600.00
                                    Then - Actions
                                        Unit - Cause Epicenter_Caster to damage (Picked unit), dealing ((Real(Epicenter_Damage)) - 30.00) damage of attack type Spells and damage type Universal
                                    Else - Actions
                                        Custom script:   call RemoveLocation (udg_Epicenter_Picked_Loc)
        Custom script:   call DestroyGroup (udg_Epicenter_Group)
        Custom script:   call RemoveLocation (udg_Epicenter_Caster_Loc)
        Custom script:   call RemoveLocation (udg_Epicenter_Picked_Loc)
 

Tinki3

Special Member
Reaction score
418
Close, but like this:
Code:
    Actions
        Set Epicenter_Pulses = (Epicenter_Pulses - 1)
        Set Epicenter_Caster_Loc = (Position of Epicenter_Caster)
        Set Epicenter_Group = (Units within 600.00 of Epicenter_Caster_Loc matching ((((Matching unit) belongs to an enemy of (Owner of Epicenter_Caster)) Equal to True) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) is A structure) Equal to False))))
        Environment - Create a 0.50 second Temporary crater deformation at Epicenter_Caster_Loc with radius 560.00 and depth 28.00
        Unit - Create 1 Dummy Unit for (Owner of Epicenter_Caster) at Epicenter_Caster_Loc facing Default building facing degrees
        Unit - Add Epicenter Slow  to (Last created unit)
        Unit - Order (Last created unit) to Human Mountain King - Thunder Clap
        Unit - Add a 0.30 second Generic expiration timer to (Last created unit)
        Unit Group - Pick every unit in Epicenter_Group and do (Actions)
            Loop - Actions
                Set Epicenter_Picked_Loc = (Position of (Picked unit))
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Distance between Epicenter_Caster_Loc and Epicenter_Picked_Loc) Less than or equal to 200.00
                    Then - Actions
                        Unit - Cause Epicenter_Caster to damage (Picked unit), dealing ((Real(Epicenter_Damage)) + 20.00) damage of attack type Spells and damage type Universal
                    Else - Actions
                        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            If - Conditions
                                (Distance between Epicenter_Caster_Loc and Epicenter_Picked_Loc) Less than or equal to 400.00
                            Then - Actions
                                Unit - Cause Epicenter_Caster to damage (Picked unit), dealing ((Real(Epicenter_Damage)) - 20.00) damage of attack type Spells and damage type Universal
                            Else - Actions
                                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    If - Conditions
                                        (Distance between Epicenter_Caster_Loc and Epicenter_Picked_Loc) Less than or equal to 600.00
                                    Then - Actions
                                        Unit - Cause Epicenter_Caster to damage (Picked unit), dealing ((Real(Epicenter_Damage)) - 30.00) damage of attack type Spells and damage type Universal
                                    Else - Actions
                [COLOR="Red"]Custom script:   call RemoveLocation (udg_Epicenter_Picked_Loc)[/COLOR]
        Custom script:   call DestroyGroup (udg_Epicenter_Group)
        Custom script:   call RemoveLocation (udg_Epicenter_Caster_Loc)
Notice that the line in red is inside the Loop - Actions, and outside the If-Then-Else statement.
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
888
New Code. Hopefully the last. :rolleyes:

JASS:
                             //These three constant functions control the range of the damage and deformation. Just change the values in these functions to alter the trigger.

constant function LargeDamageRange takes nothing returns real
    return 600.00
endfunction

constant function MediumDamageRange takes nothing returns real
    return 400.00
endfunction

constant function SmallDamageRange takes nothing returns real
    return 200.00
endfunction

constant function TimeBetweenRipples takes nothing returns real
    return 0.3
endfunction

constant function EpicenterAbilityCode takes nothing returns integer
    return 'A002'
endfunction

constant function DummyUnitCode takes nothing returns integer
    return 'h000'
endfunction

constant function DummyAbilityCode takes nothing returns integer
    return 'A001'
endfunction

function NumberOfPulses takes unit caster returns integer
    return ( 4 + ( 2 * GetUnitAbilityLevel(caster, EpicenterAbilityCode()) ) )
endfunction

function Matching takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) > 0.405 and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(udg_Epicenter_Caster)) == true
endfunction

function Picked takes nothing returns nothing
    local location unitloc = GetUnitLoc(GetEnumUnit())
    local location Epicenter_Caster_Loc = GetUnitLoc(udg_Epicenter_Caster)
    if ( DistanceBetweenPoints(Epicenter_Caster_Loc, unitloc) <= SmallDamageRange() ) then
        call UnitDamageTarget( udg_Epicenter_Caster, GetEnumUnit(), ( I2R(udg_Epicenter_Damage) + 20.00 ), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
    else
        if ( DistanceBetweenPoints(Epicenter_Caster_Loc, unitloc) <= MediumDamageRange() ) then
            call UnitDamageTarget( udg_Epicenter_Caster, GetEnumUnit(), ( I2R(udg_Epicenter_Damage) - 20.00 ), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
        else
            if ( DistanceBetweenPoints(Epicenter_Caster_Loc, unitloc) <= LargeDamageRange() ) then
                call UnitDamageTarget( udg_Epicenter_Caster, GetEnumUnit(), ( I2R(udg_Epicenter_Damage) - 30.00 ),true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
            else
            endif
        endif
    endif
    call RemoveLocation (unitloc)
    call RemoveLocation (Epicenter_Caster_Loc)
    set unitloc = null
    set Epicenter_Caster_Loc = null 
endfunction

function Trig_Epicenter_Action_Actions takes nothing returns nothing
    local unit caster = udg_Epicenter_Caster
    local integer Epicenter_Pulses = NumberOfPulses(caster)
    local location Epicenter_Caster_Loc
    local group Epicenter_Group
    local boolexpr b
    loop
      exitwhen Epicenter_Pulses == 0
      set udg_Epicenter_Caster = caster
      set Epicenter_Caster_Loc = GetUnitLoc(caster)
      set b = Condition(function Matching)
      set Epicenter_Group = GetUnitsInRangeOfLocMatching(LargeDamageRange(), Epicenter_Caster_Loc, b) 
      call TerrainDeformationCraterBJ( 0.5, false, Epicenter_Caster_Loc, LargeDamageRange()-40.00, 28.00 )
      call CreateNUnitsAtLoc( 1, DummyUnitCode(), GetOwningPlayer(caster), Epicenter_Caster_Loc, bj_UNIT_FACING )
      call UnitAddAbility(GetLastCreatedUnit(), DummyAbilityCode() )
      call IssueImmediateOrder( GetLastCreatedUnit(), "thunderclap" )
      call UnitApplyTimedLife(GetLastCreatedUnit(), 'BTLF', 0.30 )
      call ForGroup( Epicenter_Group, function Picked )
      set Epicenter_Pulses = Epicenter_Pulses-1
      call RemoveLocation (Epicenter_Caster_Loc)
      call DestroyGroup (Epicenter_Group)
      call DestroyBoolExpr(b)
      set b = null
      set Epicenter_Caster_Loc = null
      set Epicenter_Group = null
      call PolledWait(TimeBetweenRipples())
    endloop
    set caster = null
endfunction

//===========================================================================
function InitTrig_Epicenter_Action takes nothing returns nothing
    set gg_trg_Epicenter_Action = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Epicenter_Action, function Trig_Epicenter_Action_Actions )
endfunction
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
888
> Yes though you might not want to filter air units:

Is there something bad about doing that?
O_o.gif
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
888
> it'd look silly if units 700 range above the ground
were being struck by some ability that is powered by the ground.

I thought that's what that filer avoids....
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
888
Your wording was throwing me off:

> Yes though you might not want to filter air units

I suppose air units could be filtered.
Naminator could probably do that himself, actually, since you basically put it up there. :D
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
888
Tinki3! Quit giving me heart attacks thinking that the trigger has a problem! :p

So:

Filter air units, Naminator.
Take it or leave it.
Can you figure it out yourself?
That'd be great, as it would mean you're learning some JASS.
4e65e426.gif
 

Naminator

Coming Back To Life
Reaction score
76
Tinki3! Quit giving me heart attacks thinking that the trigger has a problem! :p

So:

Filter air units, Naminator.
Take it or leave it.
Can you figure it out yourself?
That'd be great, as it would mean you're learning some JASS.
4e65e426.gif

Leave it. In DotA flying heroes, they cannot past over trees, but they are flying :p, so I leave it. Thanks and Upadate it!
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top