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

[Spell] & [Trigger] No Cooldown Activation

Status
Not open for further replies.
Level 4
Joined
Aug 6, 2014
Messages
87
(Bottom is the JASS code for my trigger, but I doubt that it'd be needed)

I've got an issue when I cast an ability it just instantly runs the trigger so it doesn't activate the ability cooldown, now my question is, how do I exactly activate the cooldown / make it work?
Putting "Wait" doesn't work, since that spell trigger is based of regions > with wait it just takes center of playable map area.

Event: Unit starts effect of an ability

Code:
function Trig_Call_of_the_Earth_Copy_Conditions takes nothing returns boolean
  if ( not ( GetSpellAbilityId() == 'A00Q' ) ) then
  return false
  endif
  return true
endfunction

function Trig_Call_of_the_Earth_Copy_Func001Func001Func002Func001Func001Func001Func001Func001C takes nothing returns boolean
  if ( not ( GetUnitAbilityLevelSwapped('A00Q', GetSpellAbilityUnit()) == 6 ) ) then
  return false
  endif
  return true
endfunction

function Trig_Call_of_the_Earth_Copy_Func001Func001Func002Func001Func001Func001Func001C takes nothing returns boolean
  if ( not ( GetUnitAbilityLevelSwapped('A00Q', GetSpellAbilityUnit()) == 5 ) ) then
  return false
  endif
  return true
endfunction

function Trig_Call_of_the_Earth_Copy_Func001Func001Func002Func001Func001Func001C takes nothing returns boolean
  if ( not ( GetUnitAbilityLevelSwapped('A00Q', GetSpellAbilityUnit()) == 4 ) ) then
  return false
  endif
  return true
endfunction

function Trig_Call_of_the_Earth_Copy_Func001Func001Func002Func001Func001C takes nothing returns boolean
  if ( not ( GetUnitAbilityLevelSwapped('A00Q', GetSpellAbilityUnit()) == 3 ) ) then
  return false
  endif
  return true
endfunction

function Trig_Call_of_the_Earth_Copy_Func001Func001Func002Func001C takes nothing returns boolean
  if ( not ( GetUnitAbilityLevelSwapped('A00Q', GetSpellAbilityUnit()) == 2 ) ) then
  return false
  endif
  return true
endfunction

function Trig_Call_of_the_Earth_Copy_Func001Func001Func002C takes nothing returns boolean
  if ( not ( GetUnitAbilityLevelSwapped('A00Q', GetSpellAbilityUnit()) == 1 ) ) then
  return false
  endif
  return true
endfunction

function Trig_Call_of_the_Earth_Copy_Func001Func001C takes nothing returns boolean
  if ( not ( IsPlayerEnemy(GetOwningPlayer(GetEnumUnit()), GetOwningPlayer(GetSpellAbilityUnit())) == true ) ) then
  return false
  endif
  return true
endfunction

function Trig_Call_of_the_Earth_Copy_Func001A takes nothing returns nothing
  if ( Trig_Call_of_the_Earth_Copy_Func001Func001C() ) then
  if ( Trig_Call_of_the_Earth_Copy_Func001Func001Func002C() ) then
  call UnitDamageTargetBJ( GetSpellAbilityUnit(), GetEnumUnit(), ( 35.00 + ( ( I2R(GetHeroStatBJ(bj_HEROSTAT_AGI, GetSpellAbilityUnit(), true)) * 0.50 ) + ( I2R(GetHeroStatBJ(bj_HEROSTAT_INT, GetSpellAbilityUnit(), true)) * 0.10 ) ) ), ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
  else
  if ( Trig_Call_of_the_Earth_Copy_Func001Func001Func002Func001C() ) then
  call UnitDamageTargetBJ( GetSpellAbilityUnit(), GetEnumUnit(), ( 50.00 + ( ( I2R(GetHeroStatBJ(bj_HEROSTAT_AGI, GetSpellAbilityUnit(), true)) * 0.50 ) + ( I2R(GetHeroStatBJ(bj_HEROSTAT_INT, GetSpellAbilityUnit(), true)) * 0.10 ) ) ), ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
  else
  if ( Trig_Call_of_the_Earth_Copy_Func001Func001Func002Func001Func001C() ) then
  call UnitDamageTargetBJ( GetSpellAbilityUnit(), GetEnumUnit(), ( 80.00 + ( ( I2R(GetHeroStatBJ(bj_HEROSTAT_AGI, GetSpellAbilityUnit(), true)) * 0.50 ) + ( I2R(GetHeroStatBJ(bj_HEROSTAT_INT, GetSpellAbilityUnit(), true)) * 0.10 ) ) ), ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
  else
  if ( Trig_Call_of_the_Earth_Copy_Func001Func001Func002Func001Func001Func001C() ) then
  call UnitDamageTargetBJ( GetSpellAbilityUnit(), GetEnumUnit(), ( 105.00 + ( ( I2R(GetHeroStatBJ(bj_HEROSTAT_AGI, GetSpellAbilityUnit(), true)) * 0.50 ) + ( I2R(GetHeroStatBJ(bj_HEROSTAT_INT, GetSpellAbilityUnit(), true)) * 0.10 ) ) ), ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
  else
  if ( Trig_Call_of_the_Earth_Copy_Func001Func001Func002Func001Func001Func001Func001C() ) then
  call UnitDamageTargetBJ( GetSpellAbilityUnit(), GetEnumUnit(), ( 125.00 + ( ( I2R(GetHeroStatBJ(bj_HEROSTAT_AGI, GetSpellAbilityUnit(), true)) * 0.50 ) + ( I2R(GetHeroStatBJ(bj_HEROSTAT_INT, GetSpellAbilityUnit(), true)) * 0.10 ) ) ), ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
  else
  if ( Trig_Call_of_the_Earth_Copy_Func001Func001Func002Func001Func001Func001Func001Func001C() ) then
  call UnitDamageTargetBJ( GetSpellAbilityUnit(), GetEnumUnit(), ( 160.00 + ( ( I2R(GetHeroStatBJ(bj_HEROSTAT_AGI, GetSpellAbilityUnit(), true)) * 0.50 ) + ( I2R(GetHeroStatBJ(bj_HEROSTAT_INT, GetSpellAbilityUnit(), true)) * 0.10 ) ) ), ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
  else
  endif
  endif
  endif
  endif
  endif
  endif
  else
  call DoNothing(  )
  endif
endfunction

function Trig_Call_of_the_Earth_Copy_Actions takes nothing returns nothing
  call ForGroupBJ( GetUnitsInRectAll(RectFromCenterSizeBJ(GetSpellTargetLoc(), 300.00, 300.00)), function Trig_Call_of_the_Earth_Copy_Func001A )
  call AddSpecialEffectLocBJ( GetRectCenter(RectFromCenterSizeBJ(GetSpellTargetLoc(), 300.00, 300.00)), "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl" )
  call AddSpecialEffectLocBJ( GetRectCenter(RectFromCenterSizeBJ(GetSpellTargetLoc(), 300.00, 300.00)), "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl" )
  call TerrainDeformationCraterBJ( 2.00, false, GetSpellTargetLoc(), 300.00, 64.00 )
  call SetUnitPositionLoc( GetSpellAbilityUnit(), GetSpellTargetLoc() )
endfunction

//===========================================================================
function InitTrig_Call_of_the_Earth_Copy takes nothing returns nothing
  set gg_trg_Call_of_the_Earth_Copy = CreateTrigger(  )
  call TriggerRegisterAnyUnitEventBJ( gg_trg_Call_of_the_Earth_Copy, EVENT_PLAYER_UNIT_SPELL_EFFECT )
  call TriggerAddCondition( gg_trg_Call_of_the_Earth_Copy, Condition( function Trig_Call_of_the_Earth_Copy_Conditions ) )
  call TriggerAddAction( gg_trg_Call_of_the_Earth_Copy, function Trig_Call_of_the_Earth_Copy_Actions )
endfunction
 
Level 4
Joined
Aug 6, 2014
Messages
87
Uhm, don't get me wrong but why would I do that, can't see a point why uploading my map would be helpful.
I don't want it to leak.
 
If it is what DracoL1ch said you maybe can try out SetUnitX/Y and custom scripts. They don't interrupt orders.

But anyways, what I wanted to say - nice that you trust us your map to help fixing it, but posting the whole map with a ton of data included makes it hard to spot the problem.
Especially when we don't have pointers that tell us where exactly to look at in triggers, etc.
That's why I explicitly meant "sample map", which would cost you, the author, some of your minutes to replicate the problem in a more or less blank map, but which makes all the precess of helping so much easier.
It's not too rarely that by seperating the problem out, you spot the error yourself, but it also has the effect that the helpers can't look at your other stuff that you don't want to share yet, like you meantioned.

Not saying this only because of you here but one can often recognize that people are having the one or other issue with asking "correctly" for help or to provide needed information. Which makes help harder and longer as needed.
 
Level 4
Joined
Aug 6, 2014
Messages
87
It's not like I do it on purpose but the sad thing is I literally can't think logically.
And I appreciate your help but I'm quite low experienced in triggers at all, means I know nothing about JASS and have no idea about timers. Could you explain me that a bit? And please no JASS functions (If that call was a JASS function), I'm using JASS to paste the code because I have no idea how I paste a normal trigger. I don't want to work with JASS at all since the JassHelper doesn't seem to work properly on my PC, I don't want it to freeze everytime I save.
 

Attachments

  • sample ddd.w3x
    18.4 KB · Views: 35
What is done is almost only the usage of SetUnitX/Y instead of the normal "Unit - MoveUnit" action. Simply because as Dracol1ch said it does interrpt the unit order.

I use a variable to store the target point and finaly remove it. So ensure you have ticked "add unknown variables" inside the editor.
(Data -> Preferences -> Add unknown variables -- or something alike)

  • Custom script: set bj_wantDestroyGroup = true
  • ...
  • Custom script: call RemoveLocation(udg_Point)
^These lines are for preventing memory leaks. If you want to read up about this topic you can read here: http://www.hiveworkshop.com/threads/memory-leaks.263410/
 

Attachments

  • sample ddd.w3x
    19 KB · Views: 38
Level 4
Joined
Sep 13, 2014
Messages
106
Change

  • Unit - A unit Starts the effect of an ability
To

  • Unit - A unit Finishes casting an ability
BTW, to post GUI code like that, click on the outermost part of the trigger that you want to post, or shift click the parts of the trigger you want to post, then right click on it and press "Copy As Text", then paste it into your post and wrap [ TRIGGER] and [ /TRIGGER] tags around it (excluding the space at the beginning of each tag).
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
It's not like I do it on purpose but the sad thing is I literally can't think logically.
And I appreciate your help but I'm quite low experienced in triggers at all, means I know nothing about JASS and have no idea about timers. Could you explain me that a bit? And please no JASS functions (If that call was a JASS function), I'm using JASS to paste the code because I have no idea how I paste a normal trigger. I don't want to work with JASS at all since the JassHelper doesn't seem to work properly on my PC, I don't want it to freeze everytime I save.
Right click GUI root node and select copy as text. Then paste it in TRIGGER tags. You should also provide the map since such triggers cannot be easily modified unlike JASS.

Also JASS is always used by the editor. Just vJASS needs the JASSHelper pre-processor to save.
 
Level 4
Joined
Aug 6, 2014
Messages
87
Okay there has to be something wrong with this vJass, I just literally wanted to make a new function and the whole thing just crashed, it has ages of loading time, is this only 32 bit or what's happening?

Info: Testing IcemanBo's function right now, the one from ZerGreenOne doesn't work: Same effect as the wait function, and thanks Dr Super Good, finally I know how to do that :p

Edit: Finally works with a variable, I alrdy thought of using one but I thought I had to get each X, Y, Z and O coordinate of the target ability point, but thats its just Set Variable = Target Point.., wow, so simple. Thanks a lot, but at the end I got a question I've always wondered about: When I make custom spells with a projectile how exactly do I make that the targeted units get damaged/healed on impact of the projectile and not when the ability is casted? (Damage comes from trigger editor)
 
Last edited:
Thanks a lot, but at the end I got a question I've always wondered about: When I make custom spells with a projectile how exactly do I make that the targeted units get damaged/healed on impact of the projectile and not when the ability is casted? (Damage comes from trigger editor)

A lot of people will use dummy casters.
Dummy Casters Tutorial (thehelper.net)

Instead of triggering the damage/putting the projectile within the base spell, you'll create a custom spell with the projectile and damage already determined. When the spell is cast, create the dummy unit and order him to cast the spell. Then give him a short expiration timer so he dies.

Dealing triggered damage/healing when the projectile hits is a little bit more difficult. There isn't an easy way to detect when a projectile lands for a particular spell. There are a few options:
  • Use buffs. Add a buff to your spell. Run a periodic timer to see when the buff lands. However, timed spells become complex if you want them to work correctly. See the "MUI" section of this tutorial for more info:
    Dynamic Indexing
  • Trigger the projectile. This is a bit advanced--and I don't have a good resource to link to show you how to do this in GUI. You can check the spells section for examples.
  • You can wait (Distance between the two targets)/(Missile speed) time, and then apply the damage. This isn't 100% accurate if the target is moving, but in 95% of cases it is perfectly fine. Hell, even WoW does it this way iirc. Again, since this involves waiting, you'll want to look into MUI and sort that issue out yourself.
 
Level 4
Joined
Sep 13, 2014
Messages
106
Ok, this definitely works... oh, nvm.

Ok, this definitely works:

Do:

  • Set castPoint = (Target point of ability being cast)
  • Wait 0.20 game-time seconds
at the start of your function

and change every later instance of (Target point of ability being cast) to an instance of castPoint.

Note that using waits is inaccurate and therefore normally a bad idea, but I don't think you are looking for anything too complex.

This means that the cooldown works properly and the unit goes to the correct spot.



Also, why use this:

  • Special Effect - Create a special effect at (Center of (Region centered at castPoint with size (300.00, 300.00))) using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
  • Special Effect - Create a special effect at (Center of (Region centered at castPoint with size (300.00, 300.00))) using Abilities\Spells\Orc\WarStomp\WarStompCaster.mdl
  • Environment - Create a 2.00 second Temporary crater deformation at castPoint with radius 300.00 and depth 64.00
When you could use this (which is completely equivalent, and doesn't leak additional points and rects)

  • Special Effect - Create a special effect at castPoint using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
  • Special Effect - Create a special effect at castPoint using Abilities\Spells\Orc\WarStomp\WarStompCaster.mdl
  • Environment - Create a 2.00 second Temporary crater deformation at castPoint with radius 300.00 and depth 64.00
 
Last edited:
Using Waits in combination with temporary global variables (castPoint) is no good idea because they may get overwritten during the wait time and cause unwated results.
But ZerGreenOne is very right that you are leaking in these EffecrCreate functions unnecessarily at the moment.

@Freyky,
if you want spend some time you can have a look at this system and check out the demos for projecttiles.
If you find it comfortable you could give it a try--it's a nice system.
 
Level 4
Joined
Aug 6, 2014
Messages
87
I don't understand what's exactly leaking, sorry.

And I'll take a look at it, thanks.

Also quick question: Curious if it's possible to also add a trigger which extra damages targets for (e.g. 2x agility) targets which got attacked by chain lightning, with my trigger now it only strikes the first target:

  • Chain Lightning
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Chain Lightning
    • Actions
      • Unit - Cause (Casting unit) to damage (Target unit of ability being cast), dealing ((Real((Intelligence of (Casting unit) (Include bonuses)))) x 3.50) damage of attack type Spells and damage type Universal
 
You are creating rects with size of 300x300 which are never destroyed. -> leak.
This can't be easily prevented with GUI, so simply do what was suggested by ZerGreenOne.

For your second question--Idon't think there is a waterproof way for handling this with the default ability.
If you need precise and good results here, the recommended way is to trigger the ability yourself so you have full control over it.
 
Level 4
Joined
Aug 6, 2014
Messages
87
And how do I exactly trigger a chain lightning? I've got an Idea but that probably won't work because I'm not sure about the special effect / animation, the bouncing lightning.

> Every unit around Target unit of ability being cast for a 450 radius gets selected and damage dealt.
That's about the damage, but now I need a lightning which jumps exactly to each selected target.
 
Status
Not open for further replies.
Top