Player death and WoW graveyard respawn system

Status
Not open for further replies.
Level 5
Joined
Dec 29, 2008
Messages
61
Is there any way to tint the entire screen, or to set saturation so that it's all grey?

I'm creating a "walk to corpse" system for my RPG and wanted everything to be grey while you're dead.

It looks like something similar was done with a mask for this guy's night vision project: Ideas on "night vision goggles"

The issue is that it has to apply to the dying unit.

The way this mechanic works is that the player will lose the ability to attack/use abilities but will otherwise be invisible and invulnerable until they reach a region that is created near the location of their death. I'm working on all of that, but I just want to know how to apply the screen tint to solely the player who died.

This is what I have so far.

  • Events
    • Unit - A unit Dies
  • Conditions
    • (Owner of (Dying unit)) Equal to mPlayer[PlayerCount]
  • Actions
    • Hero - Instantly revive mHero[PlayerCount] at (Center of Graveyard1 <gen>), Hide revival graphics
  • Cinematic - Apply a filter over 2.00 seconds using Normal blending on texture White Mask, starting with color (100.00%, 100.00%, 100.00%) and 50.00% transparency and ending with color (100.00%, 100.00%, 100.00%) and 50.00% transparency
Actually I'm pretty sure this works...
 
Last edited:

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Your trigger looks a bit strange. What is PlayerCount and why is it being used as the [index] to these variable arrays?

I imagine this is more likely what you want:
  • Events
    • Unit - A unit Dies
  • Conditions
    • ((Dying unit) is a Hero) Equal to True
    • (Dying unit) Equal to mHero[Player number of (Owner of (Dying unit))]
  • Actions
    • Set Variable PN = (Player number of (Owner of (Dying unit))
    • Hero - Instantly revive mHero[PN] at (Center of Graveyard1 <gen>), Hide revival graphics /// this leaks a point
    • Custom script: if GetLocalPlayer() == Player(udg_PN - 1) then
    • Cinematic - Fade out over 2.00 seconds using texture Dream and color (0.00%, 0.00%, 0.00%) with 0.00% transparency
    • Custom script: endif
Then when you finally revive:
  • Events
    • The unit revives...
  • Conditions
  • Actions
    • Set Variable PN = (Player number of (Owner of (Triggering unit))
    • Custom script: if GetLocalPlayer() == Player(udg_PN - 1) then
    • Cinematic - Fade in over 2.00 seconds using texture Dream and color (0.00%, 0.00%, 0.00%) with 0.00% transparency
    • Custom script: endif
With this design the triggers will work for any number of players, assuming they each only control one hero. Also, you can only have one cinematic filter on at a time.

I thought the Dream texture looked neat but of course you can use whatever you want.

An alternative to this would be to use the new UI frames that were added in 1.31:
 
Level 5
Joined
Dec 29, 2008
Messages
61
You assumed correctly that PlayerCount is actually Player number of (Owner of (Dying unit). I just stored it as an integer in an integer array because at the beginning of the map it has to loop through multiple players.

Couple questions.

Wht's udg_PN - 1?

And is Dream a custom texture that you have or is that available in-game by default?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Referencing PlayerCount like that doesn't make any sense. It's only going to have one value, in this case whatever it was last set to, so the trigger would only work for the Player whose number it has been set to last. If PlayerCount was last set to 4, then it would only work for mPlayer[4], ignoring all of the other players.

PN is an Integer variable I set to make referencing the Player Number easier.

The function Player() takes in a Player's number and returns you the Player object that's associated with that number. In other words, it converts an Integer into a Player. However, this function is indexed starting at 0, so 0 = Player 1 (red), 1 = Player 2 (blue), 2 = Player 3 (teal), etc... which is why I subtracted 1 from it.

Dream is one of the many textures available by default.
 
Last edited:
Level 5
Joined
Dec 29, 2008
Messages
61
Cool. This is what I've got now. And for reference, I'd want the transparency to be at least 50% so that the texture effect is visible.

  • Events
    • Unit - A unit Dies
  • Conditions
    • ((Dying unit) is A Hero) Equal to True
    • ((Unit-type of (Dying unit)) is A Hero) Equal to True
  • Actions
    • Set VariableSet DyingPlayerNumber = (Player number of (Owner of (Dying unit)))
    • Hero - Instantly revive mHero[DyingPlayerNumber] at (Center of Graveyard1 <gen>), Hide revival graphics
    • Custom script: if GetLocalPlayer() == Player(udg_DyingPlayerNumber - 1) then
    • Cinematic - Fade out over 2.00 seconds using texture Black Mask and color (0.00%, 0.00%, 0.00%) with 75.00% transparency
    • Custom script: endif
    • Unit - Make mHero[DyingPlayerNumber] Invulnerable
    • Unit - Add Permanent Invisibility to mHero[DyingPlayerNumber]
    • Unit - Add Cargo Hold (Spirit) to mHero[DyingPlayerNumber]
I was able to remove my hero's attack ability entirely by adding the skill Cargo Hold (Orc Burrow) to my hero and setting its cargo capacity to 0.

Now I just need a way to temporarily disable all Hero abilities.
 
Last edited:
Level 45
Joined
Feb 27, 2007
Messages
5,578
Yeah you can't use PlayerCount like that, lol. I left it with that name because that's what I called that variable in the first iteration of the camera lock trigger and didn't think its name needed to be different in the second version. You're gonna have to recompute "Player number of owner of <relevant unit>" whenever you need to refer to any of the arrays.
Now I just need a way to temporarily disable all Hero abilities.
Doom is a unit-targeted ability that silences the target while active. That won't stop auras or other passive abilities, though. You can also dummy cast silence to disable attacks and spells so you wouldn't have to use cargo + doom, but you do have to make sure the silence hits only the correct target and nothing else.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Your Conditions are wrong, you're now checking if the Unit is a Hero twice, which is redundant. Here's how it should look:
  • Conditions
  • (Dying unit) is a Hero Equal to True
  • (Dying unit) Equal to mHero[Player number of (Owner of (Dying unit))]
My Conditions first check to see if the Unit that died was a Hero, this should narrow it down a lot. Then it checks if that Unit belonged to a Player by referencing mHero, which I assume is set to each Player's Hero. We're focused on the Unit, not it's Unit-Type. You could also delete the first Condition if you wanted but I figured it might be more efficient this way if a lot of units are dying all of the time.

Also, you may need to manually Disable the abilities of the Hero to truly get around any potential weirdness. But it's probably better to just use a different Unit than the actual Hero as the "ghost". You could use an illusion of the Hero, or maybe just have a Dummy version that has no Abilities/Attack/etc. For reviving, you could use Orders to detect the interaction, for instance if you needed to Right click your corpse to bring up the "Revive now" option. It depends on how you want it to work.
 
Last edited:
Level 5
Joined
Dec 29, 2008
Messages
61
Yeah you can't use PlayerCount like that, lol. I left it with that name because that's what I called that variable in the first iteration of the camera lock trigger and didn't think its name needed to be different in the second version. You're gonna have to recompute "Player number of owner of <relevant unit>" whenever you need to refer to any of the arrays.

Doom is a unit-targeted ability that silences the target while active. That won't stop auras or other passive abilities, though. You can also dummy cast silence to disable attacks and spells so you wouldn't have to use cargo + doom, but you do have to make sure the silence hits only the correct target and nothing else.

Thanks. That makes sense. I'll have to run a check each time I reference those arrays. I'm currently testing with a single player so that's why I haven't noticed anything break. It will be interesting to test with a few more.
 
Level 5
Joined
Dec 29, 2008
Messages
61
Your Conditions are wrong, you're now checking if the Unit is a Hero twice, which is redundant. Here's how it should look:
  • Conditions
  • (Dying unit) is a Hero Equal to True
  • (Dying unit) Equal to mHero[Player number of (Owner of (Dying unit))]
My Conditions first check to see if the Unit that died was a Hero, this should narrow it down a lot. Then it checks if that Unit belonged to a Player by referencing mHero, which I assume is set to each Player's Hero. We're focused on the Unit, not it's Unit-Type. You could also delete the first Condition if you wanted but I figured it might be more efficient this way if a lot of units are dying all of the time.

Also, you may need to manually Disable the abilities of the Hero to truly get around any potential weirdness. But it's probably better to just use a different Unit than the actual Hero as the "ghost". You could use an illusion of the Hero, or maybe just have a Dummy version that has no Abilities/Attack/etc. For reviving, you could use Orders to detect the interaction, for instance if you needed to Right click your corpse to bring up the "Revive now" option. It depends on how you want it to work.

Thanks. That makes sense. I've updated that.

I'm still thinking about the user story for this feature. I could dynamically create a region at the Hero's last death location (store that as a variable when they die and only allow that hero to interact with it), animate that region with a sparkling field or something, and then when that hero enters it could just automatically revive them, or issue a prompt before hand.

I could also create a "corpse" unit for that hero at the death location and then when the "ghost" returns and clicks on that corpse it could prompt the user to resurrect.

In either case, all the effects that I've set for the hero would be reversed and they'd be able to play again.

I'm leaning toward the region approach as that would give the player some latitude in terms of where they'd like to "respawn" (become playable again).

I'll post the map here when I've got something working.
 
Level 5
Joined
Dec 29, 2008
Messages
61
Yeah you can't use PlayerCount like that, lol. I left it with that name because that's what I called that variable in the first iteration of the camera lock trigger and didn't think its name needed to be different in the second version. You're gonna have to recompute "Player number of owner of <relevant unit>" whenever you need to refer to any of the arrays.

Doom is a unit-targeted ability that silences the target while active. That won't stop auras or other passive abilities, though. You can also dummy cast silence to disable attacks and spells so you wouldn't have to use cargo + doom, but you do have to make sure the silence hits only the correct target and nothing else.

It looks like you can't unit order cast Silence? I can find Doom but I can't Silence it in the menu. I have a "spirit healer" unit in the graveyard who could be the dummy to cast the spell but I'm not sure how to implement that.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Silence is an Area of Effect ability, so it relies on Point targeting, not Unit targeting. Also, I would use Drunken Haze as the ability, since it's Unit targeting and can do everything that Silence can do. Just set it's Area of Effect to 0. Note that making the unit Invulnerable will Remove the buffs on it, which is why I suggested manually disabling the abilities through triggers.

Also, creating Regions doesn't work too well, I would suggest creating a Point variable on the position of your Hero upon death, and then use a Periodic Interval trigger to periodically check if the "ghost" is near that Point:
  • Events
    • Unit - A unit Dies
  • Conditions
    • ((Dying unit) is A Hero) Equal to True
    • ((Unit-type of (Dying unit)) is A Hero) Equal to True
  • Actions
    • Set VariableSet DyingPlayerNumber = (Player number of (Owner of (Dying unit)))
    • ---
    • Set VariableSet DeathPoint[DyingPlayerNumber] = (Position of (Dying unit))
    • Unit Group - Add (Dying unit) to DeadHeroes
    • Trigger - Turn on Check Dead Heroes
    • ---
    • Hero - Instantly revive mHero[DyingPlayerNumber] at (Center of Graveyard1 <gen>), Hide revival graphics
    • Custom script: if GetLocalPlayer() == Player(udg_DyingPlayerNumber - 1) then
    • Cinematic - Fade out over 2.00 seconds using texture Black Mask and color (0.00%, 0.00%, 0.00%) with 75.00% transparency
    • Custom script: endif
    • Unit - Make mHero[DyingPlayerNumber] Invulnerable
    • Unit - Add Permanent Invisibility to mHero[DyingPlayerNumber]
    • Unit - Add Cargo Hold (Spirit) to mHero[DyingPlayerNumber]
This is the periodic trigger, it would be initially off because we only want it to run if there are dead heroes:
  • Events
    • Time - Every 0.02 seconds
  • Conditions
  • Actions
    • Unit Group - Pick every unit in DeadHeroes and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Distance between DeathPoint[Player number of (Owner of (Picked unit))] and (Position of (Picked unit))) Less than or equal to 500.00
          • Then - Actions
            • -------- Revive the hero, remove it from DeadHeroes, and check if this trigger should turn off (unit group is empty): --------
          • Else - Actions
 
Last edited:
Level 5
Joined
Dec 29, 2008
Messages
61
Silence is an Area of Effect ability, so it relies on Point targeting, not Unit targeting. Also, I would use Drunken Haze as the ability, since it's Unit targeting and can do everything that Silence can do. Just set it's Area of Effect to 0. Note that making the unit Invulnerable will Remove the buffs on it, which is why I suggested manually disabling the abilities through triggers.

Also, creating Regions doesn't work too well, I would suggest creating a Point variable on the position of your Hero upon death, and then use a Periodic Interval trigger to periodically check if the "ghost" is near their Point:
  • Events
    • Unit - A unit Dies
  • Conditions
    • ((Dying unit) is A Hero) Equal to True
    • ((Unit-type of (Dying unit)) is A Hero) Equal to True
  • Actions
    • Set VariableSet DyingPlayerNumber = (Player number of (Owner of (Dying unit)))
    • Set Variable DeathPoint[DyingPlayerNumber] = (Position of (Dying unit))
    • Unit Group - Add (Dying unit) to DeadHeroes
    • Trigger - Turn on Check Dead Heroes (ignoring conditions)
    • Hero - Instantly revive mHero[DyingPlayerNumber] at (Center of Graveyard1 <gen>), Hide revival graphics
    • Custom script: if GetLocalPlayer() == Player(udg_DyingPlayerNumber - 1) then
    • Cinematic - Fade out over 2.00 seconds using texture Black Mask and color (0.00%, 0.00%, 0.00%) with 75.00% transparency
    • Custom script: endif
    • Unit - Make mHero[DyingPlayerNumber] Invulnerable
    • Unit - Add Permanent Invisibility to mHero[DyingPlayerNumber]
    • Unit - Add Cargo Hold (Spirit) to mHero[DyingPlayerNumber]
  • Events
    • Time - Every 0.02 seconds
  • Conditions
  • Actions
    • Unit Group - Pick every unit in DeadHeroes and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Distance between DeathPoint[Player number of (Owner of (Picked unit))] and (Position of (Picked unit))) Less than or equal to 500.00
          • Then - Actions
            • -------- Revive the hero, remove it from DeadHeroes, and check if this trigger should turn off (unit group is empty): --------
          • Else - Actions

That's an awesome solution! Thanks.

Also, I was searching the forums and found that Soul Burn could work here. I can just set the Buff to Silence, set Silence's AOE to 0 and remove the DOT.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Soul Burn may alert that your Hero is under attack, so I still think Drunken Haze is the better option from among those spells. But that's not really important, Invulnerable units cannot be affected by these spells so it's rather pointless to use them. Doom may remain active during Invulnerability?

Also, my suggestions leak a lot of Points, so if you're interested in managing memory leaks you should look into that.
 
Level 5
Joined
Dec 29, 2008
Messages
61
Silence is an Area of Effect ability, so it relies on Point targeting, not Unit targeting. Also, I would use Drunken Haze as the ability, since it's Unit targeting and can do everything that Silence can do. Just set it's Area of Effect to 0. Note that making the unit Invulnerable will Remove the buffs on it, which is why I suggested manually disabling the abilities through triggers.

Also, creating Regions doesn't work too well, I would suggest creating a Point variable on the position of your Hero upon death, and then use a Periodic Interval trigger to periodically check if the "ghost" is near that Point:
  • Events
    • Unit - A unit Dies
  • Conditions
    • ((Dying unit) is A Hero) Equal to True
    • ((Unit-type of (Dying unit)) is A Hero) Equal to True
  • Actions
    • Set VariableSet DyingPlayerNumber = (Player number of (Owner of (Dying unit)))
    • ---
    • Set VariableSet DeathPoint[DyingPlayerNumber] = (Position of (Dying unit))
    • Unit Group - Add (Dying unit) to DeadHeroes
    • Trigger - Turn on Check Dead Heroes (ignoring conditions)
    • ---
    • Hero - Instantly revive mHero[DyingPlayerNumber] at (Center of Graveyard1 <gen>), Hide revival graphics
    • Custom script: if GetLocalPlayer() == Player(udg_DyingPlayerNumber - 1) then
    • Cinematic - Fade out over 2.00 seconds using texture Black Mask and color (0.00%, 0.00%, 0.00%) with 75.00% transparency
    • Custom script: endif
    • Unit - Make mHero[DyingPlayerNumber] Invulnerable
    • Unit - Add Permanent Invisibility to mHero[DyingPlayerNumber]
    • Unit - Add Cargo Hold (Spirit) to mHero[DyingPlayerNumber]
This is the periodic trigger, it would be initially off because we only want it to run if there are dead heroes:
  • Events
    • Time - Every 0.02 seconds
  • Conditions
  • Actions
    • Unit Group - Pick every unit in DeadHeroes and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Distance between DeathPoint[Player number of (Owner of (Picked unit))] and (Position of (Picked unit))) Less than or equal to 500.00
          • Then - Actions
            • -------- Revive the hero, remove it from DeadHeroes, and check if this trigger should turn off (unit group is empty): --------
          • Else - Actions

Would the UnitGroup DeadHeroes have to be created using some kind of loop? Or is this a variable Unit array?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
It's a Unit Group variable that you need to create yourself. An Array will always have brackets [] following it's name.

Unit Groups and Player Groups don't need to be Set, unlike most other variables, since we have the Add/Remove functions that allow us to manage what goes in and out of them. You can still Set them though, which is useful in a lot of cases, just not here.

Note that when working with Unit Group arrays and Player Group arrays (as well as Timer arrays), you need to manually set their Array Size to take advantage of the multiple [indexes]. Either that or you have to Create() them yourself, which requires Custom Script when using GUI. This isn't being done here but I figured I'd mention it anyway.
 
Level 5
Joined
Dec 29, 2008
Messages
61
Great. That's helpful. Thanks.

I tested the script and one thing that's happening is that instantly upon revival my debugging text fires off (this would indicate that the hero walked up to their corpse). I'm wondering if the instant revival function interferes with setting the DeathPoint variable... I set the distance in the CheckDeadHeroes function to less than or equal to 1.0 to see if the distance was throwing it off but it isn't.

  • Events
    • Unit - A unit Dies
  • Conditions
    • ((Dying unit) is A Hero) Equal to True
    • (Owner of (Dying unit)) Equal to mPlayer[(Player number of (Owner of (Dying unit)))]
  • Actions
    • Set VariableSet DyingPlayerNumber = (Player number of (Owner of (Dying unit)))
    • Set VariableSet DeathPoint[DyingPlayerNumber] = (Position of (Dying unit))
    • Unit Group - Add (Dying unit) to DeadHeroes
    • Trigger - Run CheckDeadHeroes <gen> (checkingconditions)
    • -------- Assign Ghost Logic to Hero --------
    • Hero - Instantly revive mHero[DyingPlayerNumber] at (Center of Graveyard1 <gen>), Hide revival graphics
    • ...
CheckDeadHeroes:

  • Events
    • Time - Every 0.03 seconds of game time
  • Actions
    • Unit Group - Pick every unit in DeadHeroes and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Distance between DeathPoint[(Player number of (Owner of (Picked unit)))] and (Position of (Picked unit))) Less than or equal to 1.00
          • Then - Actions
            • Game - Display to (All players) the text: You have been reviv...
          • Else - Actions
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
The reason for your issue is due to the order of your Actions and the Trigger Action you're using.

The first issue is that you're comparing the Dead hero's position to his corpse (DeathPoint) BEFORE reviving him elsewhere. So the Hero is still at the position of his corpse and as a result will be revived immediately.

The main issue is that you're running CheckDeadHeroes instead of Turning it On. The trigger is meant to act like a light switch, so we want the trigger to be off by default since there are no dead heroes yet, then on while there are dead heroes, and off again once they have all revived.

This is how you would turn off the CheckDeadHeroes trigger once all of the Heroes have revived:
  • Then - Actions
    • Game - Display to (All players) the text: You have been reviv...
    • Unit Group - Remove (Picked unit) from DeadHeroes
    • If (Number of units in DeadHeroes) Equal to 0 Then Turn off (this trigger) Else Do nothing
And you should tick the "Initially On" checkbox for the CheckDeadHeroes trigger so it's off by default.

Edit: I accidentally wrote "Turn on trigger (ignoring conditions)" in my last post so I imagine that's where the confusion came from, sorry.
 
Last edited:
Level 5
Joined
Dec 29, 2008
Messages
61
All the logic works now. The hero respawns at the graveyard and then loses all their "ghost" properties when they reach their corpse. However, it appears that either Drunken Haze isn't being cast or the effect doesn't silence spells. I'm not sure which at the moment.

Edit: My mistake. I didn't read where you said that Invulnerability disables buffs. I'd rather not disable abilities via triggers, however, unless there's a way to disable all abilities easily with one function.

  • Events
    • Unit - A unit Dies
  • Conditions
    • ((Dying unit) is A Hero) Equal to True
    • (Owner of (Dying unit)) Equal to mPlayer[(Player number of (Owner of (Dying unit)))]
  • Actions
    • Set VariableSet DyingPlayerNumber = (Player number of (Owner of (Dying unit)))
    • -------- Set Death Point --------
    • Set VariableSet DeathPoint[DyingPlayerNumber] = (Position of (Dying unit))
    • Unit Group - Add (Dying unit) to DeadHeroes
    • -------- Assign Ghost Logic to Heroes --------
    • Hero - Instantly revive mHero[DyingPlayerNumber] at (Center of Graveyard1 <gen>), Hide revival graphics
    • Trigger - Turn on CheckDeadHeroes <gen>
    • Custom script: if GetLocalPlayer() == Player(udg_DyingPlayerNumber - 1) then
    • Cinematic - Fade out over 2.00 seconds using texture Dream and color (100.00%, 100.00%, 100.00%) with 75.00% transparency
    • Custom script: endif
    • Unit - Order Spirit Healer 0038 <gen> to Neutral Brewmaster - Drunken Haze mHero[DyingPlayerNumber]
    • Unit - Make mHero[DyingPlayerNumber] Invulnerable
    • Unit - Add Permanent Invisibility to mHero[DyingPlayerNumber]
    • Unit - Add Cargo Hold (Spirit) to mHero[DyingPlayerNumber]
    • Unit - Add Detector (Sentry Ward) to mHero[DyingPlayerNumber]
  • Trigger - Turn on GhostResetCamera <gen>
All the logic works now.

  • Events
    • Time - Every 0.03 seconds of game time
  • Actions
    • Unit Group - Pick every unit in DeadHeroes and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Distance between DeathPoint[(Player number of (Owner of (Picked unit)))] and (Position of (Picked unit))) Less than or equal to 500.00
          • Then - Actions
            • Game - Display to (Player group(mPlayer[PlayerCount])) the text: You have been reviv...
            • -------- Remove Ghost Logic from Heroes --------
            • Custom script: if GetLocalPlayer() == Player(udg_DyingPlayerNumber - 1) then
            • Cinematic - Hide filter
            • Custom script: endif
            • Unit - Remove All buffs from mHero[DyingPlayerNumber]
            • Unit - Make mHero[DyingPlayerNumber] Vulnerable
            • Unit - Remove Permanent Invisibility from mHero[DyingPlayerNumber]
            • Unit - Remove Cargo Hold (Spirit) from mHero[DyingPlayerNumber]
            • Unit - Remove Detector (Sentry Ward) from mHero[DyingPlayerNumber]
            • -------- Remove Heroes from DeadHeroes --------
            • Unit Group - Remove (Picked unit) from DeadHeroes.
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • (Number of units in DeadHeroes) Equal to 0
              • Then - Actions
                • Trigger - Turn off CheckDeadHeroes <gen>
              • Else - Actions
          • Else - Actions
Also, what is this icon lol?
 

Attachments

  • icon_ghost.png
    icon_ghost.png
    1.6 MB · Views: 11
Last edited:

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
You need to customize the Drunken Haze ability. Under the Attacks Prevented field enable Melee, Ranged, Special, and Spells. Also, you cannot target an Invulnerable unit with Drunken Haze, so you'll need to Wait until the Hero actually has the Drunken Haze buff before making it Invulnerable.

Also, you no longer need the Cargo Hold ability since Drunken Haze will handle that for you.

I attached a map with an example trigger for how I would handle this. It also shows you how to create a proper Dummy unit which is super useful, I recommend copying and pasting the Unit into your map and using it whenever you need a Dummy to cast a spell.

  • Hero Dies
    • Events
      • Unit - A unit Is issued an order with no target
    • Conditions
      • (Issued order) Equal to (Order(stop))
    • Actions
      • Custom script: local unit udg_DyingHero = GetTriggerUnit()
      • Set VariableSet PN = (Player number of (Owner of DyingHero))
      • Set VariableSet DeathPoint[PN] = (Position of DyingHero)
      • -------- --------
      • -------- This stuns the Hero (do NOT stack these): --------
      • Custom script: call BlzPauseUnitEx(udg_DyingHero, true)
      • -------- --------
      • -------- Create a temporary Dummy unit which is setup to cast spells immediately: --------
      • Unit - Create 1 Dummy for (Owner of DyingHero) at DeathPoint[PN] facing Default building facing degrees
      • Unit - Add Ghost Form (Dummy) to (Last created unit)
      • Unit - Add a 0.20 second Generic expiration timer to (Last created unit)
      • Unit - Order (Last created unit) to Neutral Brewmaster - Drunken Haze DyingHero
      • -------- --------
      • -------- Drunken Haze cannot target Invulnerable units. --------
      • -------- That's why we need a Wait here, since the Ability needs to be applied BEFORE the Hero becomes Invulnerable. --------
      • Wait 0.01 game-time seconds
      • Unit - Make DyingHero Invulnerable
      • -------- --------
      • -------- This unstuns the Hero (do NOT stack these): --------
      • Custom script: call BlzPauseUnitEx(udg_DyingHero, false)
      • -------- --------
      • Custom script: set udg_DyingHero = null
This also shows off a technique for converting a global variable into a pseudo-local variable. That's what the weird Custom Script is doing at the start of the trigger, it's turning DyingHero which a global variable into a local variable which has the benefits of remaining local to this instance of the trigger.

Ignore the Event and Condition, that was done for testing purposes. You should focus on applying these Actions to your existing Hero dies trigger.
 

Attachments

  • Dummy Example.w3m
    18.3 KB · Views: 7
Last edited:
Level 5
Joined
Dec 29, 2008
Messages
61
You need to customize the Drunken Haze ability. Under the Attacks Prevented field enable Melee, Ranged, Special, and Spells. Also, you cannot target an Invulnerable unit with Drunken Haze, so you'll need to Wait until the Hero actually has the Drunken Haze buff before making it Invulnerable.

Also, you no longer need the Cargo Hold ability since Drunken Haze will handle that for you.

I attached a map with an example trigger for how I would handle this. It also shows you how to create a proper Dummy unit which is super useful, I recommend copying and pasting it into your map and using it whenever you need a Dummy to cast a spell.

Thanks. Yeah, just saw that part of about invulnerability above. I'll correct it.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Yeah, so I would copy and paste my Drunken Haze ability, the Buff that goes with it, and the Dummy unit I created into your map. Then make sure they're setup properly since some references can get unset during the map transferring process. Then take some of the Actions from my trigger and apply them to your existing trigger. You would mix the two triggers together since my trigger is missing some important things that yours already has and there's some duplicate Actions there that obviously don't need to be done twice.

That funny icon means that your ability is missing an icon. It's the default that's used in case you forget to supply one. It's probably the girlfriend/wife of one of the Reforged devs, lol. (Poor girl probably doesn't even know she's associated with the worst remaster of all time)

A good habit is to compare your "broken" stuff with other existing Blizzard stuff that already works. You can compare the differences to find what you're missing and what you're doing wrong.
 
Last edited:
Level 5
Joined
Dec 29, 2008
Messages
61
I noticed that your dummy doesn't have any spells in the object editor. Is it correct to say that you can get the dummy to cast any spell with the Order function, even if the dummy doesn't have the ability set in the object editor? Does this apply to every unit? Also, can non-Hero dummy units cast Hero spells?
 
Level 5
Joined
Dec 29, 2008
Messages
61
I haven't managed to implement the dummy into my existing system. I'll give it a shot but I'm still somewhat married to having the "spirit healer" unit in the graveyard be the one to cast the spell. For some reason it's still not casting Drunken Haze, even with a pause before assigning invulnerability. I even changed the hero spell to be a unit spell and gave it to the casting unit. Really not sure why it won't cast and I also kind of want to know why.
 
Last edited:
Level 45
Joined
Feb 27, 2007
Messages
5,578
I noticed that your dummy doesn't have any spells in the object editor. Is it correct to say that you can get the dummy to cast any spell with the Order function, even if the dummy doesn't have the ability set in the object editor? Does this apply to every unit? Also, can non-Hero dummy units cast Hero spells?
No, Uncle is adding the ability to the unit right after it's created. This way you do not need to manually populate the dummy's spell list with everything or worry about order-id conflicts when multiple dummy abilities have the same base ability.

I do not believe regular units can cast hero spells.
Also, what is this icon lol?
It's a reforged reference to the original 'oops no icon' icon called Sammy.blp
 
Level 5
Joined
Dec 29, 2008
Messages
61
Alright. So after spending literally 10 hours on this straight today I have to take a break. I tried everything, including adding the dummy unit. Brain hurts.

  • Events
    • Unit - A unit Dies
  • Conditions
    • ((Dying unit) is A Hero) Equal to True
    • (Owner of (Dying unit)) Equal to mPlayer[(Player number of (Owner of (Dying unit)))]
  • Actions
    • -------- Set Player Number of Dying Player --------
    • Set VariableSet DyingPlayerNumber = (Player number of (Owner of (Dying unit)))
    • -------- Set Death Point --------
    • Set VariableSet DeathPoint[DyingPlayerNumber] = (Position of (Dying unit))
    • Special Effect - Create a special effect at DeathPoint[DyingPlayerNumber] using Objects\InventoryItems\Glyph\Glyph.mdl
    • Set VariableSet DeathPointSpecialEffects[DyingPlayerNumber] = (Last created special effect)
    • Unit Group - Add (Dying unit) to DeadHeroes
    • -------- Assign Ghost Logic to Heroes --------
    • Custom script: if GetLocalPlayer() == Player(udg_DyingPlayerNumber - 1) then
    • Cinematic - Fade out over 2.00 seconds using texture Dream and color (100.00%, 100.00%, 100.00%) with 75.00% transparency
    • Custom script: endif
    • Sound - Play UndeadDissipate2 <gen> at 100.00% volume, attached to mHero[DyingPlayerNumber]
    • Hero - Instantly revive mHero[DyingPlayerNumber] at (Center of Graveyard1 <gen>), Hide revival graphics
    • Game - Display to (Player group(mPlayer[PlayerCount])) the text: You are dead. Run t...
    • -------- Dummy Logic --------
    • Unit - Create 1 Dummy for (Owner of (Dying unit)) at DeathPoint[DyingPlayerNumber] facing Default building facing degrees
    • Unit - Add Ghost Form (Dummy) to (Last created unit)
    • Unit - Add a 0.20 second Generic expiration timer to (Last created unit)
    • Unit - Order (Last created unit) to Neutral Brewmaster - Drunken Haze mHero[DyingPlayerNumber]
    • Wait 0.01 seconds
    • -------- Assign Ghost Logic to Heroes --------
    • Unit - Add Detector (Sentry Ward) to mHero[DyingPlayerNumber]
    • Unit - Add Permanent Invisibility to mHero[DyingPlayerNumber]
    • Unit - Make mHero[DyingPlayerNumber] Invulnerable
    • -------- Check Hero Death States --------
    • Trigger - Turn on CheckDeadHeroes <gen>
It's all here if you want to take a look.
 

Attachments

  • HarvestCrusadersRPG.w3m
    1.5 MB · Views: 4
Last edited:
Level 45
Joined
Feb 27, 2007
Messages
5,578
  • If you can logically use "Triggering Unit" instead of any of the other 'more specific' event responses like "Dying Unit", you should. They're all just wrappers that call GetTriggerUnit() internally
  • (Owner of (Dying unit)) Equal to mPlayer[(Player number of (Owner of (Dying unit)))] while this does accomplish what you want (because that variable is only set for players 1-12), it's a little silly. A better solution would be to add all player heroes to a group when they're spawned/on init and then check if the triggering unit is in that group as the only condition. Or you could check ((Triggering Unit) belongs to an Ally of Player 1 (Red)) equal to True.
  • You should generally only need one integer variable to represent PlayerNumber in all triggers, so I'd just shorten it and use PN for readability.
  • Technically the sound is pointed to by a global sound variable (internally), which means it can't be played multiple times simultaneously. The most recent thing to play it cuts off the previous instance. Probably doesn't matter but keep that in mind (this can be worked around).
  • Player group(mPlayer[PlayerCount]) creates a force (player group) that then leaks like a unit group does. This line won't likely happen too many times in the map so you could ignore it but it's best to prevent it in the first place. TTL shows the fix.
  • (Center of Graveyard1 <gen>) point leak. This is where the issue in your trigger lies: the hero is revived in the graveyard but the dummy is created at the death point, so it's likely not in range to cast Drunken Haze on the revived hero.
Because of the Wait there is a chance that another hero dies during the wait which would mess up DyingPlayerNumber. Using PN like I suggested above would have the same issue (but worse) because PN could be used for a bunch more things than just hero death. The solution is to 'shadow' the variable locally: basically trick GUI into thinking it's a variable local to this trigger action. You would do this:
  • Actions
    • Custom script: local integer udg_PN //has to be the first line of the actions
    • -------- --------
    • Set PN = (Player Number of (Owner of (Triggering Unit))) //can still do this but PN acts a local here!
If you do this with primitives you don't have to worry about nulling them, but handles (unit-item-player-group-force-location-etc.) will have to be nulled. The limitation is that you won't be able to access this local variable in any functions besides the trigger action. Things that invoke other functions are ForGroup (Pick every unit in... and do), ForForce (Pick every player in... and do), and conditions for if-blocks.
 
Level 5
Joined
Dec 29, 2008
Messages
61
(Center of Graveyard1 <gen>) point leak. This is where the issue in your trigger lies: the hero is revived in the graveyard but the dummy is created at the death point, so it's likely not in range to cast Drunken Haze on the revived hero.
I wish it were that because that would be simple. The cast range on that spell is 99999. I also set the cast range of the dummy unit to 20000 for both attack types as well.
 
Last edited:
Level 45
Joined
Feb 27, 2007
Messages
5,578
Ghost Form (Dummy) costs mana to cast but the unit you based your dummy on (locust) has 0 max mana (which you didn't change). Your dummy shouldn't have attacks enabled so it doesn't do anything stupid; attack range won't affect ability usage at all. Technically a unit has to have vision of its target to use a unit-targeted ability on it (even when ordered to do so by a trigger), and usually you do not want dummy units to have a sight range. Making them owned by a player who does have vision of the target is the easiest solution (in this case the owner of the dying hero), so what you've done here will work. Something to know in the future if you try to make a hostile dummy cast on a unit it doesn't have vision of.

I wouldn't use 0 projectile speed for the ability, as in my experience that can either mean minimum speed or maximum speed depending on the spell and I don't know which one Drunken Haze is; use 10000. Note that projectile speed will actually matter here if the graveyard and the player's corpse are any reasonable distance away from each other.
 
Level 5
Joined
Dec 29, 2008
Messages
61
Thank you for all the help guys. Here's the latest version of the map in case someone searches this and wants to play with the system.
 

Attachments

  • HarvestCrusadersRPG.w3m
    1.6 MB · Views: 6
Status
Not open for further replies.
Top