• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Soul Storage

Status
Not open for further replies.
Level 4
Joined
Jan 6, 2023
Messages
33
Hey! Tried to search through many ways to do it, took many paths but can't really get it right
Making a spell that will search for nearby dead units and depending on dead count it will do certain actions. (For example if 3 dead units, summon infernal, if 5, summon doomlord etc) But don't really know what technique to use here to store these dead units and use them after ability ends (channeling)

Or storing like this - After killing an unit, a hero is granted a soul. Having 10 souls will remove them and grant strength buff. Issue is the same, i don;t really know how to store them/use them later
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,877
I attached a map with spells similar to what you described.

I didn't fully understand your first spell so I just attempted to do what I thought you wanted.

These require that you have a Unit Indexer imported into your map because they take advantage of Custom Value. Your map must contain only ONE Unit Indexer of any kind. Also, Unit Indexer systems use the Set Unit Custom Value action as an integral part of their design and will interfere with any other triggers of yours that use this action as well. You can easily adapt those other triggers to replace your Custom Value usage with Variable Arrays instead.

Soul Storage - Every 10 kills, gain a buff that grants 50% increased attack damage for 10.00 seconds.
  • Soul Storage On Kill
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Level of Soul Storage (Unit) for (Killing unit)) Not equal to 0
    • Actions
      • Set VariableSet SS_Caster = (Killing unit)
      • Set VariableSet SS_CV = (Custom value of SS_Caster)
      • Set VariableSet SS_SoulCount[SS_CV] = (SS_SoulCount[SS_CV] + 1)
      • -------- --------
      • -------- Buff: --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SS_SoulCount[SS_CV] Equal to 10
        • Then - Actions
          • Set VariableSet SS_CastingPlayer = (Owner of SS_Caster)
          • Set VariableSet SS_Point = (Position of SS_Caster)
          • -------- --------
          • Unit - Create 1 Dummy (Uncle) for SS_CastingPlayer at SS_Point facing Default building facing degrees
          • Set VariableSet SS_Dummy = (Last created unit)
          • Unit - Add a 0.20 second Generic expiration timer to SS_Dummy
          • Unit - Add Soul Storage (Dummy) to SS_Dummy
          • Unit - Order SS_Dummy to Human Priest - Inner Fire SS_Caster
          • -------- --------
          • Custom script: call RemoveLocation(udg_SS_Point)
        • Else - Actions
Soul Conversion - Channels and consumes the souls of nearby corpses. Upon finishing, summon a minion based on the # of souls consumed.
  • Soul Conversion Channel
    • Events
      • Unit - A unit Begins channeling an ability
    • Conditions
      • (Ability being cast) Equal to Soul Conversion (Unit)
    • Actions
      • Set VariableSet SS_Caster = (Triggering unit)
      • Set VariableSet SS_CastingPlayer = (Owner of SS_Caster)
      • Set VariableSet SS_CV = (Custom value of SS_Caster)
      • -------- --------
      • -------- Reset souls: --------
      • Set VariableSet SC_SoulCount[SS_CV] = 0
      • -------- --------
      • Unit Group - Add SS_Caster to SC_CasterGroup
      • Trigger - Turn on Soul Conversion Loop <gen>
  • Soul Conversion Finish
    • Events
      • Unit - A unit Stops casting an ability
    • Conditions
      • (Ability being cast) Equal to Soul Conversion (Unit)
      • ((Triggering unit) is alive) Equal to True
    • Actions
      • Set VariableSet SS_Caster = (Triggering unit)
      • Set VariableSet SS_CastingPlayer = (Owner of SS_Caster)
      • Set VariableSet SS_CV = (Custom value of SS_Caster)
      • -------- --------
      • Set VariableSet SC_Point = (Position of SS_Caster)
      • -------- --------
      • -------- Summon: --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SC_SoulCount[SS_CV] Greater than or equal to 10
        • Then - Actions
          • Unit - Create 1 Doom Guard (Standard) for SS_CastingPlayer at SC_Point facing Default building facing degrees
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SC_SoulCount[SS_CV] Greater than or equal to 6
            • Then - Actions
              • Unit - Create 1 Infernal for SS_CastingPlayer at SC_Point facing Default building facing degrees
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SC_SoulCount[SS_CV] Greater than or equal to 3
                • Then - Actions
                  • Unit - Create 1 Fel Stalker for SS_CastingPlayer at SC_Point facing Default building facing degrees
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • SC_SoulCount[SS_CV] Greater than or equal to 1
                    • Then - Actions
                      • Unit - Create 1 Zombie for SS_CastingPlayer at SC_Point facing Default building facing degrees
                    • Else - Actions
      • -------- --------
      • Custom script: call RemoveLocation(udg_SC_Point)
      • -------- --------
      • -------- Special Effect: --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SC_SoulCount[SS_CV] Greater than 0
        • Then - Actions
          • Set VariableSet SC_Point = (Position of (Last created unit))
          • Special Effect - Create a special effect at SC_Point using Abilities\Spells\Demon\DarkPortal\DarkPortalTarget.mdl
          • Special Effect - Destroy (Last created special effect)
          • Custom script: call RemoveLocation(udg_SC_Point)
        • Else - Actions
      • -------- --------
      • -------- Reset souls: --------
      • Set VariableSet SC_SoulCount[SS_CV] = 0
      • -------- --------
      • Unit Group - Remove SS_Caster from SC_CasterGroup.
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in SC_CasterGroup) Equal to 0
        • Then - Actions
          • Trigger - Turn off Soul Conversion Loop <gen>
        • Else - Actions
  • Soul Conversion Loop
    • Events
      • Time - Every 0.25 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in SC_CasterGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet SS_Caster = (Picked unit)
          • Set VariableSet SS_CV = (Custom value of SS_Caster)
          • Set VariableSet SS_Point = (Position of SS_Caster)
          • Set VariableSet SC_Skip = False
          • -------- --------
          • -------- Set the Area of Effect here: --------
          • Set VariableSet SC_DeadGroup = (Units within 900.00 of SS_Point.)
          • -------- --------
          • Custom script: call RemoveLocation(udg_SS_Point)
          • -------- --------
          • Unit Group - Pick every unit in SC_DeadGroup and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SC_Skip Equal to False
                • Then - Actions
                  • Set VariableSet SC_Target = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (SC_Target is dead) Equal to True
                    • Then - Actions
                      • Set VariableSet SC_Skip = True
                      • -------- --------
                      • Set VariableSet SC_SoulCount[SS_CV] = (SC_SoulCount[SS_CV] + 1)
                      • -------- --------
                      • -------- Special Effect: --------
                      • Set VariableSet SC_Point = (Position of SC_Target)
                      • Special Effect - Create a special effect at SC_Point using Objects\Spawnmodels\Undead\UndeadDissipate\UndeadDissipate.mdl
                      • Special Effect - Destroy (Last created special effect)
                      • Custom script: call RemoveLocation(udg_SC_Point)
                      • -------- --------
                      • Unit - Remove SC_Target from the game
                    • Else - Actions
                • Else - Actions
          • -------- --------
          • Custom script: call DestroyGroup(udg_SC_DeadGroup)
I reused some variables between the two spells which is why it may look confusing at times. I figured it was better than creating extra variables and bloating your map.
 

Attachments

  • Soul Storage 1.w3m
    29.5 KB · Views: 6
Last edited:
Level 45
Joined
Feb 27, 2007
Messages
5,578
search for nearby dead units and depending on dead count it will do certain actions
  • Set SearchPoint = (Target point of ability being cast)
  • Set SearchPoint = (Position of (Triggering Unit))
  • -------- set SearchPoint to wherever is relevant, depending on how the ability should function; two iikely options are shown above --------
  • Set Range = 300.00 //or whatever the range is
  • Set DeadCount = 0
  • Custom script: set bj_wantDestroyGroup = true //primes a unit group leak that will occur in the next line to clean itself up automatically
  • Unit Group - Pick every unit in (Units within Range of SearchPoint) matching (((Matching Unit) is Dead) equal to True) and do (Actions)
    • Loop - Actions
      • Set DeadCount = (DeadCount + 1)
  • -------- at this point DeadCount is the total number of dead units within Range of SearchPoint; do whatever you need with that information --------
  • -------- check DeadCount from high to low, so that when a valid condition is found it will only execute that set of actions and not everything --------
  • If (All conditions are true) then do (Then actions) else do (Else actions)
    • If - Conditions
      • DeadCount Greater than or equal to 5
    • Then - Actions
      • Unit - Create 1 Doomguard for (Owner of (Triggering Unit)) at SearchPoint facing Default building facing degrees
      • Unit - Play (Last created unit)'s attack,slam animation
      • Set DeadCount = 0 //either do this or use "Skip remaining actions"
    • Else - Actions
  • If (All conditions are true) then do (Then actions) else do (Else actions)
    • If - Conditions
      • DeadCount Greater than or equal to 3
    • Then - Actions
      • Unit - Create 1 Infernal for (Owner of (Triggering Unit)) at SearchPoint facing Default building facing degrees
      • Unit - Play (Last created unit)'s birth animation
      • Set DeadCount = 0
    • Else - Actions
  • //etc.
  • Custom script: call RemoveLocaiton(udg_SearchPoint) //match the name of your variable but keep the udg_ prefix
How exactly you want this to interface with the spell's channel time is unclear to me, so I didn't engage with that side of things.
 
Level 4
Joined
Jan 6, 2023
Messages
33
Sorry for the late reply here!

Your triggers work flawlessly Uncle! Thank you for those, exactly what I was looking for!!

How exactly you want this to interface with the spell's channel time is unclear to me, so I didn't engage with that side of things.
Just wanted the trigger to run after the caster finishes channel ability/gets interrupted/moves, I'll just use relevant events for that. "DeadCount" is a C variable?
Your trigger Pyro works perfectly as intended aswell, just one question. Is there any way to fix one issue? If the corpse of killed unit does not decay I can cast this spell spawning Doomlords etc infinitely because it detects dead unit all the time. Same for units that instantly decay - spell doesn't work
 
Last edited:

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,877
Sorry for the late reply here!

Your triggers work flawlessly Uncle! Thank you for those, exactly what I was looking for!!


Just wanted the trigger to run after the caster finishes channel ability/gets interrupted/moves, I'll just use relevant events for that. "DeadCount" is a C variable?
Your trigger Pyro works perfectly as intended aswell, just one question. Is there any way to fix one issue? If the corpse of killed unit does not decay I can cast this spell spawning Doomlords etc infinitely because it detects dead unit all the time. Same for units that instantly decay - spell doesn't work
You need to Remove the Dead unit from the game after using it's corpse, which is what I'm doing in my example. Units that instantly decay are literally Removed from the game and no longer exist so they can't be considered Dead.

Here's how unit death and spells like Raise Dead work:

When a non-Hero unit dies, it either gets Removed from the game immediately:
  • Unit - Remove (Dying unit) from the game
Or, if it leaves behind a corpse, it remains in the game as an inactive corpse and gets Removed after X seconds (corpse decay time):
  • Wait (Corpse decay time) seconds
  • Unit - Remove (Dying unit) from the game
Or, if it's a Hero, it simply gets Hidden (I assume) since it can be Revived in the future.

There's also the option to make a Unit leave behind a corpse but also ignore spells like Raise Dead -> Decays over time, can't be raised.
I don't think there's an easy way to detect this in the Trigger Editor but I could be wrong. You could always come up with a system for this if need be.

It's good that you brought this up because we aren't excluding Heroes from our triggers which is going to be a problem. I've updated my map to fix this issue and also added another trigger which showcases a simplified version of the Soul Conversion spell I made.
 

Attachments

  • Soul Storage 2.w3m
    30.3 KB · Views: 4
Last edited:
Level 45
Joined
Feb 27, 2007
Messages
5,578
DeadCount is an integer. I think Uncle's reply addresses your question, generally, so I won't write an example trigger to show how you'd modify my previous example. To remove units you would:
  • Remove the bj_wantDestroyGroup line because actually we can just use that group to hold all the dead units; instead of just picking the units in the group we'll assign the group to a variable (DeadGroup) and then pick all units in that group variable.
  • Add some additional filters to only grab dead non-heroes; as Uncle guessed there's no way to learn a unit's raisability type directly (only by dummy-casting raise dead on the corpse to see if it works).
  • Inside the if blocks I wrote, use the bj_wantDestroy method to pick DeadCount random units from DeadGroup and remove them from the map.
  • Destroy DeadGroup properly.
 
Status
Not open for further replies.
Top