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

Soul Eaters 1.2

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
So here's my very first resource! Hope you guys enjoy it as much as I enjoyed making it.

Soul Eaters:
Summon Soul Eaters to move around the field and damage enemy units they come in contact with. Soul Eaters explode once the spell ends and damage nearby enemy units.

Pass Damage - 20/25/30
Blast Damage - 50/60/70
Blast AOE - 250
Number of Summons - 10/15/20
Spell Duration - 5 seconds

  • SE Initialization
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- /////CONFIGURABLES\\\\\ --------
      • -------- Base ability --------
      • Set SE_Ability = Soul Eaters
      • -------- ---------------------------- --------
      • -------- Unit type of the summon --------
      • Set SE_Unit_Type = Soul Eater
      • -------- ---------------------------- --------
      • -------- Blast radius --------
      • Set SE_Blast_AOE[1] = 250.00
      • Set SE_Blast_AOE[2] = 250.00
      • Set SE_Blast_AOE[3] = 250.00
      • -------- ---------------------------- --------
      • -------- Amount of damage to enemies in range of the blast --------
      • Set SE_Blast_Dmg[1] = 50.00
      • Set SE_Blast_Dmg[2] = 60.00
      • Set SE_Blast_Dmg[3] = 70.00
      • -------- ---------------------------- --------
      • -------- Attack type used for the blast damage --------
      • Set SE_Blast_Attck_Type = Spells
      • -------- ---------------------------- --------
      • -------- Damage type used for the blast damage --------
      • Set SE_Blast_Dmg_Type = Normal
      • -------- ---------------------------- --------
      • -------- Limit of the range between the enemy and the summon to deal damage --------
      • Set SE_Pass_AOE[1] = 125.00
      • Set SE_Pass_AOE[2] = 125.00
      • Set SE_Pass_AOE[3] = 125.00
      • -------- ---------------------------- --------
      • -------- Amount of damage to enemies in range of summon --------
      • Set SE_Pass_Dmg[1] = 20.00
      • Set SE_Pass_Dmg[2] = 25.00
      • Set SE_Pass_Dmg[3] = 30.00
      • -------- ---------------------------- --------
      • -------- Attack type used for the pass damage --------
      • Set SE_Pass_Attck_Type = Spells
      • -------- ---------------------------- --------
      • -------- Damage type used for the blast damage --------
      • Set SE_Blast_Dmg_Type = Normal
      • -------- ---------------------------- --------
      • -------- Spell duration --------
      • Set SE_Duration[1] = 5.00
      • Set SE_Duration[2] = 5.00
      • Set SE_Duration[3] = 5.00
      • -------- ---------------------------- --------
      • -------- Number of summons --------
      • Set SE_Summon_Number[1] = 10
      • Set SE_Summon_Number[2] = 15
      • Set SE_Summon_Number[3] = 20
      • -------- ---------------------------- --------
      • -------- Effect used for the blast --------
      • Set SE_Blast_Effect = Units\NightElf\Wisp\WispExplode.mdl
      • -------- ---------------------------- --------
      • -------- Effect used for the pass --------
      • Set SE_Pass_Effect = Abilities\Spells\Items\OrbVenom\OrbVenomSpecialArt.mdl
      • -------- ---------------------------- --------
      • -------- \\\\\END OF CONFIGURABLES///// --------
  • SE Start
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to SE_Ability
    • Actions
      • Set SE_Temp_Unit_1 = (Triggering unit)
      • Set SE_Caster_Loc = (Position of SE_Temp_Unit_1)
      • For each (Integer SE_Index_3) from 1 to SE_Summon_Number[(Level of SE_Ability for SE_Temp_Unit_1)], do (Actions)
        • Loop - Actions
          • Unit - Create 1 SE_Unit_Type for (Triggering player) at SE_Caster_Loc facing Default building facing degrees
          • Unit - Add SE_Ability to (Last created unit)
          • Unit - Set level of SE_Ability for (Last created unit) to (Level of SE_Ability for SE_Temp_Unit_1)
          • Set SE_Max_Index = (SE_Max_Index + 1)
          • Set SE_Life_Timer[SE_Max_Index] = SE_Duration[(Level of SE_Ability for SE_Temp_Unit_1)]
          • Set SE_Unit[SE_Max_Index] = (Last created unit)
          • Set SE_Angle[SE_Max_Index] = (Random angle)
          • Set SE_Add[SE_Max_Index] = (Random real number between 3.00 and 6.00)
          • Set SE_Chance[SE_Max_Index] = 200
          • Set SE_Move_Left[SE_Max_Index] = (Random integer number between 0 and 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SE_Loop_On Equal to False
        • Then - Actions
          • Trigger - Turn on SE Move Loop <gen>
          • Set SE_Loop_On = True
        • Else - Actions
      • Custom script: call RemoveLocation(udg_SE_Caster_Loc)
  • SE Move Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer SE_Index) from 1 to SE_Max_Index_2, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SE_Dmg_CD[SE_Index] Less than or equal to 0.00
            • Then - Actions
              • Set SE_Enemy[SE_Index] = SE_Enemy[SE_Max_Index_2]
              • Set SE_Dmg_CD[SE_Index] = SE_Dmg_CD[SE_Max_Index_2]
              • Set SE_Max_Index_2 = (SE_Max_Index_2 - 1)
              • Set SE_Index = (SE_Index - 1)
            • Else - Actions
              • Set SE_Dmg_CD[SE_Index] = (SE_Dmg_CD[SE_Index] - 0.03)
      • For each (Integer SE_Index) from 1 to SE_Max_Index, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SE_Move_Left[SE_Index] Equal to 1
            • Then - Actions
              • Set SE_Summon_Loc = (Position of SE_Unit[SE_Index])
              • Set SE_Summon_Move = (SE_Summon_Loc offset by 20.00 towards SE_Angle[SE_Index] degrees)
              • Unit - Move SE_Unit[SE_Index] instantly to SE_Summon_Move, facing SE_Angle[SE_Index] degrees
              • Set SE_Angle[SE_Index] = (SE_Angle[SE_Index] + SE_Add[SE_Index])
              • Set SE_Roll = (Random integer number between 1 and SE_Chance[SE_Index])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SE_Roll Less than or equal to 1
                • Then - Actions
                  • Set SE_Move_Left[SE_Index] = 0
                  • Set SE_Chance[SE_Index] = 200
                  • Set SE_Add[SE_Index] = (Random real number between 3.00 and 6.00)
                  • Set SE_Angle[SE_Index] = (SE_Angle[SE_Index] - SE_Add[SE_Index])
                • Else - Actions
                  • Set SE_Chance[SE_Index] = (SE_Chance[SE_Index] - 1)
            • Else - Actions
              • Set SE_Summon_Loc = (Position of SE_Unit[SE_Index])
              • Set SE_Summon_Move = (SE_Summon_Loc offset by 20.00 towards SE_Angle[SE_Index] degrees)
              • Unit - Move SE_Unit[SE_Index] instantly to SE_Summon_Move, facing SE_Angle[SE_Index] degrees
              • Set SE_Angle[SE_Index] = (SE_Angle[SE_Index] - SE_Add[SE_Index])
              • Set SE_Roll = (Random integer number between 1 and SE_Chance[SE_Index])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SE_Roll Less than or equal to 1
                • Then - Actions
                  • Set SE_Move_Left[SE_Index] = 1
                  • Set SE_Chance[SE_Index] = 200
                  • Set SE_Add[SE_Index] = (Random real number between 3.00 and 6.00)
                  • Set SE_Angle[SE_Index] = (SE_Angle[SE_Index] + SE_Add[SE_Index])
                • Else - Actions
                  • Set SE_Chance[SE_Index] = (SE_Chance[SE_Index] - 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SE_Max_Index_2 Equal to 0
            • Then - Actions
              • Custom script: set bj_wantDestroyGroup=true
              • Unit Group - Pick every unit in (Units within SE_Pass_AOE[(Level of SE_Ability for SE_Unit[SE_Index])] of SE_Summon_Move) and do (Actions)
                • Loop - Actions
                  • Set SE_Temp_Unit_2 = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (SE_Temp_Unit_2 belongs to an enemy of (Owner of SE_Unit[SE_Index])) Equal to True
                      • (SE_Temp_Unit_2 is alive) Equal to True
                    • Then - Actions
                      • Set SE_Max_Index_2 = (SE_Max_Index_2 + 1)
                      • Set SE_Enemy[SE_Max_Index_2] = SE_Temp_Unit_2
                      • Set SE_Dmg_CD[SE_Max_Index_2] = 0.35
                      • Unit - Cause SE_Unit[SE_Index] to damage SE_Enemy[SE_Max_Index_2], dealing SE_Pass_Dmg[(Level of SE_Ability for SE_Unit[SE_Index])] damage of attack type SE_Pass_Attck_Type and damage type SE_Pass_Dmg_Type
                      • Special Effect - Create a special effect attached to the overhead of SE_Temp_Unit_2 using SE_Pass_Effect
                      • Special Effect - Destroy (Last created special effect)
                    • Else - Actions
            • Else - Actions
              • Custom script: set bj_wantDestroyGroup=true
              • Unit Group - Pick every unit in (Units within SE_Pass_AOE[(Level of SE_Ability for SE_Unit[SE_Index])] of (Center of (Playable map area))) and do (Actions)
                • Loop - Actions
                  • Set SE_Temp_Unit_2 = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (SE_Temp_Unit_2 belongs to an enemy of (Owner of SE_Unit[SE_Index])) Equal to True
                      • (SE_Temp_Unit_2 is alive) Equal to True
                    • Then - Actions
                      • For each (Integer SE_Index_2) from 1 to SE_Max_Index_2, do (Actions)
                        • Loop - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (SE_Enemy[SE_Index_2] is dead) Equal to False
                            • Then - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • SE_Temp_Unit_2 Not equal to SE_Enemy[SE_Index_2]
                                • Then - Actions
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • SE_Index_2 Equal to SE_Max_Index_2
                                    • Then - Actions
                                      • Set SE_Max_Index_2 = (SE_Max_Index_2 + 1)
                                      • Set SE_Enemy[SE_Max_Index_2] = (Picked unit)
                                      • Set SE_Dmg_CD[SE_Max_Index_2] = 0.35
                                      • Set SE_Index_2 = (SE_Index_2 + 1)
                                      • Unit - Cause SE_Unit[SE_Index] to damage SE_Enemy[SE_Index_2], dealing SE_Pass_Dmg[(Level of SE_Ability for SE_Unit[SE_Index])] damage of attack type SE_Pass_Attck_Type and damage type SE_Pass_Dmg_Type
                                      • Special Effect - Create a special effect attached to the overhead of SE_Temp_Unit_2 using SE_Pass_Effect
                                      • Special Effect - Destroy (Last created special effect)
                                    • Else - Actions
                                • Else - Actions
                                  • Set SE_Index_2 = SE_Max_Index_2
                            • Else - Actions
                              • Set SE_Enemy[SE_Index_2] = SE_Enemy[SE_Max_Index_2]
                              • Set SE_Dmg_CD[SE_Index_2] = SE_Dmg_CD[SE_Max_Index_2]
                              • Set SE_Max_Index_2 = (SE_Max_Index_2 - 1)
                              • Set SE_Index_2 = (SE_Index_2 - 1)
                    • Else - Actions
          • Set SE_Life_Timer[SE_Index] = (SE_Life_Timer[SE_Index] - 0.03)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SE_Life_Timer[SE_Index] Less than or equal to 0.00
            • Then - Actions
              • Unit - Kill SE_Unit[SE_Index]
              • Set SE_Death_Loc = (Position of SE_Unit[SE_Index])
              • Special Effect - Create a special effect at SE_Death_Loc using SE_Blast_Effect
              • Special Effect - Destroy (Last created special effect)
              • Custom script: set bj_wantDestroyGroup=true
              • Unit Group - Pick every unit in (Units within SE_Blast_AOE[(Level of SE_Ability for SE_Unit[SE_Index])] of SE_Death_Loc) and do (Actions)
                • Loop - Actions
                  • Set SE_Temp_Unit_3 = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (SE_Temp_Unit_3 belongs to an enemy of (Owner of SE_Unit[SE_Index])) Equal to True
                      • (SE_Temp_Unit_3 is alive) Equal to True
                    • Then - Actions
                      • Unit - Cause SE_Unit[SE_Index] to damage SE_Temp_Unit_3, dealing SE_Blast_Dmg[(Level of SE_Ability for SE_Unit[SE_Index])] damage of attack type SE_Blast_Attck_Type and damage type SE_Blast_Dmg_Type
                    • Else - Actions
              • Set SE_Add[SE_Index] = SE_Add[SE_Max_Index]
              • Set SE_Angle[SE_Index] = SE_Angle[SE_Max_Index]
              • Set SE_Chance[SE_Index] = SE_Chance[SE_Max_Index]
              • Set SE_Move_Left[SE_Index] = SE_Move_Left[SE_Max_Index]
              • Set SE_Unit[SE_Index] = SE_Unit[SE_Max_Index]
              • Set SE_Max_Index = (SE_Max_Index - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SE_Max_Index Equal to 0
                • Then - Actions
                  • Set SE_Loop_On = False
                  • Trigger - Turn off (This trigger)
                • Else - Actions
              • Custom script: call RemoveLocation(udg_SE_Death_Loc)
            • Else - Actions
          • Custom script: call RemoveLocation(udg_SE_Summon_Loc)
          • Custom script: call RemoveLocation(udg_SE_Summon_Move)
How to Import:
1. Right click "Spells Triggers" category to the right and click copy.
2. Open the map you wish to import the spell to.
3. Make sure the "Automatically create unknown variables" is ticked on in File/Preferences/General.
4. Go to the trigger editor, right click anywhere on the right and click on paste.
5. Go to the object editor and create a unit type for the summon. (Make sure it has the same values as a dummy would have except
with a model.)
6. Create the base ability for the spell. (Use a no-target ability.)
7. Set the configurables in the "Initialization" trigger to your liking. (Make sure to also set SE_Ability and SE_Unit_Type to your newly
created ability and unit type.
8. Test
9. ???
10. Profit?

v1.0 - Uploaded spell
v1.1 - Fixed a couple of leaks and made the spell more efficient
v1.2 - Better efficiency and merged SE Move Loop and SE Summon Dies triggers together.


Keywords:
Soul, Eater, Eaters, GUI, Banshee, Blast, Pass, Summon, Summons, No Target
Contents

Soul Eaters (Map)

Reviews
12th Dec 2015 IcemanBo: For long time as NeedsFix. Rejected. 12:09, 5th Jan 2015 IcemanBo: Make the changes noted in this post: http://www.hiveworkshop.com/forums/spells-569/soul-eaters-1-2-a-256660/index2.html#post2604041
Level 13
Joined
Jul 16, 2012
Messages
679
In your Trigger Start

Dont use INTEGER A / B
use Integer var instead

Save the Triggering Unit in a variable "TempUnit"
and use it

In owner of caster
Unit - Create 1 SE_Unit_Type for (Owner of (Triggering unit)) at SE_Caster_Loc facing Default building facing degrees
Change it into this
Unit - Create 1 SE_Unit_Type for Triggering Player at SE_Caster_Loc facing Default building facing degrees

====================

In your Trigger Loop

In your Unit Groups
you must save the Picked Unit in a variable

Inside in your Unit Groups
You have Special Effect Leak
Special Effect - Create a special effect attached to the overhead of (Picked unit) using SE_Pass_Effect\

====================

In your SUMMON DIES Trigger

Save the Triggering Unit in a variable "TempUnit"
and use it

You have Unit Group Leak

Inside in your Unit Group
You must save the Picked Unit in a variable then use it
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
OH MY GOSH!!
attachment.php

Dat banshee has a male voice LOL :xxd:

You made my day bro! Seriously, I was very surprised :D

On topic: cool spell!

  • Unit - Add a SE_Duration[(Level of SE_Ability for SE_Temp_Unit_1)] second Generic expiration timer to (Last created unit)
Don't use it, you should use a timer (in real) which is the lifespan of the spirits. Then substract it by 0.03 (since periodic timer is per 0.03 second) per tick. So you can merge Summon Dies trigger into Move Loop trigger.

Anyway, your trigger should have unique prefix name such as SE_Cast or SEat_Cast.
 

Attachments

  • a.jpg
    a.jpg
    32 KB · Views: 695
Last edited:

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
  • For each (Integer SE_Index_3) from 1 to SE_Summon_Number[(Level of SE_Ability for SE_Temp_Unit_1)], do (Actions)
Store (Level of SE_Ability for SE_Temp_Unit_1) into an array variable.

  • Unit Group - Pick every unit in (Units within SE_Pass_AOE[(Level of SE_Ability for SE_Unit[SE_Index])] of (Center of (Playable map area))) and do (Actions)
You leaked one location there

Other than that, it seems acceptable for me. :)

OFF:
Some of my resources have been burried for more than 5 months lol
 
It was boring in chat room, so edo494 and me decided to review this resource, as you obviously demanded for feedback. :pgrin:

Soul Eaters 1.2 - Review by IcemanBo & edo494

Concept:

The idea is to create random moving 'Soul Eaters', which deal damage to enemies by touching. It reminds of LocustSwarm by CryptLord.
The explosive disappearance at the end of the spell deals extra damage to nearby enemies, and is a good addition.
You could immediatly end the spell and kill Soul Eaters, if the caster/bearer is dead. At least it could be an optional feature.
At the moment the spell itself doesn't have any cooldown and doesn't cost mana. The unit can spam casting, which results in an overpowered ability.
I know the user can change it himself in object editor, but your default example should have adequate settings and values.
Furthermore if I read "Soul Eaters" I expect it to work with died units in any kind of way, but well that's really minor and subjective.

Code:

  • -------- Attack type used for the pass damage --------
  • Set SE_Pass_Attck_Type = Spells
  • -------- ---------------------------- --------
  • -------- Damage type used for the blast damage --------
  • Set SE_Blast_Dmg_Type = Normal
  • [/stable]
->
  • -------- Attack type used for the pass damage --------
  • Set SE_Pass_Attck_Type = Spells
  • -------- ---------------------------- --------
  • -------- Damage type used for the pass damage --------
  • Set SE_Pass_Dmg_Type = Normal
  • [/stable]
^Pay attention on the damage type.
In cast trigger immediatly store "LastCreatedUnit" into the variable, and use it in further actions to win performance.
Why do you add the base ability to each dummy? There is no sense in doing it.
  • Unit Group - Pick every unit in (Units within SE_Pass_AOE[(Level of SE_Ability for SE_Unit[SE_Index])] of (Center of (Playable map area))) and do (Actions)[/stable]
^(Center of (Playable map area)) -> SE_Summon_Move.
If you use If/Then/Else avoid having exactly same actions in "Then - Actions" AND "Else - Actions". Or move these actions before or after the If-statement.
Instead of using "Owner of SE_Unit[SE_Index]", store TriggeringPlayer into a variable in cast trigger. SE_Owner[SE_Index].
You store all affected enemies into a unit variable. You have to null these unit variables, when you don't need them anymore, else you leak.
Instead of "SE_Move_Left" integer variable, and changing it between 0 and 1, you can use a boolean variable "SE_Turn" and set it to true/false.
The offset for Soul Eater's movement is constant 20. It should be configurable, and it would be user friendly if he could give it a offset/second value, and then you would re-calculate the value for your system, depending of the periodic timeout.
( Your 20 offset in periodic event would be 667 speed for the user, for example.)
The "Roll" variable is not needed. Directly compare the correct expression in your condition.
The attack damage timeout for the Soul Eaters is 0.35, which is hardcoded. It could be stored into a variable in the initialization trigger.
Attachment points should be configurable.
  • Set SE_Add[SE_Max_Index] = (Random real number between 3.00 and 6.00)
  • Set SE_Chance[SE_Max_Index] = 200[/stable]
^Example of which I can't imagine the sense of the varibales, because of the non-informative names. (Or you can add a short comment)
Btw for your naming..., using multiple underscopes in the variable name can make it more unreadable and just lengthen the code. I think "prefix_variableName" is a good convention for GUI code.
"SE_Index_3" variable has actually not much to do with an index. It's used within a loop, as normal tmpInteger.
Short and informative comments in main loop would be helpful in terms of a guide.
Visuals:

The banshee as model looks good. It's movement behaviour is fitting and looking smooth.
The tooltip does provide all important information. The icon is also matching.
The spell is based on battle roar. Once the unit casts the spell, it gets the battle roar buff, and corresponding attachment effect over it's head. Fix this.

Conclusion:

All in all the spell looks good and might be useful. However, there are some minor mistakes that should be fixed, and some others that could be improved.
It is a good try for your first submission, go on like this. :)

Rating: 3/5

 
Top