• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Trigger] [SOLVED] Trying to make SC2 Oracle's Revelation

Level 6
Joined
Sep 10, 2022
Messages
78
Hello, I am here with a new question. I am trying to make something similar to the Oracle Revelation spell from Starcraft 2.

How does Revelation in SC2 actually work:
1. Any caster with the ability just chooses an area (in my case it is the point), and then clicks to perform the spell.
2. You gave a few seconds of vision on the area (or area around the point), if there are any units or buildings, they will be highlighted and stay revealed for some seconds.

What I did:

1. Created Revelation(AoE) spell based on Alliance Magic Tower Scout ability (or based on Goblin neutral building, does not matter) to just have an opportunity to scout an area. Then reduced the casting range from default 99999.00 to my 1400 (it does not matter). Reduced the area of spell effect and removed the scout effect in "Stats: Effects".

2. Created a single spell "Revelation" based on fairy fire ability to further give it to DummyCaster.

3. Wrote a trigger that causes Dummy to cast a custom fairy fire on all units within range of the spell target point.

  • Revelation AoE
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Revelation (AoE)
    • Actions
      • Set VariableSet spell_target_area_2 = (Target point of ability being cast)
      • Set VariableSet spell_target_units = (Units within 600.00 of spell_target_area_2.)
      • Unit Group - Pick every unit in spell_target_units and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is Magic Immune) Equal to Нет
              • ((Picked unit) is alive) Equal to Да
            • Then - Actions
              • Unit - Create 1 Dummy for (Triggering player) at spell_target_area_2 facing Default building facing degrees
              • Unit - Add a 2.00 second Generic expiration timer to (Last created unit)
              • Unit - Add Revelation (single target) to (Last created unit)
              • Unit - Order (Last created unit) to Night Elf Druid Of The Talon - Faerie Fire (Picked unit)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_spell_target_area_2)
      • Custom script: call DestroyGroup(udg_spell_target_units)
It seems the ability works correctly -BUT- the custom fairy fire will be cast only in case an Area of the Spell is explored/scouted (don't know how to designate it properly but I mean when you have a vision on area), moreover, fairy fire is not cast on units, even if you previously scouted with Revelation AoE, which gives vision...
I don't really understand what the problem is, but I have a suspicion that Dummy Unit can't cast the custom fairy fire because of the spell itself -like it does not work on unexplored territory.

It would be appreciated if you could comment on the situation as well as my script (I am still new to triggers and jass), and suggest how I may fix the situation.
 
Last edited:
An approach I can think of at the top of my head is to have one dummy cast the dust of appearance ability in the target location, which targets units and buildings.

To intercept the order for dust of appearance, you can use the following trigger:

  • Events
    • Unit - A unit is issued an Order
  • Conditions
  • Actions
    • Custom Script: call BJDebugMsg("Issued order id: " + I2S(GetIssuedOrderId()))
 
Level 20
Joined
Feb 27, 2019
Messages
592
Hi. The reason Faerie Fire cant be cast is as you suspected. A target unit spell cant be cast on a unit that isnt considered visible to the casting player. Using that logic the units can be made considered visible to the player for the instant required to cast the spell.
  • Unit - Grant shared vision of (Picked unit) to Player 1 (Red)
  • Unit - Order (Last created unit) to Night Elf Druid Of The Talon - Faerie Fire (Picked unit)
  • Unit - Deny shared vision of (Picked unit) to Player 1 (Red)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
Also, you can clean this up to use a single Dummy unit. Here's the final trigger using Duckfarter's suggestion:
  • Revelation AoE
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Revelation (AoE)
    • Actions
      • Set VariableSet spell_player = (Triggering player)
      • Set VariableSet spell_target_area_2 = (Target point of ability being cast)
      • Unit - Create 1 Dummy for spell_player at spell_target_area_2 facing Default building facing degrees
      • Set VariableSet spell_dummy = (Last created unit)
      • Unit - Add a 0.20 second Generic expiration timer to spell_dummy
      • Unit - Add Revelation (single target) to spell_dummy
      • Set VariableSet spell_target_units = (Units within 600.00 of spell_target_area_2.)
      • Custom script: call RemoveLocation(udg_spell_target_area_2)
      • Unit Group - Pick every unit in spell_target_units and do (Actions)
        • Loop - Actions
          • Set VariableSet spell_target = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (spell_target is Magic Immune) Equal to Нет
              • (spell_target is alive) Equal to Да
            • Then - Actions
              • Unit - Grant shared vision of spell_target to spell_player
              • Unit - Order spell_dummy to Night Elf Druid Of The Talon - Faerie Fire spell_target
              • Unit - Deny shared vision of spell_target to spell_player
            • Else - Actions
      • Custom script: call DestroyGroup(udg_spell_target_units)
Note that this single Dummy unit will only work if you set it up properly. Here's how:

Step 1: Copy and paste the Locust unit. The most important aspect of this unit is it's Locust ability.
Step 2: Change it's Model/Shadow to None so it's completely "invisible".
Step 3: Change it's Attacks Enabled to None, Movement Type to None, and Speed Base to 0.

With these settings the Dummy unit can cast any number of abilities (assuming they aren't channeled) any number of times within the same game frame. Also, make sure the Dummy Faerie Fire ability has 0 cooldown, 0 mana cost, 999999 cast range, etc... It should be able to cast it anywhere at any time.
 
Last edited:
Level 6
Joined
Sep 10, 2022
Messages
78
Hi. The reason Faerie Fire cant be cast is as you suspected. A target unit spell cant be cast on a unit that isnt considered visible to the casting player. Using that logic the units can be made considered visible to the player for the instant required to cast the spell.
  • Unit - Grant shared vision of (Picked unit) to Player 1 (Red)
  • Unit - Order (Last created unit) to Night Elf Druid Of The Talon - Faerie Fire (Picked unit)
  • Unit - Deny shared vision of (Picked unit) to Player 1 (Red)

Seems to be a sensible solution))

Also, you can clean this up to use a single Dummy unit. Here's the final trigger using Duckfarter's suggestion:
  • Revelation AoE
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Revelation (AoE)
    • Actions
      • Set VariableSet spell_player = (Triggering player)
      • Set VariableSet spell_target_area_2 = (Target point of ability being cast)
      • Unit - Create 1 Dummy for spell_player at spell_target_area_2 facing Default building facing degrees
      • Set VariableSet spell_dummy = (Last created unit)
      • Unit - Add a 0.20 second Generic expiration timer to spell_dummy
      • Unit - Add Revelation (single target) to spell_dummy
      • Set VariableSet spell_target_units = (Units within 600.00 of spell_target_area_2.)
      • Custom script: call RemoveLocation(udg_spell_target_area_2)
      • Unit Group - Pick every unit in spell_target_units and do (Actions)
        • Loop - Actions
          • Set VariableSet spell_target = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (spell_target is Magic Immune) Equal to Нет
              • (spell_target is alive) Equal to Да
            • Then - Actions
              • Unit - Grant shared vision of spell_target to spell_player
              • Unit - Order spell_dummy to Night Elf Druid Of The Talon - Faerie Fire spell_target
              • Unit - Deny shared vision of spell_target to spell_player
            • Else - Actions
      • Custom script: call DestroyGroup(udg_spell_target_units)
Note that this single Dummy unit will only work if you set it up properly. Here's how:

Step 1: Copy and paste the Locust unit.
Step 2: Change it's Model/Shadow to None so it's completely "invisible".
Step 3: Change it's Attacks Enabled to None, Movement Type to None, and Speed Base to 0.

With these settings the Dummy unit can cast any number of abilities (assuming they aren't channeled) any number of times within the same game frame. Also, make sure the Dummy Faerie Fire ability has 0 cooldown, 0 mana cost, 999999 cast range, etc... It should be able to cast it anywhere at any time.

I rewrote your version of the script and created a new dummy unit just in case. And it all WORKS as well as possible. Now all units are highlighted with custom fairy fire.
I still do not know what was the problem with my version of the script, so to clarify something I want to ask some questions:

1. Why did you set the expiration timer to value "0.2"? It seemed to me too low, but I did not change it.
2. Why did you rearrange the creation of the dummy unit earlier?
3. I can see a lot of variables so should I regard my method with "Last Created" and "Picked" as less reliable?
4. If I understand correctly, all variables that are used are considered global. I heard that global variables perform too slowly compared to local or hash tables, but there will be no problem in our case...

UPD: It seems the problem was in my old dummy unit. Shame on me, but I thought I created it correctly. Previously I used this guide to create dummies:

I followed all instructions attentively and patiently when I did the mentioned guide. Now it will be treated as not untrustworthy as it was.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
1. Faerie Fire doesn't use a Missile so it's going to apply it's effects almost immediately. That's why the Expiration Timer can be super short, everything is going to happen within the same game frame or 1 frame later.

2. I'm creating a single Dummy unit. You were creating X Dummy units, where X was the number of units in your Unit Group. My method is far more efficient and has the same exact result. Remember, these Loop - Actions happen once per (Picked unit):
  • Unit Group - Pick every unit in spell_target_units and do (Actions)
    • Loop - Actions
3. Yes, the additional variables can help prevent an issue where the values of the Event Responses get changed from outside sources. A lot of Event Responses are considered global. With that in mind, your global variables are also global so they suffer from the same issue. It's best to try and use unique variables whenever possible or local variables (not easy to do in GUI) since they avoid this issue entirely. If you know what you're doing then you can reuse certain global variables but you really need to stay on top of it and have a good understanding.

4. They don't perform "too slowly" but they are objectively slower. The speed of how quickly the game can access a variable is not something to really worry about. Game performance issues come from things like high Unit count, lots of Special Effects being rendered on the screen, excessive memory leaks, heavy Events related to combat (and a lot of combat going on), etc...

A lot of the information is outdated or was just wrong from the start. My dummy unit is the ideal setup, HOWEVER, it does have one flaw which is that it can't be used as a Missile in a custom triggered missile system due to it's Movement Type/Speed. That being said, we now have Special Effects that can be manipulated freely which replace this outdated approach.

If you're looking for up to date information, I've been posting on here the last few years and have touched on most topics. The majority of my posts should have the latest and best solutions (to my knowledge). I've basically documented my learning experience starting in 2019, which is when most of the new Reforged stuff was released. That being said, I've definitely been wrong before so don't take my word as law.
 
Last edited:
Level 6
Joined
Sep 10, 2022
Messages
78
1. Faerie Fire doesn't use a Missile so it's going to apply it's effects almost immediately. That's why the Expiration Timer can be super short, everything is going to happen within the same game frame or 1 frame later.

2. I'm creating a single Dummy unit. You were creating X Dummy units, where X was the number of units in your Unit Group. My method is far more efficient and has the same exact result. Remember, these Loop - Actions happen once per (Picked unit):
  • Unit Group - Pick every unit in spell_target_units and do (Actions)
    • Loop - Actions
3. Yes, the additional variables can help prevent issues where the values of the Event Responses get changed from outside sources. A lot of Event Responses are considered global. With that in mind, your global variables are also global so they suffer from the same issue. It's best to try and use unique variables whenever possible or local variables (not easy to do in GUI) since they avoid this issue entirely. If you know what you're doing then you can reuse certain global variables but you really need to stay on top of it and have a good understanding.

4. They don't perform "too slowly" but they are objectively slower. The speed of how quickly the game can access a variable is not something to really worry about. Game performance hits come from things like high Unit count, lots of Special Effects being rendered on the screen, excessive memory leaks, heavy Events related to combat (and a lot of combat going on), etc...

A lot of the information is outdated or was just wrong from the start. My dummy unit is the ideal setup, HOWEVER, it does have one flaw which is that it can't be used as a Missile in a custom triggered missile system due to it's Movement Type/Speed. That being said, we now have Special Effects that can be manipulated which replace this outdated approach.

If you're looking for up to date information, I've been posting on here the last few years and have touched on most topics. The majority of my posts should have the latest and best solutions (to my knowledge). I've basically documented my learning experience starting in 2019, which is when most of the new Reforged stuff was released. That being said, I've definitely been wrong before so don't take my word as law.

1. Understood.
2. Yes, apparently I just now noticed that every time I created a dummy unit, in fact, I created it in a for each loop...
3. It's a pity that we can't use local variables in GUI, so I will focus more on learning JASS.
4. Understood.

Documenting Experience since 2019? Are you talking about just your posts (I saw some earlier, they helped a lot too) or something like full documentation (except Hive Tutorials forums)?

Anyway, thank you all guys for helping me.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
Yes, I just mean my posts. I usually google search "Hiveworkshop topic uncle" to find information about a topic since I've probably touched on it at some point. Also, note the date of the threads you're viewing, a post from 2007 is probably going to be wrong.

We can use local variables in GUI, just not easily.
  • Actions
    • Custom script: local unit u = GetTriggerUnit()
There's also the shadowing technique -> local udg_
This technique comes in handy from time to time, just remember that the shadowed variable cannot be referenced in a Conditions block.

Jass is nice, but Lua is better. However, since Jass is older it has a lot more information and a lot more resources dedicated to it.

I personally use C# which compiles to Lua via this WCSharp but I wouldn't recommend this until you're comfortable with coding since it forces you to code ALL of your game logic. I know some people use TypeScript in a similar fashion which seems like a nice upgrade from Lua.
Also, Lua is a weakly typed language, which means that it does not check the types of data and variables that you use. This can lead to unexpected and hard-to-find errors, bugs, etc.
 
Last edited:
Level 6
Joined
Sep 10, 2022
Messages
78
Yes, I just mean my posts. I usually google search "Hiveworkshop topic uncle" to find information about a topic since I've probably touched on it at some point. Also, note the date of the threads you're viewing, a post from 2007 is probably going to be wrong.

We can use local variables in GUI, just not easily.
  • Actions
    • Custom script: local unit u = GetTriggerUnit()
There's also the shadowing technique -> local udg_
This technique comes in handy from time to time, just remember that the shadowed variable cannot be referenced in a Conditions block.

Jass is nice, but Lua is better. However, since Jass is older it has a lot more information and a lot more resources dedicated to it.

I personally use C# which compiles to Lua via this WCSharp but I wouldn't recommend this until you're comfortable with coding since it forces you to code ALL of your game logic. I know some people use TypeScript in a similar fashion which seems like a nice upgrade from Lua.
Also, Lua is a weakly typed language, which means that it does not check the types of data and variables that you use. This can lead to unexpected and hard-to-find errors, bugs, etc.
I don't think Lua has fewer guides than JASS, the difference is that Lua is still alive. There are more internet searches for Lua guides and YouTube videos, while I only saw guides on JASS on specific websites (such as Hive). I can't say about the popularity of the Lua, cause I know only one other game that uses it - it is Battle for Wesnoth - and as far as I know JASS is used only in Warcraft and Starcraft 2.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
I meant resources on Hive which are related to Warcraft 3:
Jass has been around far longer than Lua in this regard, so there's many more systems/libraries available to you which will make your life easier. I should've mentioned that you can only use one language or the other, so that's why this could be a game changer for you.

Both Jass and Lua are going to be using the same Warcraft 3 API so really the only thing you need to learn from outside sources like Youtube/official Documentation is the syntax rules. In that regard I think Lua has an easier to use syntax although since it's weakly typed you will suffer from a lack of debugging tools. Don't be surprised when you waste hours trying to debug some mystery issue and it turns out it was just that you mistook a lower case l for an upper case i in one of your variable names.
 
Top