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: 180

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.
  • Monovertex Monovertex:
    How are you all? :D
    +1
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though

      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