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

Albatross Dive Attack

Dive Attack

wwpyn2J.png

2unqArl.gif


Description

The Albatross dives onto an organic target, taking a bite out of them, dealing minor damage and healing itself.

The albatross repeats attacking the same target until given a new order.


Right-click to activate/deactivate auto-attacking

304sBTT.png

This is an idea inspired by the attack animation of the Albatross, which looks like this:
nADL9lG.png


The ability mimics regular auto-attacks. The bird wil automatically dive onto enemies to damage them. Like auto-attacks, they'll stick to attacking one target until given a new order.

Since this "attack" has a lot of movement, I also decided to add an option to turn the attack off, so I made it an auto-cast.


Triggers

  • Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Dive Attack config --------
      • -------- Change these values as you will --------
      • Set DiveAttackDamageMin = 8.00
      • Set DiveAttackDamageMax = 12.00
      • Set DiveAttackHealMultiplier = 1.00
      • Set DiveAttackChaseDur = 3.00
      • Set DiveAttackMoveSpeed = 0.00
      • Set DiveAttackSpeedMultiplier = 1.50
      • Set DiveAttackCooldownMin = 0.80
      • Set DiveAttackCooldownMax = 1.20
      • -------- Dive Attack pre-loading stuff --------
      • Custom script: set udg_DiveAttackGroupAutocast = CreateGroup()
      • Custom script: set udg_DiveAttackGroup = CreateGroup()
      • Wait 1.00 seconds
      • Set TempLoc = (Center of (Playable map area))
      • Custom script: call PlaySoundAtPoint("Sound\\Units\\Combat\\WoodLightBashFlesh1.wav", GetLocationX(udg_TempLoc), GetLocationY(udg_TempLoc), 1.0, 1)
      • Custom script: call PlaySoundAtPoint("Sound\\Units\\Combat\\WoodLightBashFlesh2.wav", GetLocationX(udg_TempLoc), GetLocationY(udg_TempLoc), 1.0, 1)
      • Custom script: call PlaySoundAtPoint("Sound\\Units\\Combat\\WoodLightBashFlesh3.wav", GetLocationX(udg_TempLoc), GetLocationY(udg_TempLoc), 1.0, 1)
      • Custom script: call RemoveLocation(udg_TempLoc)
  • Dive Attack order checks
    • Events
      • Unit - A unit Is issued an order with no target
      • Unit - A unit Is issued an order targeting an object
      • Unit - A unit Is issued an order targeting a point
    • Conditions
      • (Level of Dive Attack for (Triggering unit)) Greater than 0
    • Actions
      • Set DiveAttackUnit[1] = (Ordered unit)
      • -------- Turning autocast off --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Issued order) Equal to (Order(holdposition))
              • (Issued order) Equal to (Order(uncoldarrows))
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (DiveAttackUnit[1] is in DiveAttackGroupAutocast) Equal to True
            • Then - Actions
              • Unit - Add Cargo Hold (Orc Burrow) to DiveAttackUnit[1]
              • Unit Group - Remove DiveAttackUnit[1] from DiveAttackGroupAutocast
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Issued order) Not equal to (Order(uncoldarrows))
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                  • Unit - Order DiveAttackUnit[1] to Neutral Naga Sea Witch - Deactivate Frost Arrows
                  • Trigger - Turn on (This trigger)
                • Else - Actions
            • Else - Actions
        • Else - Actions
      • -------- Turning autocast on --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Issued order) Equal to (Order(coldarrows))
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (DiveAttackUnit[1] is in DiveAttackGroupAutocast) Equal to False
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DiveAttackUnit[1] is in DiveAttackGroup) Equal to False
                • Then - Actions
                  • Unit - Remove Cargo Hold (Orc Burrow) from DiveAttackUnit[1]
                • Else - Actions
              • Unit Group - Add DiveAttackUnit[1] to DiveAttackGroupAutocast
            • Else - Actions
        • Else - Actions
      • -------- right-click smart cast, and manual cast --------
      • Custom script: if GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER then
      • Set DiveAttackUnit[2] = (Target unit of issued order)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DiveAttackUnit[1] is Snared) Equal to False
          • (DiveAttackUnit[1] is Polymorphed) Equal to False
          • (DiveAttackUnit[1] is Ethereal) Equal to False
          • Or - Any (Conditions) are true
            • Conditions
              • (Issued order) Equal to (Order(coldarrowstarg))
              • And - All (Conditions) are true
                • Conditions
                  • (Issued order) Equal to (Order(smart))
                  • (DiveAttackUnit[2] belongs to an enemy of (Owner of DiveAttackUnit[1])) Equal to True
                  • (DiveAttackUnit[2] is A structure) Equal to False
                  • (DiveAttackUnit[2] is Mechanical) Equal to False
                  • (DiveAttackUnit[2] is A flying unit) Equal to False
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (DiveAttackUnit[1] is in DiveAttackGroup) Equal to False
            • Then - Actions
              • Unit - Remove Cargo Hold (Orc Burrow) from DiveAttackUnit[1]
              • Trigger - Turn off (This trigger)
              • Unit - Order DiveAttackUnit[1] to Attack DiveAttackUnit[2]
              • Trigger - Turn on (This trigger)
            • Else - Actions
        • Else - Actions
          • -------- Disarming when other unit-targeted orders are given while autocast is off --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (DiveAttackUnit[1] is in DiveAttackGroupAutocast) Equal to False
            • Then - Actions
              • Unit - Add Cargo Hold (Orc Burrow) to DiveAttackUnit[1]
            • Else - Actions
      • Custom script: endif
      • -------- Disarming when point-targeted orders are given while autocast is off --------
      • Custom script: if GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER then
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DiveAttackUnit[1] is in DiveAttackGroupAutocast) Equal to False
        • Then - Actions
          • Unit - Add Cargo Hold (Orc Burrow) to DiveAttackUnit[1]
        • Else - Actions
      • Custom script: endif
      • -------- Stop attacking current target when order is given after hitting the target. --------
      • For each (Integer DiveAttackLoop) from 1 to DiveAttackIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • DiveAttackUnit[1] Equal to DiveAttackCaster[DiveAttackLoop]
              • DiveAttackState[DiveAttackLoop] Equal to 3
              • (Issued order) Not equal to (Order(uncoldarrows))
              • (Issued order) Not equal to (Order(coldarrows))
            • Then - Actions
              • Set DiveAttackCanceled[DiveAttackLoop] = True
            • Else - Actions
      • Set DiveAttackUnit[1] = No unit
      • Set DiveAttackUnit[2] = No unit
  • Dive Attack start
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • And - All (Conditions) are true
        • Conditions
          • (Level of Dive Attack for (Attacking unit)) Greater than 0
          • ((Attacking unit) is Snared) Equal to False
    • Actions
      • Set DiveAttackIndex = (DiveAttackIndex + 1)
      • Set DiveAttackCaster[DiveAttackIndex] = (Attacking unit)
      • Set DiveAttackTarget[DiveAttackIndex] = (Attacked unit)
      • Set DiveAttackHeight[DiveAttackIndex] = (Default flying height of DiveAttackCaster[DiveAttackIndex])
      • Set DiveAttackCanceled[DiveAttackIndex] = False
      • Set DiveAttackState[DiveAttackIndex] = 1
      • Set DiveAttackDamage[DiveAttackIndex] = (Random real number between DiveAttackDamageMin and DiveAttackDamageMax)
      • Set DiveAttackHeal[DiveAttackIndex] = (DiveAttackDamage[DiveAttackIndex] x DiveAttackHealMultiplier)
      • Set DiveAttackMaxDur[DiveAttackIndex] = DiveAttackChaseDur
      • Set DiveAttackCooldownTimer[DiveAttackIndex] = (Random real number between DiveAttackCooldownMin and DiveAttackCooldownMax)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DiveAttackMoveSpeed Less than or equal to 0.00
        • Then - Actions
          • Set DiveAttackSpeed[DiveAttackIndex] = ((Current movement speed of DiveAttackCaster[DiveAttackIndex]) x DiveAttackSpeedMultiplier)
        • Else - Actions
          • Set DiveAttackSpeed[DiveAttackIndex] = DiveAttackMoveSpeed
      • Unit - Add Cargo Hold (Orc Burrow) to DiveAttackCaster[DiveAttackIndex]
      • Trigger - Turn off Dive Attack order checks <gen>
      • Unit - Order DiveAttackCaster[DiveAttackIndex] to Neutral Naga Sea Witch - Frost Arrows DiveAttackTarget[DiveAttackIndex]
      • Trigger - Turn on Dive Attack order checks <gen>
      • Unit Group - Add DiveAttackCaster[DiveAttackIndex] to DiveAttackGroup
      • If (DiveAttackIndex Equal to 1) then do (Trigger - Turn on Dive Attack effect <gen>) else do (Do nothing)
      • Animation - Play DiveAttackCaster[DiveAttackIndex]'s attack animation
  • Dive Attack effect
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer DiveAttackLoop) from 1 to DiveAttackIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (DiveAttackTarget[DiveAttackLoop] is alive) Equal to False
                  • (DiveAttackCaster[DiveAttackLoop] is alive) Equal to False
                  • DiveAttackMaxDur[DiveAttackLoop] Less than or equal to 0.00
                  • And - All (Conditions) are true
                    • Conditions
                      • DiveAttackState[DiveAttackLoop] Equal to 1
                      • (Current order of DiveAttackCaster[DiveAttackLoop]) Not equal to (Order(coldarrowstarg))
                  • (DiveAttackCaster[DiveAttackLoop] is Snared) Equal to True
                  • (DiveAttackCaster[DiveAttackLoop] is Stunned) Equal to True
                  • (DiveAttackCaster[DiveAttackLoop] is Polymorphed) Equal to True
                  • (DiveAttackCaster[DiveAttackLoop] is Sleeping) Equal to True
                  • (DiveAttackCaster[DiveAttackLoop] is Ethereal) Equal to True
                  • (DiveAttackCaster[DiveAttackLoop] is hidden) Equal to True
                  • (DiveAttackCaster[DiveAttackLoop] is paused) Equal to True
                  • (DiveAttackTarget[DiveAttackLoop] is hidden) Equal to True
                  • (DiveAttackTarget[DiveAttackLoop] is A flying unit) Equal to True
            • Then - Actions
              • Set DiveAttackCanceled[DiveAttackLoop] = True
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • DiveAttackState[DiveAttackLoop] Equal to 1
            • Then - Actions
              • Set DiveAttackMaxDur[DiveAttackLoop] = (DiveAttackMaxDur[DiveAttackLoop] - 0.03)
              • Set DiveAttackLocCursor = (Position of DiveAttackTarget[DiveAttackLoop])
              • Set DiveAttackLocCasterCurrent = (Position of DiveAttackCaster[DiveAttackLoop])
              • Set DiveAttackDist = (Distance between DiveAttackLocCasterCurrent and DiveAttackLocCursor)
              • Set DiveAttackDir = (Angle from DiveAttackLocCasterCurrent to DiveAttackLocCursor)
              • Set DiveAttackLocCasterNew = (DiveAttackLocCasterCurrent offset by (DiveAttackSpeed[DiveAttackLoop] x 0.03) towards DiveAttackDir degrees)
              • Set DiveAttackHeightLoss = (Min((((Current flying height of DiveAttackCaster[DiveAttackLoop]) - 50.00) / (DiveAttackDist / (DiveAttackSpeed[DiveAttackLoop] x 0.03))), 40.00))
              • Set DiveAttackHeight[DiveAttackLoop] = ((DiveAttackHeight[DiveAttackLoop] - DiveAttackHeightLoss) + 0.00)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • DiveAttackDist Greater than (DiveAttackSpeed[DiveAttackLoop] x 0.03)
                  • (DiveAttackCaster[DiveAttackLoop] is Snared) Equal to False
                • Then - Actions
                  • Custom script: call SetUnitX(udg_DiveAttackCaster[udg_DiveAttackLoop], GetLocationX(udg_DiveAttackLocCasterNew))
                  • Custom script: call SetUnitY(udg_DiveAttackCaster[udg_DiveAttackLoop], GetLocationY(udg_DiveAttackLocCasterNew))
                • Else - Actions
              • Unit - Make DiveAttackCaster[DiveAttackLoop] face DiveAttackDir over 0.00 seconds
              • Animation - Change DiveAttackCaster[DiveAttackLoop] flying height to DiveAttackHeight[DiveAttackLoop] at 0.00
              • Custom script: call RemoveLocation(udg_DiveAttackLocCasterCurrent)
              • Custom script: call RemoveLocation(udg_DiveAttackLocCasterNew)
              • Custom script: call RemoveLocation(udg_DiveAttackLocCursor)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Or - Any (Conditions) are true
                    • Conditions
                      • (Current flying height of DiveAttackCaster[DiveAttackLoop]) Less than 50.00
                      • DiveAttackCanceled[DiveAttackLoop] Equal to True
                • Then - Actions
                  • Set DiveAttackState[DiveAttackLoop] = 2
                • Else - Actions
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • DiveAttackState[DiveAttackLoop] Equal to 2
            • Then - Actions
              • Set DiveAttackLocCursor = (Position of DiveAttackTarget[DiveAttackLoop])
              • Set DiveAttackLocCasterCurrent = (Position of DiveAttackCaster[DiveAttackLoop])
              • Set DiveAttackLocCasterNew = (DiveAttackLocCasterCurrent offset by (Min(((Current movement speed of DiveAttackCaster[DiveAttackLoop]) x (DiveAttackCooldownTimer[DiveAttackLoop] - 0.10)), (Current acquisition range of DiveAttackCaster[DiveAttackLoop]))) towards (DiveAttackDir + (Random re
              • Animation - Change DiveAttackCaster[DiveAttackLoop] flying height to (Default flying height of DiveAttackCaster[DiveAttackLoop]) at (Default flying height of DiveAttackCaster[DiveAttackLoop])
              • Animation - Play DiveAttackCaster[DiveAttackLoop]'s walk animation
              • Trigger - Turn off Dive Attack order checks <gen>
              • Unit - Order DiveAttackCaster[DiveAttackLoop] to Move To DiveAttackLocCasterNew
              • Trigger - Turn on Dive Attack order checks <gen>
              • Custom script: call RemoveLocation(udg_DiveAttackLocCursor)
              • Custom script: call RemoveLocation(udg_DiveAttackLocCasterCurrent)
              • Custom script: call RemoveLocation(udg_DiveAttackLocCasterNew)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • DiveAttackDist Less than 100.00
                  • DiveAttackCanceled[DiveAttackLoop] Equal to False
                • Then - Actions
                  • Set DiveAttackAudioInt = (Random integer number between 0 and 2)
                  • Unit - Cause DiveAttackCaster[DiveAttackLoop] to damage DiveAttackTarget[DiveAttackLoop], dealing DiveAttackDamage[DiveAttackLoop] damage of attack type Pierce and damage type Normal
                  • Unit - Set life of DiveAttackCaster[DiveAttackLoop] to ((Life of DiveAttackCaster[DiveAttackLoop]) + DiveAttackHeal[DiveAttackLoop])
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • DiveAttackAudioInt Equal to 0
                    • Then - Actions
                      • Custom script: call PlaySoundAtPoint("Sound\\Units\\Combat\\WoodLightBashFlesh1.wav", GetLocationX(udg_DiveAttackLocCursor), GetLocationY(udg_DiveAttackLocCursor), 1.0, 127)
                    • Else - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • DiveAttackAudioInt Equal to 1
                        • Then - Actions
                          • Custom script: call PlaySoundAtPoint("Sound\\Units\\Combat\\WoodLightBashFlesh2.wav", GetLocationX(udg_DiveAttackLocCursor), GetLocationY(udg_DiveAttackLocCursor), 1.0, 127)
                        • Else - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • DiveAttackAudioInt Equal to 2
                            • Then - Actions
                              • Custom script: call PlaySoundAtPoint("Sound\\Units\\Combat\\WoodLightBashFlesh3.wav", GetLocationX(udg_DiveAttackLocCursor), GetLocationY(udg_DiveAttackLocCursor), 1.0, 127)
                            • Else - Actions
                  • Special Effect - Create a special effect attached to the chest of DiveAttackTarget[DiveAttackLoop] using Objects\Spawnmodels\Critters\Albatross\CritterBloodAlbatross.mdl
                  • Special Effect - Destroy (Last created special effect)
                • Else - Actions
              • Set DiveAttackState[DiveAttackLoop] = 3
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • DiveAttackState[DiveAttackLoop] Equal to 3
            • Then - Actions
              • Set DiveAttackCooldownTimer[DiveAttackLoop] = (DiveAttackCooldownTimer[DiveAttackLoop] - 0.03)
              • Special Effect - Create a special effect attached to the overhead of DiveAttackCaster[DiveAttackLoop] using Abilities\Weapons\LordofFlameMissile\LordofFlameMissile.mdl
              • Special Effect - Destroy (Last created special effect)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • DiveAttackCooldownTimer[DiveAttackLoop] Less than or equal to 0.00
                • Then - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (DiveAttackCaster[DiveAttackLoop] is in DiveAttackGroupAutocast) Equal to True
                    • Then - Actions
                      • Unit - Remove Cargo Hold (Orc Burrow) from DiveAttackCaster[DiveAttackLoop]
                    • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Current order of DiveAttackCaster[DiveAttackLoop]) Equal to (Order((null)))
                      • DiveAttackCanceled[DiveAttackLoop] Equal to False
                      • (DiveAttackTarget[DiveAttackLoop] is alive) Equal to True
                    • Then - Actions
                      • Trigger - Turn off Dive Attack order checks <gen>
                      • Unit - Remove Cargo Hold (Orc Burrow) from DiveAttackCaster[DiveAttackLoop]
                      • Unit - Order DiveAttackCaster[DiveAttackLoop] to Stop
                      • Unit - Order DiveAttackCaster[DiveAttackLoop] to Attack DiveAttackTarget[DiveAttackLoop]
                      • Trigger - Turn on Dive Attack order checks <gen>
                    • Else - Actions
                  • Unit Group - Remove DiveAttackCaster[DiveAttackLoop] from DiveAttackGroup
                  • Set DiveAttackCaster[DiveAttackLoop] = DiveAttackCaster[DiveAttackIndex]
                  • Set DiveAttackHeight[DiveAttackLoop] = DiveAttackHeight[DiveAttackIndex]
                  • Set DiveAttackCooldownTimer[DiveAttackLoop] = DiveAttackCooldownTimer[DiveAttackIndex]
                  • Set DiveAttackTarget[DiveAttackLoop] = DiveAttackTarget[DiveAttackIndex]
                  • Set DiveAttackState[DiveAttackLoop] = DiveAttackState[DiveAttackIndex]
                  • Set DiveAttackCanceled[DiveAttackLoop] = DiveAttackCanceled[DiveAttackIndex]
                  • Set DiveAttackSpeed[DiveAttackLoop] = DiveAttackSpeed[DiveAttackIndex]
                  • Set DiveAttackMaxDur[DiveAttackLoop] = DiveAttackMaxDur[DiveAttackIndex]
                  • Set DiveAttackDamage[DiveAttackLoop] = DiveAttackDamage[DiveAttackIndex]
                  • Set DiveAttackHeal[DiveAttackLoop] = DiveAttackHeal[DiveAttackIndex]
                  • Set DiveAttackIndex = (DiveAttackIndex - 1)
                  • Set DiveAttackLoop = (DiveAttackLoop - 1)
                  • If (DiveAttackIndex Equal to 0) then do (Trigger - Turn off (This trigger)) else do (Do nothing)
                • Else - Actions
            • Else - Actions


Additional info:

  • The spell relies on the attack command. It's based on Frost Arrows.
  • Since it relies on auto-attacks, it pretty much follows the same rules. It works even with taunt, or attacks forced by other triggers.
  • The bird technically never attacks its target. Upon attack begin, it gets disarmed. The disarm lasts until the custom attack cooldown finishes.
  • When toggling off (or giving Hold Position command), the Albatross gets disarmed as well. The disarm is removed when turning auto-cast on again
  • However, right-clicking or manually casting on a target still works, so you don't need to have auto-cast on to use it.
  • The dive can be canceled at any time, by giving the bird any order during it.


Changelog:


v1.0 (11.nov.18)
  • uploaded

v1.1 (12.nov.18)
  • Changed damage to have a damage range (min max)
  • Changed heal to be a percentage of damage dealt (similar to how lifesteal works)
  • Changed how the speed works. Speed can be set in the config. Setting speed to 0 automatically uses the unit's current speed, multiplied by the multiplier. Setting it to any other value, uses that value instead, ignoring the multiplier.
  • Added configs for damage (min/max), heal multiplier, speed, speed multiplier, chase duration, and cooldown (min/max)
  • The order checks trigger now uses variables for the ordered unit and the targeted unit of issued order.
v1.2 (12.nov.18)
  • Fixed negative speed values breaking the ability (setting to negative defaults it to current movement speed)
  • Fixed the dive animation sometimes getting stuck
  • Fixed the birds sometimes returning to default flying height without horizontal movement
v1.3 (13.nov.18)
  • Fixed the caster getting stuck and unable to attack when killing an enemy with a long-ranged dive
  • Fixed issued attack orders (with autocast off) breaking the autocast logic when done while ensnared/entangled/hexed/ethereal
v1.4 (13.nov.18)
  • Fixed the target unit variable in the order check trigger
  • Fixed the heal and damage indexes not being recycled
  • Fixed the hit sound not playing since the last version
  • Removed some debug stuff I forgot to remove in the previous version


Albatross Dive Attack Icon: Here

Contents

Albatross Dive Attack (Map)

Reviews
MyPad
A minor thing, you can actually remove the wait in the Config Trigger and preload them directly, as far as how I've tested the map. There is/are a (few) variable/s whose purpose/s are quite ambiguous, and I'll list it below (and the questions that may...
Level 14
Joined
Oct 19, 2014
Messages
187
Awesome dude,, looking good and useful,, but I have suggestion,, in trigger ordering,, I think it is a mess mentioning units inside of a native many times,, so I recommend to set them in a variable to reduce the memory usage :)

and put some description and configuration for us to edit the amounts and happenings,, for example the amount of heal,, where can we edit the amount? :|
 
Last edited:
Level 8
Joined
Jul 6, 2012
Messages
65
but I have suggestion,, in trigger ordering,, I think it is a mess mentioning units inside of a native many times,, so I recommend to set them in a variable to reduce the memory usage :)

I am using variables for all units (caster and target), I don't know what you mean with this.

and put some description and configuration for us to edit the amounts and happenings,, for example the amount of heal,, where can we edit the amount? :|

They are in the "Dive Attack start" trigger. It's explained in the map as well, and there is a comment showing which variables can be edited. Duration, speed, and cooldown have to be there because they are indexed. I could move damage, heal and speed multiplier to map init, but then the changable variables would be in 2 different locations, which I didn't want.

  • Dive Attack start
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • And - All (Conditions) are true
        • Conditions
          • (Level of Dive Attack for (Attacking unit)) Greater than 0
          • ((Attacking unit) is Snared) Equal to False
    • Actions
      • -------- Fixed variables, do not change these. --------
      • Set DiveAttackIndex = (DiveAttackIndex + 1)
      • Set DiveAttackCaster[DiveAttackIndex] = (Attacking unit)
      • Set DiveAttackTarget[DiveAttackIndex] = (Attacked unit)
      • Set DiveAttackHeight[DiveAttackIndex] = (Default flying height of DiveAttackCaster[DiveAttackIndex])
      • Set DiveAttackCanceled[DiveAttackIndex] = False
      • Set DiveAttackState[DiveAttackIndex] = 1
      • -------- Other variabes, change values as you will. --------
      • Set DiveAttackDamage = 10.00 // damage
      • Set DiveAttackHeal = 10.00 // heal
      • Set DiveAttackMaxDur[DiveAttackIndex] = 3.00 // max chase duration before the bird gives up
      • Set DiveAttackCooldownTimer[DiveAttackIndex] = (Random real number between 0.80 and 1.20) // attack cooldown
      • Set DiveAttackSpeed[DiveAttackIndex] = (Current movement speed of DiveAttackCaster[DiveAttackIndex]) // dive speed (set to a fixed value if you want)
      • Set DiveAttackSpeedMultiplier = 1.50// dive speed multiplier (if you use a fixed speed for the above value, set this to 1)
 
Level 14
Joined
Oct 19, 2014
Messages
187
I am using variables for all units (caster and target), I don't know what you mean with this.



They are in the "Dive Attack start" trigger. It's explained in the map as well, and there is a comment showing which variables can be edited. Duration, speed, and cooldown have to be there because they are indexed. I could move damage, heal and speed multiplier to map init, but then the changable variables would be in 2 different locations, which I didn't want.

  • Dive Attack start
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • And - All (Conditions) are true
        • Conditions
          • (Level of Dive Attack for (Attacking unit)) Greater than 0
          • ((Attacking unit) is Snared) Equal to False
    • Actions
      • -------- Fixed variables, do not change these. --------
      • Set DiveAttackIndex = (DiveAttackIndex + 1)
      • Set DiveAttackCaster[DiveAttackIndex] = (Attacking unit)
      • Set DiveAttackTarget[DiveAttackIndex] = (Attacked unit)
      • Set DiveAttackHeight[DiveAttackIndex] = (Default flying height of DiveAttackCaster[DiveAttackIndex])
      • Set DiveAttackCanceled[DiveAttackIndex] = False
      • Set DiveAttackState[DiveAttackIndex] = 1
      • -------- Other variabes, change values as you will. --------
      • Set DiveAttackDamage = 10.00 // damage
      • Set DiveAttackHeal = 10.00 // heal
      • Set DiveAttackMaxDur[DiveAttackIndex] = 3.00 // max chase duration before the bird gives up
      • Set DiveAttackCooldownTimer[DiveAttackIndex] = (Random real number between 0.80 and 1.20) // attack cooldown
      • Set DiveAttackSpeed[DiveAttackIndex] = (Current movement speed of DiveAttackCaster[DiveAttackIndex]) // dive speed (set to a fixed value if you want)
      • Set DiveAttackSpeedMultiplier = 1.50// dive speed multiplier (if you use a fixed speed for the above value, set this to 1)
What I mean is the "Dive Attack order checks"
 
Level 8
Joined
Jul 6, 2012
Messages
65
Speed, damages, heals and durations must be in a separate trigger "Configuration"
  • Configs
    • Events
      • Map Initialization
    • Conditions
    • Actions
      • Set DiveAttackDur = 3.00
  • Set DiveAttackMaxDur[DiveAttackIndex] = DiveAttackDur
EDIT: Also cool idea 5/5!!

Speed: With my current implementation, it must be set upon cast, and not pre-set on init, because it's set to the unit's current movement speed. MS slows do affect the speed of it

As for the others, I planned to make them randomized as well, similar to how attack damage of units is usually "randomized" between a min and a max.

I still could throw them all into the init, though.

What I mean is the "Dive Attack order checks"

I see. yes, I can use variables there.

----

Updating tomorrow.
 
At this point, it would be ideal for you to implement this in JASS, based on how the trigger actions are arranged and categorized.

Spell Mechanics:

Notes:

  • In trigger Dive Attack order checks, it would be best to save (Ordered unit) into a variable, so that you save some execution time (calling a function is slower than reading a variable).

  • A proper config trigger could be set up outside of the trigger Dive Attack Start. This is to save some write-ups, which comes down to optimization.

Suggestions:

  • To resolve the horizontal lift bug where the albatross doesn't go anywhere, make the albatross go to a projected location with the same trajectory as the first location of the albatross before the attack.

  • Project the movement of the albatross upon ascending as an arc. (This is only a challenge-based suggestion).

Status:

  • Awaiting Update
 
Level 8
Joined
Jul 6, 2012
Messages
65
Updated.

Added unit variables to the order check trigger

Moved dmg, heal, speed, cd and duration to config

Slightly Changed how dmg, heal and speed work
* Added min/max damage
* The heal is now a % of damage dealt
* The movement speed now defaults to current movement speed when the speed value in the config is set to 0. The multiplier is only used when set to 0.
 
Level 8
Joined
Jul 6, 2012
Messages
65
At this point, it would be ideal for you to implement this in JASS, based on how the trigger actions are arranged and categorized.

Spell Mechanics:

Notes:

  • In trigger Dive Attack order checks, it would be best to save (Ordered unit) into a variable, so that you save some execution time (calling a function is slower than reading a variable).

  • A proper config trigger could be set up outside of the trigger Dive Attack Start. This is to save some write-ups, which comes down to optimization.

Suggestions:

  • To resolve the horizontal lift bug where the albatross doesn't go anywhere, make the albatross go to a projected location with the same trajectory as the first location of the albatross before the attack.

  • Project the movement of the albatross upon ascending as an arc. (This is only a challenge-based suggestion).

Status:

  • Awaiting Update

I have basically no experience with jass, so I don't think I could.

As for the 1st suggestion, I already figured out why that happens. I had some unnecessary conditions there which sometimes made the bird skip the move order.

As for suggestion 2, I wanted to keep that part as simple as possible. The ascending is just

  • Animation - Change DiveAttackCaster[DiveAttackLoop] flying height to (Default flying height of DiveAttackCaster[DiveAttackLoop]) at (Default flying height of DiveAttackCaster[DiveAttackLoop])
  • Unit - Order DiveAttackCaster[DiveAttackLoop] to Move To DiveAttackLocCasterNew
I think it's fine. I might consider adding an arc to it though. I'm currently trying to figure out why long-ranged killing dives break it completely.


Edit:

Update 3

I was able to fix the bug by changing the order of events. For some reason, the target dying before changing the loop's state broke it, so now I made it damage after setting the state. I still have no idea why the order would matter here, and why it only happened when it was a long-ranged dive.
 
Last edited:
A minor thing, you can actually remove the wait in the Config Trigger and preload them directly, as far as how I've tested the map.
There is/are a (few) variable/s whose purpose/s are quite ambiguous, and I'll list it below (and the questions that may arise), but I suppose these can be tested out.

udg_DiveAttackMoveSpeed - Does this take movement speed or does this act as some sort of forced movement speed multiplier upon diving?

There are also a couple of things that don't need to be redefined in map initialization, such as the following variables (located in the Config trigger):

udg_DiveAttackGroup
udg_DiveAttackGroupAutocast


Other than that, the spell is ready for approval.

Status:

  • Approved
 
Level 8
Joined
Jul 6, 2012
Messages
65
The sound preloading didn't work for me without the wait, that's why I added it.

----

DiveAttackMoveSpeed is the variable that decides the dive speed. If you set it to 0, it defaults to the caster's current movement speed. If you set it to any positive value, it uses that value instead.

If you set it to 0, you then can use the DiveAttackSpeedMultiplier variable to increase the speed by a percentage.

The variables are explained in the trigger comment.

----

The 2 groups need to be created only once, that's why they are in the config. Where else could I put them?
 
The 2 groups need to be created only once, that's why they are in the config. Where else could I put them?

When a unit group variable is created in the variable editor, it will always hold an empty group. From that, the lines that assign that variable to a group will overwrite the previously stored group handle (which is unnecessary), thus leading to my suggestion of removing that.

About the comments, I did not notice the presence of it within the trigger comment section when giving my review, so my apologies.
 
Level 2
Joined
Jun 9, 2019
Messages
15
So I imported the necessary objects and triggers and somehow the triggeras became disabled and i cant use them....ive changed all the things i needed to in the triggers whats ny issue
 
Top