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

How to find out target type of ability used?

Status
Not open for further replies.
So, I encountered a simple problem that is probably related to a bug, but whatevs...

On immediate no-target abilities based on channel the GetSpellTargetUnit() returns the casting unit instead of null. This seems to only happen for channel; for example, the Berserk ability returns null properly.

This is problematic for a very simple reason: GetSpellTargetUnit() == null is the only way we can seperate instant cast no-target abilities from targeted abilities in an event response.

Has anyone found a workaround for this yet?
 
Did anyone of you actually read my initial post?

How would GetSpellTargetLoc() even help me with that problem? Nice, I can make sure it wasn't a point target ability; great, but that's not the issue here. I want to find out that this ability wasn't a target ability!


And just to go sure: the snippet you posted does not work correctly with channel either.
 
Of course we did.

This snippet will fail if someone uses an immediate ability based on channel. Channel has the nasty property to return the caster for GetSpellTargetUnit() when setting the target type to self-cast, so your condition will break there.
If it's buggy only for instant abilities (Berserk, Defend, Magical Defense, Mana Shield, Immolation, Divine Shield)
you could write a function which checks if current order of unit equals one of them.

JASS doesn't provide a direct way to read data from object editor, so workarounds have to be used I think.
And if the method mentioned by bribe Bribe works for Non-Target Spells like WarStomb, then it could be an acceptable solution to check for orders for instant abilties.
 
It seems to work for all non-channel abilities, but not for channel.
That's what I was talking about the entire time.

And since channel is probably the most frequently used ability of all, that is actually a serious issue.

Guess I need to map out and flag all abilities in my map manually. Fun for the entire family.
 
Level 23
Joined
Feb 6, 2014
Messages
2,466
Guess I need to map out and flag all abilities in my map manually. Fun for the entire family.

Not necessary all, only unit target abilities which can be self-cast.

Example, you could store all unit-target abilities that allows self targeting to a hashtable. Your check would be something like
if not HaveSavedInteger(..., spellId) and target == caster then
//instant spell
endif
 
Not necessary all, only unit target abilities which can be self-cast.

Example, you could store all unit-target abilities that allows self targeting to a hashtable. Your check would be something like
if not HaveSavedInteger(..., spellId) and target == caster then
//instant spell
endif
If I have to map out a group of spells anyway, I might aswell do it for all spells and at least have the advantage to access that at any time from anywhere instead of just in a cast event response.

When you're forced to take a finger, at least grab the fucking hand instead; that's my motto.
 
Didn't know this fails for Channel. . .
[trigger=Fail Example]
Untitled Trigger 004
Events
Unit - A unit Starts the effect of an ability
Conditions
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Target unit of ability being cast) Not equal to No unit
Then - Actions
Game - Display to (All players) the text: Ability is a unit t...
Skip remaining actions
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Playable map area) contains (Target point of ability being cast)) Equal to True
Then - Actions
Game - Display to (All players) the text: Ability is a target
Skip remaining actions
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Target unit of ability being cast) Equal to No unit
((Playable map area) contains (Target point of ability being cast)) Equal to False
Then - Actions
Game - Display to (All players) the text: Ability is a no tar...
Else - Actions
[/trigger]


However while the above method fails for one of the most important abilities in-game this still works and catches the proper no target channel ability.


[trigger=Working Example]
Untitled Trigger 005
Events
Unit - A unit Is issued an order with no target
Conditions
Actions
Game - Display to (All players) the text: (String((Issued order)))
[/trigger]

Hope my fail-GUI doesn't bug you too much. =P
 
I have a really really stupid idea.

In order to simplify your mapping, you could just still do it in object editor. Put a number before the ability name.

For example: 0 for no target, 1 for point target, 2 for widget target, 3 for point or widget target

This way you could map it out all in object editor, and when it comes to code just use GetObjectName to and take the first letter of it.

Obviously this solution is kinda messed up but it could work really well if you wanted to go all out on indexing this stuff.
 
Well here's a solution until someone finds a juicy bug.

[trigger=Working so Far]
Untitled Trigger 004
Events
Unit - A unit Starts the effect of an ability
Conditions
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Target unit of ability being cast) Not equal to No unit
channelfixer[(Custom value of (Triggering unit))] Equal to 0
Then - Actions
Game - Display to (All players) the text: Ability is a unit t...
Skip remaining actions
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Playable map area) contains (Target point of ability being cast)) Equal to True
(X of (Target point of ability being cast)) Not equal to 0.00
(Y of (Target point of ability being cast)) Not equal to 0.00
(Target unit of ability being cast) Equal to No unit
Then - Actions
Game - Display to (All players) the text: Ability is a target
Skip remaining actions
Else - Actions
Game - Display to (All players) the text: Ability is a no tar...
Set channelfixer[(Custom value of (Triggering unit))] = 0
[/trigger]
[trigger=Other Part]
Untitled Trigger 005
Events
Unit - A unit Is issued an order with no target
Conditions
Actions
Set channelfixer[(Custom value of (Triggering unit))] = 0
Set channelfixer[(Custom value of (Triggering unit))] = 1
[/trigger]
 

EdgeOfChaos

E

EdgeOfChaos

I have a really really stupid idea.

In order to simplify your mapping, you could just still do it in object editor. Put a number before the ability name.

For example: 0 for no target, 1 for point target, 2 for widget target, 3 for point or widget target

This way you could map it out all in object editor, and when it comes to code just use GetObjectName to and take the first letter of it.

Obviously this solution is kinda messed up but it could work really well if you wanted to go all out on indexing this stuff.

This is really clever. Looks like the best solution here.
 
Using object data to create a pseudo spell registry is kind of a "magic variable" approach that is not good if you create a larger project, since you will most likely have forgotten about it eventually.

At least with code you can write comments.


Anyway, my problem is solved, I simply added the target type in an external registry.

@Dat-C3: Using orders to detect spellcasting is not a good solution for many reasons: PauseUnit, stuns, non-interrupting orders, spells with cast time, etc.
 
@Dat-C3: Using orders to detect spellcasting is not a good solution for many reasons: PauseUnit, stuns, non-interrupting orders, spells with cast time, etc.


Well the proper events don't work and luckily there's a way around each of those, glad you found the solution you wanted. :thumbs_up:
 
Last edited:
Level 7
Joined
Oct 19, 2015
Messages
286
Using orders to detect spellcasting is not a good solution for many reasons: PauseUnit, stuns, non-interrupting orders, spells with cast time, etc.
Well, you'd still use the spell effect event to detect the spellcasting, you'd only use the order event to store what was the type of the last order issued to each unit. That way, only non-interrupting orders could be a problem, but if you don't use such spells in your map this could be a viable solution.
 
Well, you'd still use the spell effect event to detect the spellcasting, you'd only use the order event to store what was the type of the last order issued to each unit. That way, only non-interrupting orders could be a problem, but if you don't use such spells in your map this could be a viable solution.

His project is actually huge, that's one of the issues here. Also there's still a problem with channel here, since it can have any order id. But I guess the solution to this would be to restrict base order ids that have the same target type?
 
Status
Not open for further replies.
Top