• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Trying to trigger a delayed falling projectile but it's not working quite as intended

Level 3
Joined
Jul 3, 2013
Messages
25
Good people of the Hive, I am once again asking for your support.

First off, the situation: I'm trying to create a spell that summons a falling meteor that lands in target location, dealing damage.

I figured, hey, I could base this off of the summon Infernal spell, just need to set the Stun duration to 0.01 seconds. That worked decently well, if a little funky... but it's functional, and that's what mattered. After that, I just had to remove the model from the Infernal, make it invuln and magic immune, turn off its ability to attack, and throw in a generic expiration timer to clean it up. I didn't wanna add Locust in case it got weird with the "Summoned unit" trigger, but I could also do that instead.

To spice things up, I wanted to add INT scaling to the meteor's damage. This is what I ended up coming up with:

  • Skyfall Trigger Test
    • Events
      • Unit - A unit Spawns a summoned unit
    • Conditions
      • (Unit-type of (Summoned unit)) Equal to Skyfall
    • Actions
      • -------- Skyfall is a custom unit I created based off of the Infernal --------
      • Set SkyfallCaster = (Summoning unit)
      • Set SkyfallDeath = (Summoned unit)
      • Unit - Add a 1.75 second Generic expiration timer to SkyfallDeath
      • Set SkyfallArea = (Position of SkyfallDeath)
      • Set SkyfallPick = (Units within 253.00 of SkyfallArea)
      • Unit Group - Pick every unit in SkyfallPick and do (Actions)
        • Loop - Actions
          • Set SkyfallPick2 = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (SkyfallPick2 belongs to an enemy of (Owner of SkyfallCaster)) Equal to True
              • (SkyfallPick2 is alive) Equal to True
              • (SkyfallPick2 is A structure) Equal to False
              • (SkyfallPick2 is Magic Immune) Equal to False
            • Then - Actions
              • Unit - Cause SkyfallCaster to damage SkyfallPick2, dealing ((1.00 + (0.15 x (Real((Level of Skyfall (Abyss Mage) for SkyfallCaster))))) x (Real((Intelligence of SkyfallCaster (Include bonuses))))) damage of attack type Spells and damage type Magic
              • Special Effect - Create a special effect attached to the origin of SkyfallPick2 using Abilities\Spells\Undead\DeathandDecay\DeathandDecayTarget.mdl
              • Special Effect - Destroy (Last created special effect)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_SkyfallArea)
      • Custom script: call DestroyGroup(udg_SkyfallPick)
I dunno if these have anything to do with it, but here are some parameters that could also be affecting things, though I'm unsure if they actually do:

Data - Duration: 3
This is probably the duration of the summoned "Infernal" - methinks this is irrelevant since I have an expiration time, but I made it longer than the expiration timer just in case. I also tested this with no expiration timer and a Duration of 1.75, nothing seemed to change.

Data - Impact Delay: 1.2
Amount of time it takes for the meteor to fall. 1.2 felt like nice, but this can be changed as needed.

Stats - Buffs: Infernal
This is just the default buff, figured I didn't need to change this since the "Infernal" dies like 0.2 seconds after being summoned

Stats - Duration - Hero: 0.01
Stats - Duration - Normal: 0.01 <-- I figured the previous two only affect the stun duration; changing these numbers seemed to only affect that

The crux of the problem: Y'all might have already guessed it, but the triggered damage occurs on spell cast, not when the dummy Infernal is summoned. I figure that has something to do with the Infernal being already "summoned" as the projectile is falling, though I can't be sure. Adding a "Wait" is obviously not recommended, but I tried it anyway just in case. Of course, that didn't help at all.

My second instinct was to instead summon a dummy unit and make it cast war stomp or something after a Wait, but I thought I'd ask here first to see if y'all have a cleaner solution.
 
Level 25
Joined
Sep 26, 2009
Messages
2,387
I can think of a few approaches:
1) using 'Inferno' ability, react to event 'unit takes damage' and modify damage taken
2) using 'Inferno' ability, react to event 'unit dies' to detect when the summoned infernal died
3) trigger the entire ability your-self using 'Channel' ability as a base
4) same approach as option #1, but base ability off Rain of Fire
5) possibly add a modified 'AoE damage upon death' ability to the summoned unit

For all options I will use simple variables, so it will not be MUI nor MPI, but it can be MUI using hashtables, indexing, unit indexer, etc.

For options #1 and #2 you need to track who the summoner was (to know how much INT the caster had). Something like this:
  • Untitled Trigger 001
    • Events
      • Unit - A unit Spawns a summoned unit
    • Conditions
      • (Unit-type of (Summoned unit)) Equal to Infernal
    • Actions
      • Set VariableSet summoners_int = (Intelligence of (Summoning unit) (Include bonuses))
Ad option #1
This would use the fact that the meteor's impact deals damage of attack type 'spells' and damage type 'force' by the summoned unit. If you are using for example Bribe's damage detection system, then you can use variables he already provides for attack/damage type check.
If you are on Reforged, then you can use the generic 'damage taken' event, but you will need a bit of jass/custom script in the trigger.
Something like this:
  • Takes Damage
    • Events
      • Unit - A unit Takes damage
    • Conditions
      • (Unit-type of (Damage source)) Equal to Infernal
    • Actions
      • Custom script: if BlzGetEventAttackType() != ATTACK_TYPE_NORMAL or BlzGetEventDamageType() != DAMAGE_TYPE_FORCE then
      • Skip remaining actions
      • Custom script: endif
      • Event Response - Set Damage of Unit Damaged Event to ((Damage taken) + (Real(summoners_int)))
The custom script just ends the trigger prematurely if attack type is not spells or damage type is not force (do note that attack type 'spells' in object editor is actually 'attack_type_normal' in jass).
If the attack/damage type match then it increases the damage taken by the unit (in my trigger this just adds summoner's INT attribute).

Ad option #2
This would leverage the fact that the summoned unit dies right after landing. Since you have the point of impact (the location of the dying unit) then you can just pick all nearby units and damage them again, this time using the summoner's int attribute.
  • Summoned Unit Dies
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Infernal
    • Actions
      • Set VariableSet loc = (Position of (Triggering unit))
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within your_range of loc matching (conditions like it is living enemy, etc.) and do (Actions)
        • Loop - Actions
          • Unit - Cause (Triggering unit) to damage (Picked unit), dealing (Real(summoners_int)) damage of attack type Spells and damage type Normal
      • Custom script: call RemoveLocation(udg_loc)
Ad option #3
From what you wrote, it sounds more like you just want to have the effect of a falling infernal meteor that then deals damage based off caster's INT.
What you could do then is to create a dummy ability that does nothing - for that, the Channel ability is perfect - and create two triggers for this.
One trigger fires when the caster starts casting the ability - you create the effect of falling meteor here and also starts a count down timer expiring in 1 second.
Second trigger fires when the countdown timer expired - here you remove the falling meteor effect, pick all units in the AoE and deal any damage you want.

Ad option #4
This would work same way as option #1 - you would detect when unit takes damage and modify that damage. The Rain of Fire ability does not stun enemies and you can update its data fields 'Number of shards' and 'Number of waves' to just drop a single fiery meteor. For the effect itself, you would need a custom 'Effect' created in the Buffs/Effects tab which would use the inferno meteor effect.

The advantage here is that the damage is dealt by the caster itself, so you have direct access to the caster's INT (no need for second trigger that react to a summon being spawned).
Disadvantage is that rain of fire deals attack type Spells and damage type Fire, which can be quite common.
You can also consider using Blizzard spell instead, which deals attack type Spells, damage type Cold.
However if your unit deals such damage type via other spells, then it may be hard to detect if damage was taken from the Meteor or something else

Ad option #5
This options only applies if you are on Reforged.
I didn't test this, but maybe you could try to leverage the 'AoE damage upon death' ability.
The flow would be as follows:
1. Detect when unit spawns summoned unit
2. Add to the summoned unit the modiifed AoE damage ability
3. Using triggers, modify the ability's damage to match the caster's INT
4. See if it works :D

Reforged added trigger actions under 'Ability' section which allows you to modify an ability for specific unit. The thing is that it is not guaranteed to work. Editing some fields via trigger works, some don't.
The action would looks something like this
  • Ability - Set Ability: (Unit: (Summoned unit)'s Ability with Ability Code: your_modified_AoE_ability )'s Real Level Field: Full Damage Amount ('Dda2') of Level: 0 to (Real((the INT of caster)))
 
Level 3
Joined
Jul 3, 2013
Messages
25

I'm gonna be completely honest, I 100% forgot that a unit that ends its Summoning duration counts as "unit dies". It works, thanks!

I'm also using a very outdated version of World Editor (cough questionably legal copy of WC3 cough) so I can't use option 1, sadly, but I appreciate the suggestion :grin:
 
Top