Need big help to optimize this spell

Immolation

Member
Reaction score
20
JASS:
scope ElectricalDischarge initializer Init

//            Electrical Discharge
              
// Spell Descrpt.:
//---------------------------
// Gives a chance to release lightning bolts upon damaging an enemy that jump and deal damage to nearby targets.
// A single enemy cannot be damaged by Electrical Discharge more than once every X seconds.

    globals
        //Rawcodes
        private constant integer SPELL_ID = 'A000' 
        private constant integer EFFECT_ID = 'A001' 
        private constant integer BUFFSPELL_ID = 'A002'
        private constant integer DUMMY_ID = 'u000'
        private constant integer BUFF_ID = 'B000'
        
        //Effects
        private constant boolean EFFECT_ON_HIT = true
        private constant string EFFECT_NAME = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
    endglobals

    private function ChanceToFire takes integer level returns integer
        return 20 + (level * 5)
    endfunction
    
    private function Damage takes integer level returns real
        return 20.00 + (level * 5.00)
    endfunction
    
    private function Targets takes integer level returns integer
        return 3 + level
    endfunction
    
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    private function Conditions takes nothing returns boolean
        return GetUnitAbilityLevel(GetEventDamageSource(), 'A000') >= 1 and IsPlayerAlly(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetEventDamageSource())) == false
    endfunction

    private function GroupFilter takes nothing returns boolean
        return IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(GetEventDamageSource())) == true and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) <= 0) == false and GetUnitTypeId(GetFilterUnit()) != DUMMY_ID and GetUnitAbilityLevel(GetFilterUnit(), BUFF_ID) == 0 
    endfunction
    
    private function PickRandomUnit2 takes nothing returns nothing
        set bj_groupRandomConsidered = bj_groupRandomConsidered + 1
        if (GetRandomInt(1,bj_groupRandomConsidered) == 1) then
            set bj_groupRandomCurrentPick = GetEnumUnit()
        endif
    endfunction

    private function PickRandomUnit takes group g returns unit
        set bj_groupRandomConsidered = 0
        set bj_groupRandomCurrentPick = null
        call ForGroup(g, function PickRandomUnit2)
        return bj_groupRandomCurrentPick
    endfunction

    private function Actions takes nothing returns nothing
        local unit tu = GetTriggerUnit()
        local real x = GetUnitX(tu)
        local real y = GetUnitY(tu)
        local unit att = GetEventDamageSource()
        local player p = GetOwningPlayer(att)
        local integer level = GetUnitAbilityLevel(att, SPELL_ID)
        local integer LoopStart
        local integer LoopEnd
        local group g = CreateGroup()
        local boolexpr f = Condition(function GroupFilter)
        local unit target
        local unit dummy
        if GetRandomInt(1, 100) <= ChanceToFire(level) then
            if EFFECT_ON_HIT == true then
                call DestroyEffect(AddSpecialEffect(EFFECT_NAME, x, y))
            endif
            set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
            call UnitAddAbility(dummy, BUFFSPELL_ID)
            call IssueTargetOrder(dummy, "cripple", tu)
            set LoopStart = 1
            set LoopEnd = Targets(level)
            loop
                exitwhen LoopStart > LoopEnd
                call GroupEnumUnitsInRange(g, x, y, 500.00, f)
                set target = PickRandomUnit(g)
                set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                call UnitAddAbility(dummy, BUFFSPELL_ID)
                call IssueTargetOrder(dummy, "cripple", target)
                set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                call UnitAddAbility(dummy, EFFECT_ID)
                call IssueTargetOrder(dummy, "chainlightning", target)
                call UnitDamageTarget(dummy, target, Damage(level), true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                set LoopStart = LoopStart + 1
            endloop
        endif
        call DestroyBoolExpr(f)
        call DestroyGroup(g)
        set target = null
        set dummy = null
        set att = null
        set tu = null
    endfunction

    //===========================================================================
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitDamaged(t)
        call TriggerAddCondition(t, Condition(function Conditions))
        call TriggerAddAction(t, function Actions)
        call UsefulFunctions_Load(SPELL_ID)
        call UsefulFunctions_Load(BUFFSPELL_ID)
        call UsefulFunctions_Load(EFFECT_ID)
        set t = null
    endfunction
endscope


As the description at the top of the script implies, this spell has a X% chance upon damaging an enemy to release several lightnings that damage enemies near the damaged target(not the target itself). Enemies cannot be hit every X seconds due to a buff that I add through the other ability(rawcode:'A002')

Note that the lightning created through a custom chain lightning(rawcode:'A001') is used purely for the visual effect.

I'm waiting in awe for your l33t words, pro vJASSers out there :D

P.S.: About -
JASS:
call TriggerRegisterAnyUnitDamaged(t)

I started making this spell with eGUI, that had the event "Any unit takes damage", after realizing this was impossible with simple, leaky, stinky GUI I moved to vJASS :p
 

Azlier

Old World Ghost
Reaction score
461
Optimization, my favorite subject.

First, let's look at the root of the whole thing, the initializer:
JASS:
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitDamaged(t) //No comment. No idea what that function does internally.
call TriggerAddCondition(t, Condition(function Conditions))
call TriggerAddAction(t, function Actions) //Try doing all the actions in the condition function. Yes, you can do that.
call UsefulFunctions_Load(SPELL_ID)
call UsefulFunctions_Load(BUFFSPELL_ID)
call UsefulFunctions_Load(EFFECT_ID) //What are these useful functions?
//set t = null This line is unneeded.


Now, actions.
JASS:
private function Actions takes nothing returns nothing
    local unit tu = GetTriggerUnit()
    local real x = GetUnitX(tu)
    local real y = GetUnitY(tu)
    local unit att = GetEventDamageSource()
    local player p = GetOwningPlayer(att)
    local integer level = GetUnitAbilityLevel(att, SPELL_ID) //Try setting all these variables inside the "if".
//You gain some speed that way.
    local integer LoopStart
    local integer LoopEnd
    //local group g = CreateGroup()  //Use a single global group instead.
    //local boolexpr f = Condition(function GroupFilter)  Use Condition(function GroupFilter directly.
    local unit target
    local unit dummy
    if GetRandomInt(1, 100) <= ChanceToFire(level) then
        if EFFECT_ON_HIT == true then
            call DestroyEffect(AddSpecialEffect(EFFECT_NAME, x, y))
        endif
        set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
        call UnitAddAbility(dummy, BUFFSPELL_ID)
        call IssueTargetOrder(dummy, "cripple", tu)
        set LoopStart = 1
        set LoopEnd = Targets(level)
        loop
            exitwhen LoopStart > LoopEnd
            call GroupEnumUnitsInRange(g, x, y, 500.00, f)
            set target = PickRandomUnit(g)
            set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
            call UnitAddAbility(dummy, BUFFSPELL_ID)
            call IssueTargetOrder(dummy, "cripple", target)
            set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
            call UnitAddAbility(dummy, EFFECT_ID)
            call IssueTargetOrder(dummy, "chainlightning", target)
            call UnitDamageTarget(dummy, target, Damage(level), true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
            set LoopStart = LoopStart + 1
        endloop
    endif
    //call DestroyBoolExpr(f)  WRONG. NEVER DESTROY BOOLEXPRS MADE FROM Filter() NOR Condition(). 
    //call DestroyGroup(g)  Unneeded.
    set target = null
    set dummy = null
    set att = null
    set tu = null
endfunction


There's nothing wrong with using the BJ in this case.
JASS:
private function PickRandomUnit2 takes nothing returns nothing
    set bj_groupRandomConsidered = bj_groupRandomConsidered + 1
    if (GetRandomInt(1,bj_groupRandomConsidered) == 1) then
        set bj_groupRandomCurrentPick = GetEnumUnit()
    endif
endfunction


Same here.
JASS:
private function PickRandomUnit takes group g returns unit
    set bj_groupRandomConsidered = 0
    set bj_groupRandomCurrentPick = null
    call ForGroup(g, function PickRandomUnit2)
    return bj_groupRandomCurrentPick
endfunction
 

Immolation

Member
Reaction score
20
I have fixed everything you pointed out except:

-How can I put the Actions in the Conditions function?
-How can I declare the locals in the "if"?

About the:
JASS:
call TriggerRegisterAnyUnitDamaged(t)

I started making this spell with eGUI and it had a "Any unit takes damage" event. That's where it comes from.

and the:
JASS:
call UsefulFunctions_Load(SPELL_ID)
call UsefulFunctions_Load(BUFFSPELL_ID)
call UsefulFunctions_Load(EFFECT_ID)

Just some stuff I use to preload =)

Oh, thanks for the fast answer!

(I am such a noob :p)
 

Azlier

Old World Ghost
Reaction score
461
>How can I put the Actions in the Conditions function?

It's as simple as putting the conditions into an "if" at the beginning of the "actions" and setting all the local variables if the if turns out to be true.

>How can I declare the locals in the "if"?

Not declare. Set. There's a difference.
 

Immolation

Member
Reaction score
20
Ok, what I got now is:
JASS:
scope ElectricalDischarge initializer Init

//            Electrical Discharge
              
// Spell Descrpt.:
//---------------------------
// Gives a chance to release lightning bolts upon damaging an enemy that jump and deal damage to nearby targets.
// A single enemy cannot be damaged by Electrical Discharge more than once every X seconds.

    globals
        //Rawcodes
        private constant integer SPELL_ID = 'A000' 
        private constant integer EFFECT_ID = 'A001' 
        private constant integer BUFFSPELL_ID = 'A002'
        private constant integer DUMMY_ID = 'u000'
        private constant integer BUFF_ID = 'B000'
        
        //Effects
        private constant boolean EFFECT_ON_HIT = true
        private constant string EFFECT_NAME = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        private group g = CreateGroup()
    endglobals

    private function ChanceToFire takes integer level returns integer
        return 20 + (level * 5)
    endfunction
    
    private function Damage takes integer level returns real
        return 20.00 + (level * 5.00)
    endfunction
    
    private function Targets takes integer level returns integer
        return 3 + level
    endfunction
    
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    private function Conditions takes nothing returns boolean
        return GetUnitAbilityLevel(GetEventDamageSource(), 'A000') >= 1 and IsPlayerAlly(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetEventDamageSource())) == false
    endfunction

    private function GroupFilter takes nothing returns boolean
        return IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(GetEventDamageSource())) == true and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) <= 0) == false and GetUnitTypeId(GetFilterUnit()) != DUMMY_ID and GetUnitAbilityLevel(GetFilterUnit(), BUFF_ID) == 0 
    endfunction

    private function Actions takes nothing returns nothing
        local unit tu
        local real x
        local real y
        local unit att
        local player p
        local integer level
        local integer LoopStart
        local integer LoopEnd
        local unit target
        local unit dummy
        if GetRandomInt(1, 100) <= ChanceToFire(level) then
            set tu = GetTriggerUnit()
            set x = GetUnitX(tu)
            set y = GetUnitY(tu)
            set att = GetEventDamageSource()
            set p = GetOwningPlayer(att)
            set level = GetUnitAbilityLevel(att, SPELL_ID)
            if EFFECT_ON_HIT == true then
                call DestroyEffect(AddSpecialEffect(EFFECT_NAME, x, y))
            endif
            set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
            call UnitAddAbility(dummy, BUFFSPELL_ID)
            call IssueTargetOrder(dummy, "cripple", tu)
            set LoopStart = 1
            set LoopEnd = Targets(level)
            loop
                exitwhen LoopStart > LoopEnd
                call GroupEnumUnitsInRange(g, x, y, 500.00, Condition(function GroupFilter))
                set target = GroupPickRandomUnit(g)
                set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                call UnitAddAbility(dummy, BUFFSPELL_ID)
                call IssueTargetOrder(dummy, "cripple", target)
                set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                call UnitAddAbility(dummy, EFFECT_ID)
                call IssueTargetOrder(dummy, "chainlightning", target)
                call UnitDamageTarget(dummy, target, Damage(level), true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                set LoopStart = LoopStart + 1
            endloop
        endif
        set target = null
        set dummy = null
        set att = null
        set tu = null
    endfunction

    //===========================================================================
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitDamaged(t)
        call TriggerAddCondition(t, Condition(function Conditions))
        call TriggerAddAction(t, function Actions)
        call UsefulFunctions_Load(SPELL_ID)
        call UsefulFunctions_Load(BUFFSPELL_ID)
        call UsefulFunctions_Load(EFFECT_ID)
    endfunction
endscope


>>It's as simple as putting the conditions into an "if" at the beginning of the "actions" and setting all the local variables if the if turns out to be true.

I don't get this :(
 

Azlier

Old World Ghost
Reaction score
461
This is an action.
JASS:
private function Actions takes nothing returns nothing
        local unit tu
        local real x
        local real y
        local unit att
        local player p
        local integer level
        local integer LoopStart
        local integer LoopEnd
        local unit target
        local unit dummy
        if GetRandomInt(1, 100) <= ChanceToFire(level) then
            set tu = GetTriggerUnit()
            set x = GetUnitX(tu)
            set y = GetUnitY(tu)
            set att = GetEventDamageSource()
            set p = GetOwningPlayer(att)
            set level = GetUnitAbilityLevel(att, SPELL_ID)
            if EFFECT_ON_HIT == true then
                call DestroyEffect(AddSpecialEffect(EFFECT_NAME, x, y))
            endif
            set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
            call UnitAddAbility(dummy, BUFFSPELL_ID)
            call IssueTargetOrder(dummy, "cripple", tu)
            set LoopStart = 1
            set LoopEnd = Targets(level)
            loop
                exitwhen LoopStart > LoopEnd
                call GroupEnumUnitsInRange(g, x, y, 500.00, Condition(function GroupFilter))
                set target = GroupPickRandomUnit(g)
                set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                call UnitAddAbility(dummy, BUFFSPELL_ID)
                call IssueTargetOrder(dummy, "cripple", target)
                set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                call UnitAddAbility(dummy, EFFECT_ID)
                call IssueTargetOrder(dummy, "chainlightning", target)
                call UnitDamageTarget(dummy, target, Damage(level), true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                set LoopStart = LoopStart + 1
            endloop
        endif
        set target = null
        set dummy = null
        set att = null
        set tu = null
    endfunction


This is a magicondition!
JASS:
private function Actions takes nothing returns boolean
    local unit tu
    local real x
    local real y
    local unit att
    local player p
    local integer level
    local integer LoopStart
    local integer LoopEnd
    local unit target
    local unit dummy
    if GetUnitAbilityLevel(GetEventDamageSource(), 'A000') >= 1 and IsPlayerAlly(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetEventDamageSource())) == false then
        if GetRandomInt(1, 100) <= ChanceToFire(level) then
            set tu = GetTriggerUnit()
            set x = GetUnitX(tu)
            set y = GetUnitY(tu)
            set att = GetEventDamageSource()
            set p = GetOwningPlayer(att)
            set level = GetUnitAbilityLevel(att, SPELL_ID)
            if EFFECT_ON_HIT == true then
                call DestroyEffect(AddSpecialEffect(EFFECT_NAME, x, y))
            endif
            set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
            call UnitAddAbility(dummy, BUFFSPELL_ID)
            call IssueTargetOrder(dummy, "cripple", tu)
            set LoopStart = 1
            set LoopEnd = Targets(level)
            loop
                exitwhen LoopStart > LoopEnd
                call GroupEnumUnitsInRange(g, x, y, 500.00, Condition(function GroupFilter))
                set target = GroupPickRandomUnit(g)
                set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                call UnitAddAbility(dummy, BUFFSPELL_ID)
                call IssueTargetOrder(dummy, "cripple", target)
                set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                call UnitAddAbility(dummy, EFFECT_ID)
                call IssueTargetOrder(dummy, "chainlightning", target)
                call UnitDamageTarget(dummy, target, Damage(level), true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                set LoopStart = LoopStart + 1
            endloop
        endif
        set target = null
        set dummy = null
        set att = null
        set tu = null
    endif
    return false
endfunction


Now you just add the function Actions as a condition and ignore whatever else.
 

Immolation

Member
Reaction score
20
JASS:
scope ElectricalDischarge initializer Init

//            Electrical Discharge
              
// Spell Descrpt.:
//---------------------------
// Gives a chance to release lightning bolts upon damaging an enemy that jump and deal damage to nearby targets.
// A single enemy cannot be damaged by Electrical Discharge more than once every X seconds.

    globals
        //Rawcodes
        private constant integer SPELL_ID = 'A000' 
        private constant integer EFFECT_ID = 'A001' 
        private constant integer BUFFSPELL_ID = 'A002'
        private constant integer DUMMY_ID = 'u000'
        private constant integer BUFF_ID = 'B000'
        
        //Effects
        private constant boolean EFFECT_ON_HIT = true
        private constant string EFFECT_NAME = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        private group g = CreateGroup()
    endglobals

    private function ChanceToFire takes integer level returns integer
        return 20 + (level * 5)
    endfunction
    
    private function Damage takes integer level returns real
        return 20.00 + (level * 5.00)
    endfunction
    
    private function Targets takes integer level returns integer
        return 3 + level
    endfunction
    
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    private function GroupFilter takes nothing returns boolean
        return IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(GetEventDamageSource())) == true and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) <= 0) == false and GetUnitTypeId(GetFilterUnit()) != DUMMY_ID and GetUnitAbilityLevel(GetFilterUnit(), BUFF_ID) == 0 
    endfunction

     private function Actions takes nothing returns boolean
        local unit tu
        local real x
        local real y
        local unit att
        local player p
        local integer level
        local integer LoopStart
        local integer LoopEnd
        local unit target
        local unit dummy
        if GetUnitAbilityLevel(GetEventDamageSource(), 'A000') >= 1 and IsPlayerAlly(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetEventDamageSource())) == false then
            if GetRandomInt(1, 100) <= ChanceToFire(level) then
                set tu = GetTriggerUnit()
                set x = GetUnitX(tu)
                set y = GetUnitY(tu)
                set att = GetEventDamageSource()
                set p = GetOwningPlayer(att)
                set level = GetUnitAbilityLevel(att, SPELL_ID)
                if EFFECT_ON_HIT == true then
                    call DestroyEffect(AddSpecialEffect(EFFECT_NAME, x, y))
                endif
                set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                call UnitAddAbility(dummy, BUFFSPELL_ID)
                call IssueTargetOrder(dummy, "cripple", tu)
                set LoopStart = 1
                set LoopEnd = Targets(level)
                loop
                    exitwhen LoopStart > LoopEnd
                    call GroupEnumUnitsInRange(g, x, y, 500.00, Condition(function GroupFilter))
                    set target = GroupPickRandomUnit(g)
                    set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                    call UnitAddAbility(dummy, BUFFSPELL_ID)
                    call IssueTargetOrder(dummy, "cripple", target)
                    set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                    call UnitAddAbility(dummy, EFFECT_ID)
                    call IssueTargetOrder(dummy, "chainlightning", target)
                    call UnitDamageTarget(dummy, target, Damage(level), true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                    set LoopStart = LoopStart + 1
                endloop
            endif
            set target = null
            set dummy = null
            set att = null
            set tu = null
        endif
        return false
    endfunction
    //===========================================================================
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitDamaged(t)
        call TriggerAddCondition(t, Condition(function Actions))
        call UsefulFunctions_Load(SPELL_ID)
        call UsefulFunctions_Load(BUFFSPELL_ID)
        call UsefulFunctions_Load(EFFECT_ID)
    endfunction
endscope


Sadly enough, this doesn't work. Any guess?
 

Azlier

Old World Ghost
Reaction score
461
Define "doesn't work". What happens? Does it not compile or somefink?

If nothing happens at all, I'm tempted to blame the AnyUnitDamaged event.
 

Immolation

Member
Reaction score
20
Nothing happens. It does compile but nothing happens. The spell doesn't work.

And the event always worked, so I suppose it's good :D

I'll upload the map in a sec, wait for meh

EDIT: Done, uploaded.
 

Attachments

  • Test map.w3x
    157.8 KB · Views: 178

Azlier

Old World Ghost
Reaction score
461
Bah, the map is useless to me. I don't have WC3 on this computer. Please, post the contents of the AnyUnitDamaged script for me.

Also, try inserting some BJDebugMsg debug messages at strategic points within your script and tell me the results.
 

Immolation

Member
Reaction score
20
JASS:
scope ElectricalDischarge initializer Init

//            Electrical Discharge
              
// Spell Descrpt.:
//---------------------------
// Gives a chance to release lightning bolts upon damaging an enemy that jump and deal damage to nearby targets.
// A single enemy cannot be damaged by Electrical Discharge more than once every X seconds.

    globals
        //Rawcodes
        private constant integer SPELL_ID = 'A000' 
        private constant integer EFFECT_ID = 'A001' 
        private constant integer BUFFSPELL_ID = 'A002'
        private constant integer DUMMY_ID = 'u000'
        private constant integer BUFF_ID = 'B000'
        
        //Effects
        private constant boolean EFFECT_ON_HIT = true
        private constant string EFFECT_NAME = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        private group g = CreateGroup()
    endglobals

    private function ChanceToFire takes integer level returns integer
        return 20 + (level * 5)
    endfunction
    
    private function Damage takes integer level returns real
        return 20.00 + (level * 5.00)
    endfunction
    
    private function Targets takes integer level returns integer
        return 3 + level
    endfunction
    
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    private function GroupFilter takes nothing returns boolean
        return IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(GetEventDamageSource())) == true and (GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) <= 0) == false and GetUnitTypeId(GetFilterUnit()) != DUMMY_ID and GetUnitAbilityLevel(GetFilterUnit(), BUFF_ID) == 0 
    endfunction

     private function Actions takes nothing returns boolean
        local unit tu
        local real x
        local real y
        local unit att
        local player p
        local integer level
        local integer LoopStart
        local integer LoopEnd
        local unit target
        local unit dummy
        if GetUnitAbilityLevel(GetEventDamageSource(), 'A000') >= 1 and IsPlayerAlly(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetEventDamageSource())) == false then
        call BJDebugMsg("1") //This one works, so the damage is detected
            if GetRandomInt(1, 100) <= ChanceToFire(level) then
                call BJDebugMsg("2") //Doesn't work, my guess is the condition above, but I see no errors?
                set tu = GetTriggerUnit()
                set x = GetUnitX(tu)
                set y = GetUnitY(tu)
                set att = GetEventDamageSource()
                set p = GetOwningPlayer(att)
                set level = GetUnitAbilityLevel(att, SPELL_ID)
                if EFFECT_ON_HIT == true then
                    call DestroyEffect(AddSpecialEffect(EFFECT_NAME, x, y))
                endif
                set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                call UnitAddAbility(dummy, BUFFSPELL_ID)
                call IssueTargetOrder(dummy, "cripple", tu)
                set LoopStart = 1
                set LoopEnd = Targets(level)
                loop
                    exitwhen LoopStart > LoopEnd
                    call GroupEnumUnitsInRange(g, x, y, 500.00, Condition(function GroupFilter))
                    set target = GroupPickRandomUnit(g)
                    set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                    call UnitAddAbility(dummy, BUFFSPELL_ID)
                    call IssueTargetOrder(dummy, "cripple", target)
                    set dummy = CreateUnit(p, DUMMY_ID, x, y, 0.00)
                    call UnitAddAbility(dummy, EFFECT_ID)
                    call IssueTargetOrder(dummy, "chainlightning", target)
                    call UnitDamageTarget(dummy, target, Damage(level), true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                    set LoopStart = LoopStart + 1
                endloop
            endif
            set target = null
            set dummy = null
            set att = null
            set tu = null
        endif
        return false
    endfunction
    //===========================================================================
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitDamaged(t)
        call TriggerAddCondition(t, Condition(function Actions))
        call UsefulFunctions_Load(SPELL_ID)
        call UsefulFunctions_Load(BUFFSPELL_ID)
        call UsefulFunctions_Load(EFFECT_ID)
    endfunction
endscope



About AnyUnitDamaged:

I could only find these thingies:

JASS:
globals
    private trigger array TRIGS
    private integer COUNT = 0
    private group GROUP = CreateGroup()
    private trigger TRIGGER = CreateTrigger()
endglobals


and this:
JASS:
function TriggerRegisterAnyUnitDamaged takes trigger whichTrigger returns nothing
    set TRIGS[COUNT] = whichTrigger
    set COUNT = COUNT + 1
endfunction

private function Call takes nothing returns boolean
    local integer i = COUNT - 1
    loop
        if IsTriggerEnabled(TRIGS<i>) then
            if TriggerEvaluate(TRIGS<i>) then
                call TriggerExecute(TRIGS<i>)
            endif
        endif
        set i = i - 1
        exitwhen i &lt; 0
    endloop
    return false
endfunction

private function Add takes nothing returns boolean
    local unit u = GetFilterUnit()
    if IsUnitInGroup(u, GROUP) == false then
        call TriggerRegisterUnitEvent(TRIGGER, u, EVENT_UNIT_DAMAGED)
        call GroupAddUnit(GROUP, u)
    endif
    set u = null
    return false
endfunction

private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local region r = CreateRegion()
    call RegionAddRect(r, bj_mapInitialPlayableArea)
    call TriggerRegisterEnterRegion(t, r, Filter(function Add))
    call GroupEnumUnitsInRect(GROUP, bj_mapInitialPlayableArea, Filter(function Add))
    call TriggerAddCondition(TRIGGER, Condition(function Call))
endfunction</i></i></i>


EDIT: I'm going to sleep now, it's past midnight here now :D I'll see tomorrow, thanks for all the things so far (+rep)
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
COnditions ARe FAster THan ACtions
Sheesh you are either a good hacker or you've seen wc3's source code or you are blizzard ex dev guy...
If so can you tell me how the Spell Shield (ability) in the Amulet of Spell Shield (item) works "internally" - did they modified every spell they made for the expansion the check if a hero has this item and then give 'invul' ability for 0.01 sec (I am pritty sure that's not the way they do it with c/c++ but who knows)

Ok seriously now:
> = greater than
< = lesser than

Still need some help about this one. Any guess?
Make something involving them in gui and convert to custom text should answer your question.(I forget those > < == != too)
 

Immolation

Member
Reaction score
20
Umm, my problem are not > or <, my problem is why the spell isn't working after the second "if". :eek:

~Immolation
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top