How to create a special effect that is the model of a unit being targeted by a spell.

Level 1
Joined
Feb 14, 2025
Messages
6
I want to create an ability that will impale a target on a scorpion's stinger. I'm thinking the easiest way would be to stun and hide the targeted unit of a spell, then attach a special effect to the caster that looks like whichever unit is targeted. How can I make the special effect have the model of the spell's target?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
I'd just Stun and periodically Move the enemy unit, assuming you want to drag it around with you. Hiding a Unit (assuming you literally meant Hide and not something to do with it's Transparency) causes all sorts of unwanted side effects.

I imagine you want something like this (scroll down and view his Impale ultimate):
 
Last edited:
Level 30
Joined
Aug 29, 2012
Messages
1,382
As convenient as it would be, there's no way to retrieve an unit's model path (at least not in GUI) as a string, so if you want to go for a special effect you need another approach

It can be tedious depending on how many different unit types you have, but you could have a string variable with an array like this

  • Actions
    • Set VariableSet ModelPath[1] = Units\Human\Footman\Footman.mdx
    • Set VariableSet ModelPath[2] = Units\Human\Rifleman\Rifleman.mdx
    • Set VariableSet ModelPath[3] = Units\Human\Knight\Knight.mdx
Then assign a value to each unit type in the unit editor, I like using Point Value for instance (footman would be 1, rifleman 2, etc.)

Then create the SFX by retrieving the model path

  • Special Effect - Create a special effect attached to the weapon of (Triggering unit) using ModelPath[(Point-value of (Target unit of ability being cast))]
 
Level 1
Joined
Feb 14, 2025
Messages
6
I'd just Stun and periodically Move the enemy unit, assuming you want to drag it around with you. Hiding a Unit (assuming you literally meant Hide and not something to do with it's Transparency) causes all sorts of unwanted side effects.

I imagine you want something like this (scroll down and view his Impale ultimate):
Similar. I'm making a scorpion boss who'll be fighting heroes in an arena, the impale just needs to stick them on the stinger and keep them there for 10 seconds. So I need a way to make it look like a hero is stuck to the stinger and moves with it when the boss moves.
 
Level 1
Joined
Feb 14, 2025
Messages
6
As convenient as it would be, there's no way to retrieve an unit's model path (at least not in GUI) as a string, so if you want to go for a special effect you need another approach

It can be tedious depending on how many different unit types you have, but you could have a string variable with an array like this

  • Actions
    • Set VariableSet ModelPath[1] = Units\Human\Footman\Footman.mdx
    • Set VariableSet ModelPath[2] = Units\Human\Rifleman\Rifleman.mdx
    • Set VariableSet ModelPath[3] = Units\Human\Knight\Knight.mdx
Then assign a value to each unit type in the unit editor, I like using Point Value for instance (footman would be 1, rifleman 2, etc.)

Then create the SFX by retrieving the model path

  • Special Effect - Create a special effect attached to the weapon of (Triggering unit) using ModelPath[(Point-value of (Target unit of ability being cast))]
So I need to set all the potential units' model paths as a variable then make condition triggers for every single unit? I've never seen "Point-value of", does that automatically find the index that matches the unit targeted?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
So I need to set all the potential units' model paths as a variable then make condition triggers for every single unit? I've never seen "Point-value of", does that automatically find the index that matches the unit targeted?
"Point-value" is some generic data that you can attach to a Unit, I think it's meant to be used with the Score system that you see at the end of Melee matches. But you can repurpose it for anything, such as a unique identifier for your Unit-Type. In this case it'd be representing an [index] of an Array variable. You can also use something like Custom Value (triggered data), or better yet make use of a Unit Indexer system.

Anyway, it's important to understand how all of this works. This is your database of Model Paths:
  • Set VariableSet ModelPath[1] = Units\Human\Footman\Footman.mdx
  • Set VariableSet ModelPath[2] = Units\Human\Rifleman\Rifleman.mdx
  • Set VariableSet ModelPath[3] = Units\Human\Knight\Knight.mdx
Note the number in the brackets -> [#]. This is the Index of your Array Variable. A Footman is mapped to the index [1]. A Rifleman is mapped to [2]. A Knight is mapped to [3].

So if you used Impale on a Footman you would get the (point) value 1 from the Footman, plug that into your database -> ModelPath[1], and get the appropriate model path in return -> Units\Human\Footman\Footman.mdx. If every single Unit-Type has their own unique [index] and a ModelPath[] to go with it, you can make Impale work on them with just a couple Actions. This rids the need of a huge chain of If Then Else statements -> "Did you impale a footman? Did you impale a grunt? Did you impale a chicken?" "Repeat for every single Unit-Type".

But this assumes that your Unit has actually been assigned this value beforehand, for example:
  • Events
    • Unit - A unit Enters (playable map area)
  • Conditions
    • (Unit-type of (Triggering unit)) Equal to Footman
  • Actions
    • Unit - Set Point Value of (Triggering unit) to 1
However, in the case of Point Value you can actually define it in the Object Editor, saving you the above hassle.

I personally avoid Point Value because there's more flexible and straightforward alternatives, ie: A Hashtable using Unit-Type Ids as Parent keys. But the alternatives require a bit more effort and are somewhat more technical, so Point Value can get the job if need be.
 
Last edited:
Level 45
Joined
Feb 27, 2007
Messages
5,578
Seems considerably easier to me to use an actual unit instead of a special effect. Since you know the target you can get its unit-type, create another of that type for a neutral player, pause or stun that unit (invisibly if desired), give it locust, and change its teamcolor to match the original. At that point you can do anything you'd want to do with SFX.
 
Level 1
Joined
Feb 14, 2025
Messages
6
Seems considerably easier to me to use an actual unit instead of a special effect. Since you know the target you can get its unit-type, create another of that type for a neutral player, pause or stun that unit (invisibly if desired), give it locust, and change its teamcolor to match the original. At that point you can do anything you'd want to do with SFX.
I had this idea myself but was unable to find a way to add locust to a unit created by a trigger. It's weirdly absent from the GUI list.

I think it's possible with JASS but I'm not confident in creating any kind of code. Even replacing small parts of data within code to copy someone else.
 
Last edited:
Level 1
Joined
Feb 14, 2025
Messages
6
"Point-value" is some generic data that you can attach to a Unit, I think it's meant to be used with the Score system that you see at the end of Melee matches. But you can repurpose it for anything, such as a unique identifier for your Unit-Type. In this case it'd be representing an [index] of an Array variable. You can also use something like Custom Value (triggered data), or better yet make use of a Unit Indexer system.

Anyway, it's important to understand how all of this works. This is your database of Model Paths:
  • Set VariableSet ModelPath[1] = Units\Human\Footman\Footman.mdx
  • Set VariableSet ModelPath[2] = Units\Human\Rifleman\Rifleman.mdx
  • Set VariableSet ModelPath[3] = Units\Human\Knight\Knight.mdx
Note the number in the brackets -> [#]. This is the Index of your Array Variable. A Footman is mapped to the index [1]. A Rifleman is mapped to [2]. A Knight is mapped to [3].

So if you used Impale on a Footman you would get the (point) value 1 from the Footman, plug that into your database -> ModelPath[1], and get the appropriate model path in return -> Units\Human\Footman\Footman.mdx. If every single Unit-Type has their own unique [index] and a ModelPath[] to go with it, you can make Impale work on them with just a couple Actions. This rids the need of a huge chain of If Then Else statements -> "Did you impale a footman? Did you impale a grunt? Did you impale a chicken?" "Repeat for every single Unit-Type".

But this assumes that your Unit has actually been assigned this value beforehand, for example:
  • Events
    • Unit - A unit Enters (playable map area)
  • Conditions
    • (Unit-type of (Triggering unit)) Equal to Footman
  • Actions
    • Unit - Set Point Value of (Triggering unit) to 1
However, in the case of Point Value you can actually define it in the Object Editor, saving you the above hassle.

I personally avoid Point Value because there's more flexible and straightforward alternatives, ie: A Hashtable using Unit-Type Ids as Parent keys. But the alternatives require a bit more effort and are somewhat more technical, so Point Value can get the job if need be.
Is a hash table as easy as saying (Hash table of unit(footman)) which I set as 1, same as point value?

Sorry, if I had an example of how to set 3 units' IDs in a hash table and then use them in the trigger I should be able to apply that same method to the other 50 or so. Would you be able to give me 3 examples of the method? (just so I can be certain what changes and what stays the same between units)



Edit: Nvm I've just realised a problem with this idea. My map is basically a melee map but with some elaborate creep camps, creep settlements, and some custom heroes. But outside of that it's supposed to be a regular VS map where you can use reforged graphics and skins. So if I set the archmage unit model as 1 in an array (only heroes can enter the arena with the Scorpion) and then someone using the Jaina skin gets impaled, the special effect will be a regular archmage.

I'll either have to drag the unit around or scrap the idea. Probably better to just give them a stunning poison or something.
 
Last edited:

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Is a hash table as easy as saying (Hash table of unit(footman)) which I set as 1, same as point value?

Sorry, if I had an example of how to set 3 units' IDs in a hash table and then use them in the trigger I should be able to apply that same method to the other 50 or so. Would you be able to give me 3 examples of the method? (just so I can be certain what changes and what stays the same between units)
A Hashtable is basically an Array with an extra [index]. Also, known as a 2D array.

The first thing you need to understand is the concept of a Handle Id. In Warcraft 3 (and basically any game), each Object has a unique Integer Id that represents it. This is a way for the program to distinguish things apart, you can think of it like a phone number, a state id, a ssn, etc. In this case it's often a long Integer like 1249358447.

A normal Array, which is what was being used for ModelPath, has a limitation where it can only use an index ranging from [0] to [32768]. This is an efficiency thing and is limited in order to preserve memory since a computer would struggle to store Arrays with huge ranges. Although it doesn't really apply to modern hardware but Warcraft 3 is 20 years old and has limitations related to that era. This is why we rely on things like Unit Indexing and Point-Values since we can control those and keep them within the bounds of the Array.

Anyway, with that limitation in mind it means that we cannot plug a Handle Id inside of an Array [index], which is a shame because it'd be great to be able to do something like this:
  • Events
    • Unit - A unit Acquires an Item
  • Conditions
    • (Item-type of (Item being manipulated) Equal to Mage's Staff
  • Actions
    • Set Variable Spell_Power[(Hero manipulating item)] = 100
^ So when a Hero acquires an Item we increase their "Spell Power" stat by 100. We use the Unit directly as the [index], which would actually be it's Handle Id. Unfortunately, that's not actually possible with a standard Array...

Fortunately, Hashtables solve this problem! Here's the same trigger using this new technique:
  • Events
    • Unit - A unit Acquires an Item
  • Conditions
    • (Item-type of (Item being manipulated) Equal to Mage's Staff
  • Actions
    • Hashtable - Save 100 as 1 of (Key (Hero manipulating item)) in MyHashtable
^ This does the same thing as the above trigger but we've now introduced a new [index] and can use our Unit as one of the two [indexes].

This effectively does the following:
  • Actions
    • Set Variable MyHashtable[(Hero manipulating item)][1] = 100
You can change the number 1 to ANY Integer that you want, it basically acts like a unique category. In this case I am using 1 to represent Spell Power. But if I wanted even more custom stats then I would want to use a different number for them.

Here's a more advanced example with some extra variables to help with the clarity (they're optional). Let's introduce Block_Chance as another custom stat and let's actually increase the values rather than overwrite them:
  • Events
    • Unit - A unit Acquires an Item
  • Conditions
    • (Item-type of (Item being manipulated) Equal to Mage's Shield
  • Actions
    • -------- Let's get an efficient reference to our unit's Handle --------
    • Set Variable TempHandle = (Hero manipulating item)
    • -------- --------
    • -------- Let's load our unit's Spell Power and Block Chance from our Hashtable --------
    • Set Variable TempSpellPower = (Load 1 of TempHandle from MyHashtable)
    • Set Variable TempBlockChance = (Load 2 of TempHandle from MyHashtable)
    • -------- --------
    • -------- Let's increase the unit's Spell Power by 100 and Block Chance by 50 --------
    • Set Variable TempSpellPower = (TempSpellPower + 100)
    • Set Variable TempBlockChance = (TempBlockChance + 50)
    • -------- --------
    • -------- Let's save these values, updating them in our Hashtable --------
    • Hashtable - Save TempSpellPower as 1 of TempHandle in MyHashtable)
    • Hashtable - Save TempBlockChance as 2 of TempHandle in MyHashtable)
So we've effectively Loaded data from our Hashtable, increased it, then Saved it, overwriting their previous values.
"Loading" and "Saving" is just another way of saying "Getting" and "Setting" data, which you've been doing all of this time with normal Variables.

Remember, you can Load this data whenever you want, so it wouldn't be difficult to Load these custom stats in say a trigger that uses Spell Power to increase your damage dealt or a trigger that handles Block Chance to reduce damage taken. Also, a Hashtable can Save any TYPE of data, it doesn't just have to be Integers. So Block Chance could be a Real like 50.00%, etc.

Variable Types used here:
TempHandle = Handle
TempSpellPower = Integer
TempBlockChance = Integer

Lastly, but extremely important, you have to actually create and store your Hashtables manually:
  • Events
    • Map initialization
  • Conditions
  • Actions
    • Hashtable - Create a hashtable
    • Set Variable MyHashtable = (Last created hashtable)
Do this before you try to use it! A Hashtable can contain a massive amount of data so this creation is necessary (again, efficiency thing). You're limited to 255 Hashtables in a single map, however, that's basically impossible to reach and you're using them wrong if you how somehow get even close to that number.

Edit: Nvm I've just realised a problem with this idea. My map is basically a melee map but with some elaborate creep camps, creep settlements, and some custom heroes. But outside of that it's supposed to be a regular VS map where you can use reforged graphics and skins. So if I set the archmage unit model as 1 in an array (only heroes can enter the arena with the Scorpion) and then someone using the Jaina skin gets impaled, the special effect will be a regular archmage.

I'll either have to drag the unit around or scrap the idea. Probably better to just give them a stunning poison or something.
Like Pyro and I said, it's easier to Move the Unit rather than a Special Effect. You're just creating extra steps with the Special Effect.

If you're on the latest patch I can show you how to do it, although I'm sure there's a "Flaming Lasso" (DotA ability that drags a unit) on Hive which you could use as a starting point.
 
Last edited:
Level 1
Joined
Feb 14, 2025
Messages
6
I think I'm on the latest patch, I only downloaded warcraft about a month ago. If it's do-able in GUI I'd love to learn how, thank you.

If flaming lasso needs JASS I wouldn't be able to tweak it to fit the scenario because I'm not at all competent with anything outside of basic GUI.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
I think I'm on the latest patch, I only downloaded warcraft about a month ago. If it's do-able in GUI I'd love to learn how, thank you.
As long as you're playing on the official BNET app then you'll be on the latest patch. Some people choose to use the older patches to avoid the pitfalls of Reforged - which often breaks things more than it fixes them. I personally use the latest patch as I can't be bothered with managing different versions and I like the new toys.

If flaming lasso needs JASS I wouldn't be able to tweak it to fit the scenario because I'm not at all competent with anything outside of basic GUI.
It can be done in GUI. GUI uses JASS (or Lua) so there's not really any limitations there. You're simply using an interface that hides the code from you. Whenever you use the Custom Script action you're actually writing JASS directly, instead of indirectly with the interface. The reason that Custom Script even works is because you're technically writing JASS code already.

Anyway, I'm in no rush to make this since it's a decent sized project. If I get bored enough I'll likely take a whack at it, though.

Also, I updated my last post with some info about Hashtables, you may have missed it because you replied while I was editing it.
 
Last edited:
Top