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

[Spell] Making Forked Lightning a healing spell

Status
Not open for further replies.
Level 1
Joined
Apr 26, 2019
Messages
5
Greetings

Some time ago, I began working on my first big project and usually I find the necessary tutorials or work around the encountered issues myself, yet I feel lost regarding this one. Some tutorials displayed options which seemed to be impossible since the editor doesn't offer the desired solution...

The result I want to get is a healing spell which acts like the forked lightning ability: It is cast by the hero, hits - let's say 3 allies - and heals by an amount dependant on the level of the ability. I also wanted to meddle with scaling the power of spells with the caster's stats but this still seems too advanced for me at this stage.

If I missed an already existing thread on this forum, describing exactly what I am looking for, I apologize. I feel like I have gotten blind to reason at this point.

Thanks in advance,

Mr. Socky
 
Level 39
Joined
Feb 27, 2007
Messages
4,992
Change the spell’s targets allowed to match something like the Alchemist or Voodoo Doctor healing abilities. Hold shift and double click the damage fields to allow negative numbers, then give it negative damage equal to the healing you want.

If you want to scale damage with attributes you will have to trigger the entire spell yourself. That’s just the nature of stat based damage.
 
Level 8
Joined
Nov 9, 2011
Messages
326
Change the spell’s targets allowed to match something like the Alchemist or Voodoo Doctor healing abilities. Hold shift and double click the damage fields to allow negative numbers, then give it negative damage equal to the healing you want.

If you want to scale damage with attributes you will have to trigger the entire spell yourself. That’s just the nature of stat based damage.
Be wary tho. If u have a damage detection system it will fuck the spell up. If you do. Best would be to trigger it.
 
Level 1
Joined
Apr 26, 2019
Messages
5
Change the spell’s targets allowed to match something like the Alchemist or Voodoo Doctor healing abilities. Hold shift and double click the damage fields to allow negative numbers, then give it negative damage equal to the healing you want.

If you want to scale damage with attributes you will have to trigger the entire spell yourself. That’s just the nature of stat based damage.

Thank you very much! This actually worked. Again, the solution to my problem seemed to be ridiculously simple...
What I failed to mention was that I intended the ability to target 3 random targets so that there is no need to click on a specific unit. Is there any easy way to do this?

Otherwise I might ditch the idea completely.

Thanks again in advance!
 
Level 39
Joined
Feb 27, 2007
Messages
4,992
What I failed to mention was that I intended the ability to target 3 random targets so that there is no need to click on a specific unit.
Make a non-target ability based on Channel (tutorial: Spells - Channel) and then dummy cast the real forked lightning skill when that one's cast:

  • Events
    • Unit - A unit starts the effect of an ability
  • Conditions
    • (Ability being cast) equal to Dummy_Heal
  • Actions
    • Set TempPoint = (Position of (Triggering Unit))
    • Set TempGroup = (Units within YOUR_RANGE of TempPoint matching (<put some conditions here to filter targets, allies, etc.>))
    • Unit - Create 1 Dummy at TempPoint facing Default building facing degrees
    • Unit - Add a 1.00 second generic expiration timer to (Last created unit)
    • Unit - Add Forked_Heal to (Last created unit)
    • Unit - Order (Last created unit) to Naga Sea Witch - Forked Lightning (Random unit from TempGroup)
    • Custom script: call RemoveLocation(udg_TempPoint) //change the name to match your variable, keep the udg_ prefix
    • Custom script: call DestroyGroup(udg_TempGroup)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,509
I attached a map with 2 triggered Forked Lightning abilities, one that targets a unit and another that targets a point.

Pyrogasm's method is a lot easier to understand and I'd recommend using that if you're still learning but you should check out my map if you want to learn how to trigger this type of ability and add in stat scaling.

And if you don't understand how to use a Unit Indexer (which I take advantage of in my map) I highly recommend learning how. It's extremely easy, you can literally copy the "Unit Indexer" trigger from my map and put it into your own map and you're done. Just make sure you have turned on "automatically create unknown variables" in the World Editor's "File -> Preferences". After that you can store information to units using their custom value in conjunction with Array variables. This allows you to create custom stats like "Ability Power" and have it work for any unit(s) you want.

Here's the main trigger for the ability:

  • Forked Lightning TARGET POINT
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Forked Lightning (Point)
    • Actions
      • Set Caster = (Casting unit)
      • Set CastPoint = (Position of Caster)
      • Set TargetPoint = (Target point of ability being cast)
      • Set CustomValue = (Custom value of Caster)
      • Set AbilityPower[CustomValue] = (Real((Intelligence of Caster (Include bonuses))))
      • Set HealAmount = (100.00 x (Real((Level of (Ability being cast) for Caster))))
      • Set MaximumTargets = 3
      • Set FinalArea = 300.00
      • Set Angle = 90.00
      • For each (Integer A) from 1 to MaximumTargets, do (Actions)
        • Loop - Actions
          • Set ShortestDistance = 1000000000.00
          • Set ClosestUnit = No unit
          • Custom script: set bj_wantDestroyGroup=true
          • Unit Group - Pick every unit in (Units within FinalArea of TargetPoint) and do (Actions)
            • Loop - Actions
              • Set PickedUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (PickedUnit belongs to an ally of (Owner of Caster)) Equal to True
                  • (PickedUnit is A structure) Equal to False
                  • (PickedUnit is Mechanical) Equal to False
                  • (PickedUnit is alive) Equal to True
                  • PickedUnit Not equal to Caster
                  • (PickedUnit is in ClosestGroup) Equal to False
                • Then - Actions
                  • Set TempPoint = (Position of PickedUnit)
                  • Set relativeAngle = ((Facing of Caster) - (Angle from CastPoint to TempPoint))
                  • Set relativeAngle = (Cos(relativeAngle))
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • relativeAngle Greater than (Cos(Angle))
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Distance between TargetPoint and TempPoint) Less than ShortestDistance
                        • Then - Actions
                          • Set ClosestUnit = PickedUnit
                          • Set ShortestDistance = (Distance between TargetPoint and TempPoint)
                        • Else - Actions
                    • Else - Actions
                  • Custom script: call RemoveLocation(udg_TempPoint)
                • Else - Actions
          • Unit Group - Add ClosestUnit to ClosestGroup
      • Unit Group - Pick every unit in ClosestGroup and do (Actions)
        • Loop - Actions
          • Set PickedUnit = (Picked unit)
          • Set TempPoint = (Position of PickedUnit)
          • Custom script: set bj_lastCreatedLightning = AddLightningEx("FORK", true, GetLocationX(udg_CastPoint), GetLocationY(udg_CastPoint), GetLocationZ(udg_CastPoint) + 60, GetLocationX(udg_TempPoint), GetLocationY(udg_TempPoint), GetLocationZ(udg_TempPoint) + 60)
          • Set LightningTotal = (LightningTotal + 1)
          • Set LightningRemaining = (LightningRemaining + 1)
          • Set Lightning[LightningTotal] = (Last created lightning effect)
          • Set LightningDuration[LightningTotal] = 0.00
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • LightningTotal Equal to 1
            • Then - Actions
              • Trigger - Turn on Lightning Timer <gen>
            • Else - Actions
          • Unit - Set life of PickedUnit to ((Life of PickedUnit) + (HealAmount + AbilityPower[CustomValue]))
          • Special Effect - Create a special effect at TempPoint using Abilities\Weapons\Bolt\BoltImpact.mdl
          • Special Effect - Destroy (Last created special effect)
      • Unit Group - Remove all units from ClosestGroup
      • Custom script: call RemoveLocation(udg_CastPoint)
      • Custom script: call RemoveLocation(udg_TargetPoint)

Edit: Fixed it up and updated the attached map. Everything seems to work properly now.
 

Attachments

  • Forked Lightning Heal Fixed 4.w3x
    30.5 KB · Views: 51
Last edited:
Level 1
Joined
Apr 26, 2019
Messages
5
  • Events
    • Unit - A unit starts the effect of an ability
  • Conditions
    • (Ability being cast) equal to Dummy_Heal
  • Actions
    • Set TempPoint = (Position of (Triggering Unit))
    • Set TempGroup = (Units within YOUR_RANGE of TempPoint matching [U](<put some conditions here to filter targets, allies, etc.>))[/U]
    • Unit - Create 1 Dummy at TempPoint facing Default building facing degrees
    • Unit - Add a 1.00 second generic expiration timer to (Last created unit)
    • Unit - Add Forked_Heal to (Last created unit)
    • Unit - Order (Last created unit) to Naga Sea Witch - Forked Lightning (Random unit from TempGroup)
    • Custom script: call RemoveLocation(udg_TempPoint) //change the name to match your variable, keep the udg_ prefix
    • Custom script: call DestroyGroup(udg_TempGroup)

How do I put those additional conditions into the whole equation? After three hours of re-designing the whole setup of the spell - I tried various other methods - I still couldn't get it to work. Basically I used your variable names for easier understanding with your example. I used the only ability called channel I could find and I think it is the right one. Are there any obvious mistakes I could have made?

If you can't help me with this information alone I will give you screenshots of my attempt.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,509
How do I put those additional conditions into the whole equation? After three hours of re-designing the whole setup of the spell - I tried various other methods - I still couldn't get it to work. Basically I used your variable names for easier understanding with your example. I used the only ability called channel I could find and I think it is the right one. Are there any obvious mistakes I could have made?

If you can't help me with this information alone I will give you screenshots of my attempt.

TempGroup is a Unit Group variable. Set it's value to "Units in Range Matching Condition" and then select "AND" inside of your conditions to add multiple conditions. It should look similar to this:

  • Untitled Trigger 001
    • Events
    • Conditions
    • Actions
      • Set TempGroup = (Units within 300.00 of TempPoint matching ((((Matching unit) is A structure) Equal to True) and ((((Matching unit) is A structure) Equal to True) and (((Matching unit) is A structure) Equal to True))))
Here is an alternate method that I like to use:
  • Untitled Trigger 002
    • Events
    • Conditions
    • Actions
      • 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
              • ((Picked unit) belongs to an ally of (Owner of Caster)) Equal to True
              • ((Picked unit) is A structure) Equal to False
              • ((Picked unit) is Mechanical) Equal to False
              • ((Picked unit) is alive) Equal to True
              • (Picked unit) Not equal to Caster
            • Then - Actions
              • Unit Group - Add (Picked unit) to TempGroup
            • Else - Actions
      • -------- Then create the dummy and add the rest of the actions here --------
^This makes it so you can add conditions without having to deal with the annoying "Condition AND Condition AND Condition" crap. It relieves a lot of future headaches to do it this way since you can easily add and remove conditions. Keep in mind that if you destroy TempGroup this method won't work.

Also, the Channel ability is used as the basis or template for most custom abilities. It's useful because it has options that other abilities don't have and can be given a unique ID so you can give the hero as many Channel abilities as you want and with unique Base Order ID's you can avoid conflicting abilities (Try giving a hero two Forked Lightning abilities, even if you change the icon/name for one they'll still conflict with one another).

What you need to worry about in the Channel ability fields:

-Art Duration: This is for the art fields like Art - Caster and Art - Effect. You don't have to worry about it in this case.

-Base Order ID: This is a unique ID that separates the ability from other abilities. You'll notice if you give a hero two of the same abilities (Two Forked Lightnings for example) they will conflict with one another. Make sure to never use two of the same IDs.

-Disable Other Abilities: This is never really good to use in my experience. This will basically Pause the unit or Disable it until it finishes casting the ability. Pausing units can cause all sorts of problems.

-Follow Through Time: Channel, hence the name, can also be used to make channeling abilities. This follow through time is how long the ability can be channeled. We want to set this to 0 since we're NOT making a channeled ability.

-Options: This is important. The ability needs to be set to Visible so you can actually see it and use it. Also, you can turn on Targeting Image if you want an Area of Effect indicator like Blizzard or Flame Strike have. The rest of the options are rarely used in my experience and we can ignore them for this ability.

-Target Type: Self explanatory, what we can target with the ability. Units, Points, Both. Choose Point in this case.
-------------------------------
And check out my post above, I attached a map file for two triggered Forked Lightning abilities that work great. I'm still tweaking them to behave exactly the same as the original ability, but at the moment they get the job done.
 
Last edited:
Level 1
Joined
Apr 26, 2019
Messages
5
Here is what I made. The dummy is a usual dummy unit without sound sets and without any model etc. It has mana and was assigned the corresponding ability, which on it's own works perfectly.

Untitled Trigger 001
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Channel2
Actions
Set TempPoint = (Position of (Triggering unit))
Set TempGroup = (Units within 600.00 of TempPoint matching ((((Unit-type of (Matching unit)) is A ground unit) Equal to True) and (((Matching unit) is Able to attack ground units) Equal to True)))
Unit - Create 1 FORKEDHEALDUMMY for (Matching player) at TempPoint facing Default building facing degrees
Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
Unit - Add Swamp's Affection to (Last created unit)
Unit - Order (Last created unit) to Neutral Naga Sea Witch - Forked Lightning (Random unit from TempGroup)
Custom script: call RemoveLocation(udg_TempPoint)
Custom script: call DestroyGroup(udg_TempGroup)


For some reason it still doesn't work. Any ideas?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,509
As Aeryn said. I see your line of thinking though. You have a Matching unit, so you'd think you'd have a Matching player. That's not the way it works.

The game will only remember who the "Matching Unit" or "Matching Player" are INSIDE of the action/loop that had the conditions for "matching". In your case this action:

Set TempGroup = (Units within 600.00 of TempPoint matching ((((Unit-type of (Matching unit)) is A ground unit) Equal to True) and (((Matching unit) is Able to attack ground units) Equal to True)))

^Any Action beyond this one will not remember who the Matching Unit is.

Here's some examples of what does and doesn't work:

  • Example
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Channel
    • Actions
      • -------- This DOESN'T Work --------
      • Set TempGroup = (Units in (Playable map area) matching (((Matching unit) is alive) Equal to True))
      • Unit - Create 1 Footman for (Owner of (Matching unit)) at (Center of (Playable map area)) facing Default building facing degrees
      • -------- - --------
      • -------- - --------
      • -------- - --------
      • -------- This Works --------
      • -------- Since the game doesn't remember who the matching unit/owner of matching unit is --------
      • -------- then it won't work if you try to reference them. They don't exist in this context. Instead, reference the owner of the casting/triggering unit --------
      • Set TempGroup = (Units in (Playable map area) matching (((Matching unit) is alive) Equal to True))
      • Unit - Create 1 Footman for (Owner of (Casting unit)) at (Center of (Playable map area)) facing Default building facing degrees
      • -------- - --------
      • -------- - --------
      • -------- - --------
      • -------- This Works and is the best way to make your spells. You can use these variables to remember and reference the units/players in your trigger--------
      • Set Caster = (Casting unit)
      • Set CastingPlayer = (Owner of (Casting unit))
      • Set TempGroup = (Units in (Playable map area) matching (((Matching unit) is alive) Equal to True))
      • Unit - Create 1 Footman for CastingPlayer at (Center of (Playable map area)) facing Default building facing degrees
      • -------- OR --------
      • Unit - Create 1 Footman for (Owner of Caster) at (Center of (Playable map area)) facing Default building facing degrees
      • -------- Both of these work --------
Also, did you base your Dummy unit off of the Locust unit? It's important that your Dummy Unit has the Locust ability and it's Art - Animation - Cast Backswing and Cast Point are set to 0.000 and it's Attacks enabled = None. I attached some pictures with examples. You can also download a custom "Dummy" model on here and import it into your map to use for your Dummy units.
 

Attachments

  • dummy 1.png
    dummy 1.png
    1.4 MB · Views: 37
  • dummy 2.png
    dummy 2.png
    860 KB · Views: 60
Last edited:
Status
Not open for further replies.
Top