• 🏆 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!
  • ✅ HD Level Design Contest #1 POLL is now OPEN! Check out the stunning visuals of the final entries. 🔗Click here to cast your vote!

[JASS] Custom-Spell's effects doesn't work properly

Status
Not open for further replies.
Level 2
Joined
May 1, 2010
Messages
13
Hi, i've got a problem with a triggers and timers created effects.
The trigger is a custom spell based on abitily: ANcl. It simply creates a signal-effect and a chaos-comet effect, starts a non-periodic timer for 3 secs. After that, the comet hits and another effect is created and damage is dealt.

Here the JASS:


JASS:
function Trig_ChaosComet_IsEnemy takes nothing returns boolean
    return (( IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(udg_ChaosCometCaster)) == true ) )
endfunction

function Trig_ChaosComet_Damage takes nothing returns nothing
    local integer level = GetUnitAbilityLevelSwapped('A0DJ', udg_ChaosCometCaster)
    local real damage = (level * 75.00)
    call UnitDamageTargetBJ( udg_ChaosCometCaster, GetEnumUnit(), damage, ATTACK_TYPE_HERO, DAMAGE_TYPE_UNIVERSAL )
    call AddSpecialEffectTargetUnitBJ( "chest", GetEnumUnit(), "Abilities\\Spells\\Other\\FrostDamage\\FrostDamage.mdl" )
    call DestroyEffect( bj_lastCreatedEffect )
endfunction

function Trig_ChaosComet_Wait takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local group damageGroup
    local effect tempEffect 
    
    set damageGroup = GetUnitsInRangeOfLocMatching( 200, udg_ChaosCometTarget, Condition(function Trig_ChaosComet_IsEnemy) )
    call ForGroup(damageGroup, function Trig_ChaosComet_Damage)

    set tempEffect = AddSpecialEffectLoc( "Units\\NightElf\\Wisp\\WispExplode.mdl", udg_ChaosCometTarget )
    call DestroyEffect( tempEffect )
    set tempEffect = AddSpecialEffectLoc( "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl", udg_ChaosCometTarget )
    call DestroyEffect( tempEffect )
    set tempEffect = null
    
    call DestroyEffect(udg_ChaosCometIndicator)
    set udg_ChaosCometIndicator = null
    set udg_ChaosCometCaster = null
    call RemoveLocation(udg_ChaosCometTarget)
    set udg_ChaosCometTarget = null
    call DestroyGroup(damageGroup)
    set damageGroup = null
    call PauseTimer(t)
    call DestroyTimer(t)
    set t = null
endfunction

function Trig_ChaosComet_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local effect tempEffect 
    
    set udg_ChaosCometCaster = GetTriggerUnit()
    set udg_ChaosCometTarget = GetSpellTargetLoc()
    
    set tempEffect = AddSpecialEffectLoc( "Objects\\Spawnmodels\\Demon\\InfernalMeteor\\InfernalMeteor3.mdl", udg_ChaosCometTarget )
    call DestroyEffect( tempEffect )
    set tempEffect = null
    
    set udg_ChaosCometIndicator = AddSpecialEffectLoc( "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl", udg_ChaosCometTarget )

    call TimerStart(t, 2.7, false, function Trig_ChaosComet_Wait)
    set t = null
    
endfunction

function Trig_ChaosComet_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A0DJ' ) ) then
        return false
    endif
    return true
endfunction

//===========================================================================
function InitTrig_ChaosComet takes nothing returns nothing
    set gg_trg_ChaosComet = CreateTrigger(  )
    
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ChaosComet, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_ChaosComet, Condition( function Trig_ChaosComet_Conditions ) )
    
    call TriggerAddAction( gg_trg_ChaosComet, function Trig_ChaosComet_Actions )
endfunction

Now, the problem is that some of the created effects won't display! The ChaosCometIndicator-Effect:
JASS:
set udg_ChaosCometIndicator = AddSpecialEffectLoc( "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl", udg_ChaosCometTarget )
works, and the others won't show up...

I have to mention, that it worked! I'm using newgen and just switched my wc3 to 1.26a.

Does anybod has an idea, what caused the error??? i'm totaly confused...:vw_wtf:
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
Try this instead of creating effects and then destroying them:

JASS:
call DestroyEffect(AddSpecialEffectTarget("Units\\NightElf\\Wisp\\WispExplode.mdl", udg_ChaosCometTarget, "origin"))
I'm no expert with JASS but, you seem to be using AddSpecialEffectLoc without including a location.
 
Level 2
Joined
May 1, 2010
Messages
13
Yes, i'll try it! but it worked for the global effect-var
JASS:
udg_ChaosCometIndicator
but not for the local
JASS:
tempEffect
in this lines:
JASS:
    set tempEffect = AddSpecialEffectLoc( "Objects\\Spawnmodels\\Demon\\InfernalMeteor\\InfernalMeteor3.mdl", udg_ChaosCometTarget )
    call DestroyEffect( tempEffect )
    set tempEffect = null
    
    set udg_ChaosCometIndicator = AddSpecialEffectLoc( "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl", udg_ChaosCometTarget )

Edit:
You meant that udg_ChaosCometTarget is not assigned in the call of the timer-function? it is assigned before the timer is started in the function: Trig_ChaosComet_Actions
here:
JASS:
function Trig_ChaosComet_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local effect tempEffect 
    
    set udg_ChaosCometCaster = GetTriggerUnit()
    set udg_ChaosCometTarget = GetSpellTargetLoc()
    
    set tempEffect = AddSpecialEffectLoc( "Objects\\Spawnmodels\\Demon\\InfernalMeteor\\InfernalMeteor3.mdl", udg_ChaosCometTarget )
    call DestroyEffect( tempEffect )
    set tempEffect = null
    
    set udg_ChaosCometIndicator = AddSpecialEffectLoc( "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl", udg_ChaosCometTarget )

    call TimerStart(t, 2.7, false, function Trig_ChaosComet_Wait)
    set t = null
    
endfunction
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
Is "udg_ChaosCometTarget" a location variable?
Try putting the destroy and add special effect into one line - this may solve the problem. This way you don't need to create a local variable.

JASS:
call DestroyEffect(AddSpecialEffectLoc("Objects\\Spawnmodels\\Demon\\InfernalMeteor\\InfernalMeteor3.mdl", udg_ChaosCometTarget))
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
I will add destription in sec. Fixed trigger:
~MUI version
JASS:
function Trig_ChaosComet_IsEnemy takes nothing returns boolean
    local integer level
    local real damage
    local unit u = GetFilterUnit()

    if IsPlayerEnemy(GetOwningPlayer(u), GetOwningPlayer(udg_ChaosCometCaster)) == true then
        set level = GetUnitAbilityLevel(udg_ChaosCometCaster, 'A0DJ')
        set damage = (level * 75.00)
        call UnitDamageTarget(udg_ChaosCometCaster, u, damage, false, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_UNIVERSAL, null)
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\FrostDamage\\FrostDamage.mdl", u, "chest"))
    endif

    set u = null
    return false
endfunction

function Trig_ChaosComet_Wait takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local real x = LoadReal(udg_Hash, id, 2)
    local real y = LoadReal(udg_Hash, id, 3)

    set udg_ChaosCometCaster = LoadUnitHandle(udg_Hash, id, 1)
    call GroupEnumUnitsInRange (bj_lastCreatedGroup, x, y, 200, Condition(function Trig_ChaosComet_IsEnemy))
    call DestroyEffect(AddSpecialEffect( "Units\\NightElf\\Wisp\\WispExplode.mdl", x, y))
    call DestroyEffect(AddSpecialEffect( "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl", x, y))
    call DestroyEffect(LoadEffectHandle(udg_Hash, id, 4))
    call FlushChildHashtable(udg_Hash, id)
    call PauseTimer(t)
    call DestroyTimer(t)

    set t = null
endfunction

function Trig_ChaosComet_Conditions takes nothing returns boolean
    local timer t
    local integer id
    local real x = GetSpellTargetX()
    local real y = GetSpellTargetY()
    local unit u = GetTriggerUnit()

    if GetSpellAbilityId() == 'A0DJ' then
        set t = CreateTimer()
        set id = GetHandleId(t)
        call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Demon\\InfernalMeteor\\InfernalMeteor3.mdl", x, y))
        call SaveUnitHandle(udg_Hash, id, 1, u)
        call SaveReal(udg_Hash, id, 2, x)
        call SaveReal(udg_Hash, id, 3, y)
        call SaveEffectHandle(udg_Hash, id, 4, AddSpecialEffect( "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl", x, y))
        call TimerStart(t, 2.7, false, function Trig_ChaosComet_Wait)
    endif
    set t = null
    set u = null
    return false
endfunction

//===========================================================================
function InitTrig_ChaosComet takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(t, Condition( function Trig_ChaosComet_Conditions ))
    set udg_Hash = InitHashtable()
    set t = null
endfunction
 
Last edited:
Level 2
Joined
May 1, 2010
Messages
13
No, it is a global variable.

i changed it that no more local variables are needed, but the problem remains :(

here the code:

JASS:
function Trig_ChaosComet_IsEnemy takes nothing returns boolean
    return (( IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(udg_ChaosCometCaster)) == true ) )
endfunction

function Trig_ChaosComet_Damage takes nothing returns nothing
    local integer level = GetUnitAbilityLevelSwapped('A0DJ', udg_ChaosCometCaster)
    local real damage = (level * 75.00)
    call UnitDamageTargetBJ( udg_ChaosCometCaster, GetEnumUnit(), damage, ATTACK_TYPE_HERO, DAMAGE_TYPE_UNIVERSAL )
    call DestroyEffect( AddSpecialEffectTarget("Abilities\\Spells\\Other\\FrostDamage\\FrostDamage.mdl", GetEnumUnit(), "chest") )
endfunction

function Trig_ChaosComet_Wait takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local group damageGroup
    
    set damageGroup = GetUnitsInRangeOfLocMatching( 200, udg_ChaosCometTarget, Condition(function Trig_ChaosComet_IsEnemy) )
    call ForGroup(damageGroup, function Trig_ChaosComet_Damage)

    call DestroyEffect( AddSpecialEffectLoc( "Units\\NightElf\\Wisp\\WispExplode.mdl", udg_ChaosCometTarget ) )
    call DestroyEffect( AddSpecialEffectLoc( "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl", udg_ChaosCometTarget ) )
    
    call DestroyEffect(udg_ChaosCometIndicator)
    set udg_ChaosCometIndicator = null
    set udg_ChaosCometCaster = null
    call RemoveLocation(udg_ChaosCometTarget)
    set udg_ChaosCometTarget = null
    call DestroyGroup(damageGroup)
    set damageGroup = null
    call PauseTimer(t)
    call DestroyTimer(t)
    set t = null
endfunction

function Trig_ChaosComet_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    
    set udg_ChaosCometCaster = GetTriggerUnit()
    set udg_ChaosCometTarget = GetSpellTargetLoc()
    
    call DestroyEffect( AddSpecialEffectLoc( "Objects\\Spawnmodels\\Demon\\InfernalMeteor\\InfernalMeteor3.mdl", udg_ChaosCometTarget ) )
    
    set udg_ChaosCometIndicator = AddSpecialEffectLoc( "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl", udg_ChaosCometTarget )

    call TimerStart(t, 2.7, false, function Trig_ChaosComet_Wait)
    set t = null
endfunction

function Trig_ChaosComet_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A0DJ' ) ) then
        return false
    endif
    return true
endfunction

//===========================================================================
function InitTrig_ChaosComet takes nothing returns nothing
    set gg_trg_ChaosComet = CreateTrigger(  )
    
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ChaosComet, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_ChaosComet, Condition( function Trig_ChaosComet_Conditions ) )
    
    call TriggerAddAction( gg_trg_ChaosComet, function Trig_ChaosComet_Actions )
endfunction
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Fixed syntax errors. Now, a bit of explanation:

- Merge Conditions and Actions into one function
- You need only two globals variables: hashtable and unit one (hashtable 'Hash' is here for making your spell MUI)
- to get rid of ForGroup() just add actions immidiately in Filter function
- use natives instead of Switch/Sample/BJ
- coordinates proves to be much more effective than locations
- get rid of leaks
- first destroy handles before nulling them (you're actually nulling them before destroying, so functions Destroy/Removing will actually refer to null - nothing will get removed)
 
Level 2
Joined
May 1, 2010
Messages
13
Thanks Spinnaker, now it is optimized ;) But the error is still the same, only the manadrain-effect is displayed...as before :(

here how it looks now:

JASS:
function Trig_ChaosComet_IsEnemy takes nothing returns boolean
    local integer level
    local real damage
    local unit u = GetFilterUnit()
    if IsPlayerEnemy(GetOwningPlayer(u), GetOwningPlayer(udg_ChaosCometCaster)) == true then
        set level = GetUnitAbilityLevel(udg_ChaosCometCaster, 'A0DJ')
        set damage = (level * 75.00)
        call UnitDamageTarget(udg_ChaosCometCaster, u, damage, false, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_UNIVERSAL, null)
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\FrostDamage\\FrostDamage.mdl", u, "chest"))
    endif
    set u = null
    return true
endfunction

function Trig_ChaosComet_Wait takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local real x = LoadReal(udg_ChaosCometHash, id, 2)
    local real y = LoadReal(udg_ChaosCometHash, id, 3)
    local effect tempEffect 
    set udg_ChaosCometCaster = LoadUnitHandle(udg_ChaosCometHash, id, 1)
    call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, 200, Condition(function Trig_ChaosComet_IsEnemy))

    call DestroyEffect(AddSpecialEffect( "Units\\NightElf\\Wisp\\WispExplode.mdl", x, y))
    call DestroyEffect(AddSpecialEffect( "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl", x, y))
    
    call DestroyEffect(LoadEffectHandle(udg_ChaosCometHash, id, 4))
    call FlushChildHashtable(udg_ChaosCometHash, id)
    call PauseTimer(t)
    call DestroyTimer(t)
    set t = null
endfunction

function Trig_ChaosComet_Conditions takes nothing returns boolean
    local timer t
    local integer id
    local effect tempEffect 
    local real x = GetSpellTargetX()
    local real y = GetSpellTargetY()
    local unit u = GetTriggerUnit()
    if GetSpellAbilityId() == 'A0DJ' then
        set t = CreateTimer()
        set id = GetHandleId(t)
        call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Demon\\InfernalMeteor\\InfernalMeteor3.mdl", x, y))
        call SaveEffectHandle(udg_ChaosCometHash, id, 4, AddSpecialEffect( "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl", x, y))
        call TimerStart(t, 2.7, false, function Trig_ChaosComet_Wait)
    endif
    set t = null
    return true
endfunction

//===========================================================================
function InitTrig_ChaosComet takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(t, Condition( function Trig_ChaosComet_Conditions ))
    set udg_ChaosCometHash = InitHashtable()
    set t = null
endfunction

i still think that the error could have been caused by changing form v1.24d to 1.26 :eekani:
 
Level 2
Joined
May 1, 2010
Messages
13
Fixed syntax errors. Now, a bit of explanation:

- Merge Conditions and Actions into one function
- You need only two globals variables: hashtable and unit one (hashtable 'Hash' is here for making your spell MUI)
- to get rid of ForGroup() just add actions immidiately in Filter function
- use natives instead of Switch/Sample/BJ
- coordinates proves to be much more effective than locations
- get rid of leaks
- first destroy handles before nulling them (you're actually nulling them before destroying, so functions Destroy/Removing will actually refer to null - nothing will get removed)

Thanks for that! It isn't needed MUI now, but maybe later. I've never considered doing it in the conditions, clever :)
Im still writing it fast with BJs and stuff and optimize it afterwards...stupid, i know -.-

Well, problem remains sadly....i could explode...
 
Level 2
Joined
May 1, 2010
Messages
13
Done, but it is still that the drain is on the ground and nothing happens.
Im gonna make a extra map for that and post it! Than it is better to compare :)

Edit: map for testing included! please take a look at this. Does every effect display?
 

Attachments

  • ChaosComet.w3m
    15.6 KB · Views: 63
  • ChaosComet.w3x
    20.3 KB · Views: 78
Last edited:
Level 2
Joined
May 1, 2010
Messages
13
What is the diffrence if you use Hash and i ChaosCometHash? If i replace it, the results are the same...or not?

And for me i see only the mana-drain effect, nothing else! same for you or do you see the comet and the impact effects?
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
@gormed For me all effects apply correctly. You have to have low details turned on. Btw, good point watermelon - that effect play's it's death animation (which for this model exactly sucks). Download mine test map. I don't how the spell can work if you are refering to hashtable 'Hash' which doesn't exist in your map.
 
Level 2
Joined
May 1, 2010
Messages
13
Thanks you two,

so it isn't the spell which was wrong (okay, it was leaking and so on, but it did what i intended). So my wc3 could be the problem:

i used this tool: Warcraft 1.26 Version Switcher to switch form 1.24d to 1.26 as said before. Does anybody know such errors??

@Spinnaker I refered to udg_ChaosCometHash not to udg_Hash.

@watermelon_1234 thanks, i will take another one. That was only to test if that effect appears or isn't displayed like the rest. So this was a bad testing-sample^^

Edit: Okay i think i got the error: this program is used to patch from 1.25b to 1.26 -.-
I will try to patch it the right way...

Edit2: Thaaanks to all! now it works, was that nasty version-error :thumbs_up:
 
Last edited:
Status
Not open for further replies.
Top