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

[Solved] Camouflage Ability (Weak Invisibility) - MUI

Status
Not open for further replies.
Level 4
Joined
Sep 25, 2018
Messages
81
"Camouflaged units are temporarily revealed when an enemy unit is within a certain range of the camouflaged unit."

Basically, I am currently testing an ability which grants invisibility to a unit for 12 seconds. When the casting unit (CU) casts Ambush, CU is granted a buff for 12 seconds. While CU has this buff, he is given invisibility (the buff and the invisibility are two separate things in this case). If CU attacks or casts a spell, the Ambush buff is lost and CU is no longer able to go invisible. If an enemy unit is within 300 range of CU, CU loses the ability to go invisible, but the Ambush buff is not removed. This means that when the enemy unit is no long within 300 range of CU, CU gains the ability to turn invisible again.

  • AmbushCast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Ambush (Assassin)
    • Actions
      • -------- Store casting unit in Hashtable --------
      • Hashtable - Save Handle Of(Triggering unit) as (Key A_UnitCaster.) of (Key A_Handle.) in A_HastTable.
      • -------- Add invisibility to casting unit --------
      • Unit - Add Permanent Invisibility to (Triggering unit)
      • Trigger - Turn on AmbushDurationEnd <gen>
  • AmbushDurationEnd
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Load (Key A_UnitCaster.) of (Key A_Handle.) in A_HastTable.) has buff Berserk) Equal to False
        • Then - Actions
          • Unit - Remove Permanent Invisibility from (Load (Key A_UnitCaster.) of (Key A_Handle.) in A_HastTable.)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Number of units in (Units within 300.00 of (Position of (Load (Key A_UnitCaster.) of (Key A_Handle.) in A_HastTable.)) matching (((Matching unit) belongs to an enemy of (Owner of (Load (Key A_UnitCaster.) of (Key A_Handle.) in A_HastTable.)).) Equal to True) Greater than or equal to 1
            • Then - Actions
              • Unit - Remove Permanent Invisibility from (Load (Key A_UnitCaster.) of (Key A_Handle.) in A_HastTable.)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Number of units in (Units within 300.00 of (Position of (Load (Key A_UnitCaster.) of (Key A_Handle.) in A_HastTable.)) matching (((Matching unit) belongs to an enemy of (Owner of (Load (Key A_UnitCaster.) of (Key A_Handle.) in A_HastTable.)).) Equal to True) Less than 1
                  • (Level of Permanent Invisibility for (Load (Key A_UnitCaster.) of (Key A_Handle.) in A_HastTable.)) Not equal to 1
                • Then - Actions
                  • Unit - Add Permanent Invisibility to (Load (Key A_UnitCaster.) of (Key A_Handle.) in A_HastTable.)
                • Else - Actions
Just wondering if anyone sees any glaring issues with how I have put this trigger together. Any tips/advice would be greatly appreciated. Also still wondering how to remove the Ambush buff when CU casts a spell/attacks a target.

Edit: Issue I have currently is if I have two units who have cast this ability, only the second unit has the Permanent Invisibility ability added and removed (depending on whether there is an enemy unit nearby).
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,565
Issues:
Your Hashtable is done incorrectly. What is A_UnitCaster and A_Handle? They're never assigned as far as I can tell.
You never turn off the AmbushDurationEnd trigger.
You're leaking Points and Unit Groups.
In the AmbushDurationEnd trigger you're loading the same unit over and over again. You're never changing A_UnitCaster so it's always going to be the same unit.

I would say scrap the Hashtable as it's extremely unnecessary for an ability like this. Instead use a Unit Group and the Pick every Unit function.
Example:
  • Ambush Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Ambush
    • Actions
      • -------- Add Permanent Invisibility --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Ambush Invisibility for (Triggering unit)) Equal to 0
        • Then - Actions
          • Unit - Add Ambush Invisibility to (Triggering unit)
        • Else - Actions
      • -------- - --------
      • -------- Add to AmbushGroup --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Triggering unit) is in AmbushGroup.) Equal to False
        • Then - Actions
          • Unit Group - Add (Triggering unit) to AmbushGroup
        • Else - Actions
      • -------- - --------
      • -------- Turn On Ambush Timer --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ambush Timer <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Ambush Timer <gen>
        • Else - Actions
  • Ambush Timer
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in AmbushGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet TempUnit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (TempUnit has buff Ambush ) Equal to True
            • Then - Actions
              • -------- First we set our Boolean AmbushEnemyFound = False. Then we look for nearby enemies. If we find an enemy then we set this Boolean to True. --------
              • Set VariableSet AmbushEnemyFound = False
              • -------- - --------
              • -------- Always set a Point like this so you can remove it later to avoid Memory Leaks. --------
              • Set VariableSet TempPoint = (Position of TempUnit)
              • -------- - --------
              • -------- Remove Ambush Invisibility - If Enemies Nearby --------
              • Custom script: set bj_wantDestroyGroup = true
              • Unit Group - Pick every unit in (Units within 300.00 of TempPoint.) and do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • AmbushEnemyFound Equal to False
                      • ((Picked unit) belongs to an enemy of (Owner of TempUnit).) Equal to True
                      • ((Picked unit) is alive) Equal to True
                    • Then - Actions
                      • Set VariableSet AmbushEnemyFound = True
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Level of Ambush Invisibility for TempUnit) Equal to 1
                        • Then - Actions
                          • Unit - Remove Ambush Invisibility from TempUnit
                        • Else - Actions
                    • Else - Actions
              • -------- - --------
              • -------- Add Ambush Invisibility - If No Nearby Enemies --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AmbushEnemyFound Equal to False
                  • (Level of Ambush Invisibility for TempUnit) Equal to 0
                • Then - Actions
                  • Unit - Add Ambush Invisibility to TempUnit
                • Else - Actions
              • -------- - --------
              • -------- Clean Up Memory Leak --------
              • Custom script: call RemoveLocation (udg_TempPoint)
            • Else - Actions
              • Unit - Remove Ambush Invisibility from TempUnit
              • Unit Group - Remove TempUnit from AmbushGroup.
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in AmbushGroup) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
  • Ambush Remove Ability
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Not equal to Ambush
      • ((Triggering unit) is in AmbushGroup.) Equal to True
    • Actions
      • Unit - Remove Ambush buff from (Triggering unit)
      • Unit - Remove Ambush Invisibility from (Triggering unit)
      • Unit Group - Remove (Triggering unit) from AmbushGroup.
  • Ambush Remove Attack
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • ((Attacking unit) is in AmbushGroup.) Equal to True
    • Actions
      • Unit - Remove Ambush buff from (Attacking unit)
      • Unit - Remove Ambush Invisibility from (Attacking unit)
      • Unit Group - Remove (Attacking unit) from AmbushGroup.
So when the unit casts Ambush it's added to the AmbushGroup and we add Permanent Invisibility to it. Then we turn on our Timer if it's off.

Timer: Every 0.10 seconds we pick each unit in AmbushGroup and check a few things:

1. Check if the picked unit has the Ambush buff.
2. Check if there are any enemies near our picked unit.

If #1 comes back False and our Unit does NOT have the buff then we know the ability has ended and we can remove the unit from AmbushGroup along with the Permanent Invisibility ability.

If #1 comes back True then we move on to #2.

For #2, first we set the Boolean AmbushEnemyFound to False since no enemy has been found yet. Then we look for nearby enemies. To do so we pick every enemy unit within 300 range of our Ambush Unit, and if at least 1 eligible enemy is found then we set AmbushEnemyFound = True and remove Permanent Invisibility.

But what if no enemies are found? Remember, we set AmbushEnemyFound to False at the start of our trigger, so if no enemies are found then it will still be False. So if it's still False then we check to see if our Ambush Unit has Permanent Invisibility. If it doesn't because it was previously removed then we add it back.

Finally we clean up our memory leaks and check to see if AmbushGroup is Empty. If it is Empty then that means that no units on the map have the Ambush buff and we can safely turn off the timer.
 

Attachments

  • Ambush Uncle 1.w3m
    20.2 KB · Views: 37
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,023
There is a ‘unit - remove specific buff’ action; since you are checking for this buff in your periodic trigger all you need to do is to remove it when the spell should end and it will all be cleaned up automatically. This in conjunction with a damage detection system will allow you to remove the buff when attacking an enemy or casting an ability in stealth. It's not quite as straightforward as just checking that the damaging unit has the Ambush buff if you're planning to also implement Twitch's poison DoT effect. This DoT does not break stealth as it's not a direct attack, so you must make sure only actual attacks break the stealth. You can't use the "unit is attacked" event because that fires before the attack happens so you can lose it without actually attacking.

  • Events
    • Unit - A unit starts the effect of an ability
  • Conditions
    • ((Triggering Unit) has buff Ambush) equal to True
  • Actions
    • Unit - Remove Ambush from (Triggering Unit)
  • Events
    • Game - DamageEvent becomes equal to 1.00
  • Conditions
    • (DamageEventSource has buff Ambush) equal to True
    • Or - Any conditions are true
      • IsDamageMelee equal to True
      • IsDamageRanged equal to True
  • Actions
    • Unit - Remove Ambush from (DamageEventSource)
It might also be a good idea to change the caster's transparency (alpha) value on spell cast and back when the spell ends so that they still appear that they could be hidden when a unit is in range of it to disable the camouflage.
 
Level 4
Joined
Sep 25, 2018
Messages
81
To be honest, I think my initial implementation of this trigger is unnecessarily complicated.

Instead, I think it would be easier to just have a spell based on Wind Walk. When an enemy unit is within 300 range, either use the reveal unit trigger (not sure if the reveal unit trigger is ideal, don’t want them to be able to see the CU over cliffs and such), or add a unit with no vision range, and the true sight ability, and just have that follow CU until the enemy unit is no longer within the 300 range.

Edit: Then, obviously, using Wind Walk gives me the ability to kill two birds with one stone by having the effect completely removed when CU attacks and also allows me to add some type of “break invis” damage.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,565
Well, the map I made works great and is MUI with just the use of one Unit Group. That's just about as simple as you can get when it comes to MUI spells. To be honest the reveal/true sight stuff sounds even more complicated and less optimal than what I did.
 
Level 4
Joined
Sep 25, 2018
Messages
81
Well, the map I made works great and is MUI with just the use of one Unit Group. That's just about as simple as you can get when it comes to MUI spells. To be honest the reveal/true sight stuff sounds even more complicated and less optimal than what I did.
I tried it the other way and you were right. It was horribly more confusing.

Your method is probably the most efficient way.

Here is what it came to using Bribe's DDS

  • AmbushCast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Ambush (Assassin)
    • Actions
      • -------- Add Permanent Invisibility --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Camouflage (Dummy Buff) for (Triggering unit)) Equal to 0
        • Then - Actions
          • Unit - Add Camouflage (Dummy Buff) to (Triggering unit)
        • Else - Actions
      • -------- Add to Group --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Triggering unit) is in A_Group.) Equal to False
        • Then - Actions
          • Unit Group - Add (Triggering unit) to A_Group
        • Else - Actions
      • -------- Turn on AmbushTimer --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (AmbushTimer <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on AmbushTimer <gen>
        • Else - Actions
  • AmbushTimer
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in A_Group and do (Actions)
        • Loop - Actions
          • Set VariableSet A_TempUnit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (A_TempUnit has buff Ambush ) Equal to True
            • Then - Actions
              • Set VariableSet A_EnemyFound = False
              • Set VariableSet A_TempPoint = (Position of A_TempUnit)
              • Custom script: bj_wantDestroyGroup = true
              • Unit Group - Pick every unit in (Units within 450.00 of A_TempPoint.) and do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • A_EnemyFound Equal to False
                      • ((Picked unit) belongs to an enemy of (Owner of A_TempUnit).) Equal to True
                      • ((Picked unit) is alive) Equal to True
                    • Then - Actions
                      • Set VariableSet A_EnemyFound = True
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Level of Camouflage (Dummy Buff) for A_TempUnit) Equal to 1
                        • Then - Actions
                          • Unit - Remove Camouflage (Dummy Buff) from A_TempUnit
                        • Else - Actions
                    • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • A_EnemyFound Equal to False
                  • (Level of Camouflage (Dummy Buff) for A_TempUnit) Equal to 0
                • Then - Actions
                  • Unit - Add Camouflage (Dummy Buff) to A_TempUnit
                • Else - Actions
              • Custom script: RemoveLocation(udg_A_TempPoint)
            • Else - Actions
              • Unit - Remove Camouflage (Dummy Buff) from A_TempUnit
              • Unit Group - Remove A_TempUnit from A_Group.
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in A_Group) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
  • AmbushRemoveAbility
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Not equal to Ambush (Assassin)
      • ((Triggering unit) is in A_Group.) Equal to True
    • Actions
      • Unit - Remove Ambush buff from (Triggering unit)
      • Unit - Remove Camouflage (Dummy Buff) from (Triggering unit)
      • Unit Group - Remove (Triggering unit) from A_Group.
  • AmbushRemoveAttack
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (DamageEventSource is in A_Group.) Equal to True
    • Actions
      • Set VariableSet DamageEventAmount = (DamageEventAmount + 80.00)
      • Unit - Remove Ambush buff from DamageEventSource
      • Unit - Remove Camouflage (Dummy Buff) from DamageEventSource
      • Unit Group - Remove DamageEventSource from A_Group.
 
Level 39
Joined
Feb 27, 2007
Messages
5,023
Be aware that will trigger off of any damage done by the camouflaged unit regardless of whether it was an attack. Periodic damage or even damage caused by triggers included. There should be a boolean to check for if the damage was an attack.
 
Level 4
Joined
Sep 25, 2018
Messages
81
Be aware that will trigger off of any damage done by the camouflaged unit regardless of whether it was an attack. Periodic damage or even damage caused by triggers included. There should be a boolean to check for if the damage was an attack.
Oh yeah, good point! The annoying thing about using the Permanent Invisibility is that CU gets revealed as soon as it starts an auto attack. I suppose there is nothing I can really do about that.

Was trying to also add a part which will remove the invisibility from CU if the target is detected (e.g. towers/sentry wards). Would you suggest adding that in the AmbushTimer trigger, or have another separate trigger which does that?
 
Level 4
Joined
Sep 25, 2018
Messages
81
Set Permanent invisibility's fade time to 0 and it should never break.

Not too sure how you would go about checking if a unit is detected. Is their a condition for this?
Yes, it is in the Visibility section of Actions. Something a long the lines of ”unit visible by player.“
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,565
Ah, I see it now. Pretty neat.

Yeah, throw that into the AmbushTimer trigger. I uploaded a map with the trigger updated, I also optimized it so it doesn't run unnecessary things.
  • Ambush Timer
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in AmbushGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet TempUnit = (Picked unit)
          • Set VariableSet TempPlayer = (Owner of TempUnit)
          • -------- - --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (TempUnit has buff Ambush ) Equal to True
            • Then - Actions
              • -------- First we set our Boolean AmbushEnemyFound = False. Then we look for nearby enemies. If we find an enemy then we set this Boolean to True. --------
              • Set VariableSet AmbushEnemyFound = False
              • -------- - --------
              • -------- Is Unit Visible To Enemies --------
              • Set VariableSet TempPlayerGroup = (All enemies of TempPlayer.)
              • Player Group - Pick every player in TempPlayerGroup and do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (TempUnit is visible to (Picked player).) Equal to True
                    • Then - Actions
                      • Set VariableSet AmbushEnemyFound = True
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Level of Ambush Invisibility for TempUnit) Equal to 1
                        • Then - Actions
                          • Unit - Remove Ambush Invisibility from TempUnit
                        • Else - Actions
                    • Else - Actions
              • Custom script: call DestroyForce (udg_TempPlayerGroup)
              • -------- - --------
              • -------- If Unit Isn't Visible Then Look For Nearby Enemy Units --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AmbushEnemyFound Equal to False
                • Then - Actions
                  • -------- Always set a Point like this so you can remove it later to avoid Memory Leaks. --------
                  • Set VariableSet TempPoint = (Position of TempUnit)
                  • -------- - --------
                  • -------- Remove Ambush Invisibility - If Enemies Nearby --------
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within 300.00 of TempPoint.) and do (Actions)
                    • Loop - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • AmbushEnemyFound Equal to False
                          • ((Picked unit) belongs to an enemy of (Owner of TempUnit).) Equal to True
                          • ((Picked unit) is alive) Equal to True
                        • Then - Actions
                          • Set VariableSet AmbushEnemyFound = True
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (Level of Ambush Invisibility for TempUnit) Equal to 1
                            • Then - Actions
                              • Unit - Remove Ambush Invisibility from TempUnit
                            • Else - Actions
                        • Else - Actions
                  • -------- - --------
                  • -------- Clean Up Memory Leak --------
                  • Custom script: call RemoveLocation (udg_TempPoint)
                • Else - Actions
              • -------- - --------
              • -------- Add Ambush Invisibility If EnemyFound = False --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AmbushEnemyFound Equal to False
                  • (Level of Ambush Invisibility for TempUnit) Equal to 0
                • Then - Actions
                  • Unit - Add Ambush Invisibility to TempUnit
                • Else - Actions
            • Else - Actions
              • Unit - Remove Ambush Invisibility from TempUnit
              • Unit Group - Remove TempUnit from AmbushGroup.
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in AmbushGroup) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
EDIT: Had a problem with TempPoint. Use version 3 instead.
 

Attachments

  • Ambush Uncle 3.w3m
    21.5 KB · Views: 43
Last edited:
Status
Not open for further replies.
Top