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

[Trigger] Making a tether ability. The markers for the chain aren't MUI for some reason?

Status
Not open for further replies.
Level 4
Joined
Jun 10, 2019
Messages
69
Hi all,

Today I'm working on an ability I'm calling "Cosmic Link." The caster can target either an ally or an enemy, forming a tether between them. 10 markers appear between the caster and the target, showing the tether. An allied target is healed over time while an enemy target is damaged over time so long as the tether holds (if the target and the caster move too far apart, the tether breaks early).

Here are my triggers:

  • Cosmic Link Hashtable Creation
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set VariableSet CLink_Hashtable = (Last created hashtable)
  • Cosmic Link Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Cosmic Link
    • Actions
      • Set VariableSet CLink_Instances = (CLink_Instances + 1)
      • Set VariableSet CLink_Caster[CLink_Instances] = (Triggering unit)
      • Set VariableSet CLink_Target[CLink_Instances] = (Target unit of ability being cast)
      • Set VariableSet CLink_TempPoint[1] = (Position of CLink_Caster[CLink_Instances])
      • Set VariableSet CLink_TempPoint[2] = (Position of CLink_Target[CLink_Instances])
      • Set VariableSet CLink_TempDistance = (Distance between CLink_TempPoint[1] and CLink_TempPoint[2])
      • Set VariableSet CLink_TempAngle = (Angle from CLink_TempPoint[1] to CLink_TempPoint[2])
      • For each (Integer CLink_MarkerInteger) from 1 to 10, do (Actions)
        • Loop - Actions
          • Set VariableSet CLink_TempPoint[3] = (CLink_TempPoint[1] offset by (((Real(CLink_MarkerInteger)) x CLink_TempDistance) / 11.00) towards CLink_TempAngle degrees.)
          • Unit - Create 1 Cosmic Link Marker Dummy for (Owner of CLink_Caster[CLink_Instances]) at CLink_TempPoint[3] facing CLink_TempPoint[2]
          • Hashtable - Save Handle Of(Last created unit) as CLink_MarkerInteger of CLink_Instances in CLink_Hashtable.
      • Set VariableSet CLink_HealingDamage[CLink_Instances] = ((5.00 x (Real((Intelligence of CLink_Caster[CLink_Instances] (Include bonuses))))) + (30.00 x (Real((Level of Cosmic Link for CLink_Caster[CLink_Instances])))))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (CLink_Caster[CLink_Instances] has buff Astral Infusion (Buff)) Equal to True
        • Then - Actions
          • Set VariableSet CLink_HealingDamage[CLink_Instances] = (CLink_HealingDamage[CLink_Instances] + (((Real((Level of Astral Infusion for CLink_Caster[CLink_Instances]))) x 30.00) + (3.00 x (Real((Intelligence of CLink_Caster[CLink_Instances] (Include bonuses)))))))
          • Unit - Remove Astral Infusion (Buff) buff from CLink_Caster[CLink_Instances]
          • Special Effect - Create a special effect attached to the overhead of CLink_Caster[CLink_Instances] using Abilities\Spells\Human\HolyBolt\HolyBoltSpecialArt.mdl
          • Special Effect - Destroy (Last created special effect)
        • Else - Actions
      • Custom script: call RemoveLocation(udg_CLink_TempPoint[1])
      • Custom script: call RemoveLocation(udg_CLink_TempPoint[2])
      • Custom script: call RemoveLocation(udg_CLink_TempPoint[3])
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CLink_Instances Equal to 1
        • Then - Actions
          • Trigger - Turn on Cosmic Link Loop <gen>
        • Else - Actions
  • Cosmic Link Loop
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • For each (Integer CLink_Loop) from 1 to CLink_Instances, do (Actions)
        • Loop - Actions
          • Set VariableSet CLink_TempPoint[1] = (Position of CLink_Caster[CLink_Loop])
          • Set VariableSet CLink_TempPoint[2] = (Position of CLink_Target[CLink_Loop])
          • Set VariableSet CLink_TempDistance = (Distance between CLink_TempPoint[1] and CLink_TempPoint[2])
          • Set VariableSet CLink_TempAngle = (Angle from CLink_TempPoint[1] to CLink_TempPoint[2])
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between CLink_TempPoint[1] and CLink_TempPoint[2]) Greater than or equal to 750.00
              • (CLink_Target[CLink_Loop] has buff Cosmic Link ) Equal to True
            • Then - Actions
              • Unit - Remove Cosmic Link buff from CLink_Target[CLink_Loop]
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (CLink_Target[CLink_Loop] has buff Cosmic Link ) Equal to True
            • Then - Actions
              • For each (Integer CLink_MarkerInteger) from 1 to 10, do (Actions)
                • Loop - Actions
                  • Set VariableSet CLink_TempPoint[3] = (CLink_TempPoint[1] offset by (((Real(CLink_MarkerInteger)) x CLink_TempDistance) / 11.00) towards CLink_TempAngle degrees.)
                  • Unit - Move (Load CLink_MarkerInteger of CLink_Loop in CLink_Hashtable.) instantly to CLink_TempPoint[3]
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (CLink_Target[CLink_Loop] belongs to an ally of (Owner of CLink_Caster[CLink_Loop]).) Equal to True
                • Then - Actions
                  • Unit - Set life of CLink_Target[CLink_Loop] to ((Life of CLink_Target[CLink_Loop]) + (CLink_HealingDamage[CLink_Loop] / 300.00))
                • Else - Actions
                  • Unit - Set life of CLink_Target[CLink_Loop] to ((Life of CLink_Target[CLink_Loop]) - (CLink_HealingDamage[CLink_Loop] / 300.00))
            • Else - Actions
              • For each (Integer CLink_MarkerInteger) from 1 to 10, do (Actions)
                • Loop - Actions
                  • Unit - Kill (Load CLink_MarkerInteger of CLink_Loop in CLink_Hashtable.)
              • Set VariableSet CLink_Caster[CLink_Loop] = CLink_Caster[CLink_Instances]
              • Set VariableSet CLink_Target[CLink_Loop] = CLink_Target[CLink_Instances]
              • Set VariableSet CLink_HealingDamage[CLink_Loop] = CLink_HealingDamage[CLink_Instances]
              • Set VariableSet CLink_Loop = (CLink_Loop - 1)
              • Set VariableSet CLink_Instances = (CLink_Instances - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CLink_Instances Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
          • Custom script: call RemoveLocation(udg_CLink_TempPoint[1])
          • Custom script: call RemoveLocation(udg_CLink_TempPoint[2])
          • Custom script: call RemoveLocation(udg_CLink_TempPoint[3])
The damage/healing is working perfectly, but the problem is that, once the first tether comes to an end, the second tether's markers stop moving and won't die when the second tether comes to an end.

Any help would be greatly appreciated!

Thanks!
 
Last edited:
Level 14
Joined
Feb 7, 2020
Messages
387
Is this a leftover? I don't think it is needed:

Code:
Set VariableSet CLink_Loop = (CLink_Loop - 1)

My immediate code smell is something with the indexing. I'm glancing at this:

Code:
Unit - Kill (Load CLink_MarkerInteger of CLink_Loop in CLink_Hashtable.)

When the first effect ends, the next run of the loop . .

Code:
For each (Integer CLink_Loop) from 1 to CLink_Instances, do (Actions)

. . needs to do 1,2 in order to grab the 2nd hash index (since it was saved at index 2), but the instance count gets reduced by 1 after the 1st spell ends (I assume this is triggered by the buff's duration ending or the distance allowed being exceeded). So, the loop is checking for 1,1 on the 2nd run, therefore hash index 2 won't be hit.

Hope this is it. I struggle with reading GUI these days!
 
Level 4
Joined
Jun 10, 2019
Messages
69
@Planetary thank you for your suggestion, but unfortunately, I don't think that that's the problem. I tried removing the

  • Set VariableSet CLink_Loop = (CLink_Loop - 1)
but that didn't solve the problem. :(

I also just checked the 2 other abilities I made using hashtables, and upon further inspection, they're not MUI either. The non-hashtable skillshots, however, are working perfectly.

Any recommendations would be greatly appreciated!

Edit: @Planetary I do, however, agree that it seems to be a problem with the indexing.

Edit 2: I tried removing the entire de-index:

  • Set VariableSet CLink_Caster[CLink_Loop] = CLink_Caster[CLink_Instances]
  • Set VariableSet CLink_Target[CLink_Loop] = CLink_Target[CLink_Instances]
  • Set VariableSet CLink_HealingDamage[CLink_Loop] = CLink_HealingDamage[CLink_Instances]
  • Set VariableSet CLink_Loop = (CLink_Loop - 1)
  • Set VariableSet CLink_Instances = (CLink_Instances - 1)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • CLink_Instances Equal to 0
    • Then - Actions
      • Trigger - Turn off (This trigger)
    • Else - Actions
and that got it working, so that must be where the problem lies.
 
Last edited:
Level 14
Joined
Feb 7, 2020
Messages
387
@Planetary thank you for your suggestion, but unfortunately, I don't think that that's the problem. I tried removing the

  • Set VariableSet CLink_Loop = (CLink_Loop - 1)
but that didn't solve the problem. :(

(...)

I ran into this problem when I made my first array-based missile script. As a basic, amateur fix, what I did was track the maximum instances created as a separate integer which I would use as the max loop value, and that maximum integer value would only reset when the instances of the spell became 0 (checked whenever an instance of the spell ends, i.e. where you set instances - 1). I actually don't think this is the best way (garbage collection considerations) but it is the simplest way.

With other solutions, you're getting into more complex territory. For example--I'm used to Lua tables--but in JASS I imagine what you could do is resort the hash every time the 1st spell ends (since the first instance should always be the oldest). i.e. when spell 1 ends, move spell 2 to the 1st position (repeating this for every item that exists in the hash). However, this would require resorting any global arrays or converting every data point into hashtable values.

I attached some references to my ugly code to give you an idea of the "entity count". This could be mimic'd in your GUI.

edit: I forgot to add, you would also add a boolean variable for if the spell instance was destroyed, so you can efficiently skip any trigger code for that spell instance while going through the instances loop (set that boolean to true when it has ended; and don't forget to set new instance values to false i.e. resetting their destroy check).
 

Attachments

  • reference 2.png
    reference 2.png
    28.7 KB · Views: 22
  • reference.png
    reference.png
    64.1 KB · Views: 43
  • reference 3.png
    reference 3.png
    63.3 KB · Views: 44
Last edited:
Level 4
Joined
Jun 10, 2019
Messages
69
I may have actually figured something out that appears to be working. It may cause me to run into problems, but so far so good.

Right before the index, I added:

  • For each (Integer CLink_MarkerInteger) from 1 to 10, do (Actions)
    • Loop - Actions
      • Hashtable - Save Handle Of(Load CLink_MarkerInteger of CLink_Instances in CLink_Hashtable.) as CLink_MarkerInteger of CLink_Loop in CLink_Hashtable.
and that seems to have done the trick. I did the same on the other 2 hashtable (hopefully) MUI abilities, and they both seem to be working (although the damage of one of them seems to be bugged?).

Thank you for your help!

Edit: I got the damage bug fixed
 
Last edited:
Status
Not open for further replies.
Top