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

StarCraft Systems (GUI) - need MUI help!

Status
Not open for further replies.

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706

Hey, I'm trying to convert my (solo) working triggered "spell" to work on multiple units at once using this:
Visualize: Dynamic Indexing

What am I doing wrong? I assume it might be probably related to the last triggers where I am supposed to switch variables.
I'm using 4 loops each with its own integer as the first number to the max limit of the first integer/index used in the first trigger.

What happens is, that after I train more units and they are being attacked, some of them even if not attacked lose their shield when others are attacked. Other things might happen too but I'm not quite sure what.


  • Shield Units Training
    • Events
      • Unit - A unit owned by Player 1 (Red) Finishes training a unit
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of (Trained unit)) Equal to Irregular Footman
        • Then - Actions
          • Set ShieldsIndexInteger = (ShieldsIndexInteger + 1)
          • Set ShieldsTrainedUnit[ShieldsIndexInteger] = (Trained unit)
          • Set ShieldsInitialValue[ShieldsIndexInteger] = 500
          • Set ShieldsMaxValue[ShieldsIndexInteger] = ShieldsInitialValue[ShieldsIndexInteger]
          • Floating Text - Create floating text that reads ((String(ShieldsInitialValue[ShieldsIndexInteger])) + ( / + (String(ShieldsMaxValue[ShieldsIndexInteger])))) above ShieldsTrainedUnit[ShieldsIndexInteger] with Z offset 10.00, using font size 8.00, color (100.00%, 0.00%, 100.00%), and 0.00% transparency
          • Set ShieldsFloatingText[ShieldsIndexInteger] = (Last created floating text)
          • Floating Text - Create floating text that reads ((+ + ((String(ShieldsArmourValue[ShieldsIndexInteger])) + ))) above ShieldsTrainedUnit[ShieldsIndexInteger] with Z offset 10.00, using font size 8.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
          • Set ShieldsArmourFloatingText[ShieldsIndexInteger] = (Last created floating text)
          • -------- Floating Text with Armour --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsArmourValue[ShieldsIndexInteger] Equal to 0
            • Then - Actions
              • Floating Text - Change text of ShieldsArmourFloatingText[ShieldsIndexInteger] to <Empty String> using font size 8.00
            • Else - Actions
          • -------- Check If Ready to Go --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsIndexInteger Equal to 1
            • Then - Actions
              • Trigger - Add to Shield Units Damaged <gen> the event (Unit - ShieldsTrainedUnit[ShieldsIndexInteger] Takes damage)
              • Trigger - Turn on Shields Regenerate <gen>
              • Trigger - Turn on Shield Floating Texts Move <gen>
              • Trigger - Turn on Shield Texts OFF <gen>
            • Else - Actions
        • Else - Actions



  • Shield Units Damaged
    • Events
    • Conditions
    • Actions
      • For each (Integer ShieldsUnitDamagedLoopInteger) from 1 to ShieldsIndexInteger, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] Greater than 0
            • Then - Actions
              • Set DamageSourceUnits[ShieldsUnitDamagedLoopInteger] = (Damage source)
              • Set DamageTakenReals[ShieldsUnitDamagedLoopInteger] = (Damage taken)
              • Unit - Set life of ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger] to ((Life of ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger]) + DamageTakenReals[ShieldsUnitDamagedLoopInteger])
              • -------- Forbidden under 0 Shield Value --------
              • Set ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] = (ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] - (Integer(DamageTakenReals[ShieldsUnitDamagedLoopInteger])))
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] Less than 0
                • Then - Actions
                  • Set ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] = 0
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Greater than (Real(ShieldsInitialValue[ShieldsUnitDamagedLoopInteger]))
                • Then - Actions
                  • Set LifesTaken[ShieldsUnitDamagedLoopInteger] = ((Integer(DamageTakenReals[ShieldsUnitDamagedLoopInteger])) - ShieldsInitialValue[ShieldsUnitDamagedLoopInteger])
                  • Unit - Cause DamageSourceUnits[ShieldsUnitDamagedLoopInteger] to damage ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger], dealing (Real(LifesTaken[ShieldsUnitDamagedLoopInteger])) damage of attack type Chaos and damage type Normal
                • Else - Actions
              • -------- Bonus Shield Armour --------
              • -------- Lower Damage than Armour --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Less than or equal to (Real(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger]))
                • Then - Actions
                  • Set ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] = (ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] + (Integer(DamageTakenReals[ShieldsUnitDamagedLoopInteger])))
                  • Set DamageTakenReals[ShieldsUnitDamagedLoopInteger] = 0.00
                • Else - Actions
              • -------- Higher Damage than Armour --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Greater than (Real(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger]))
                      • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Greater than 0.00
                • Then - Actions
                  • Set DamageTakenReals[ShieldsUnitDamagedLoopInteger] = (DamageTakenReals[ShieldsUnitDamagedLoopInteger] - (Real(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger])))
                • Else - Actions
              • Game - Display to (All players) the text: ((ShieldArmour + (String(ShieldsUnitDamagedLoopInteger))) + (String(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger])))
              • Floating Text - Change text of ShieldsFloatingText[ShieldsUnitDamagedLoopInteger] to ((String(ShieldsInitialValue[ShieldsUnitDamagedLoopInteger])) + ( / + (String(ShieldsMaxValue[ShieldsUnitDamagedLoopInteger])))) using font size 8.00
              • -------- Floating Text with Armour --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ShieldsArmourValue[ShieldsUnitDamagedLoopInteger] Greater than 0
                • Then - Actions
                  • Floating Text - Change text of ShieldsArmourFloatingText[ShieldsUnitDamagedLoopInteger] to ((+ + ((String(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger])) + ))) using font size 8.00
                • Else - Actions
              • Game - Display to (All players) the text: ((DamageTaken + (String(ShieldsUnitDamagedLoopInteger))) + (String(DamageTakenReals[ShieldsUnitDamagedLoopInteger])))
            • Else - Actions



  • Shields Regenerate
    • Events
      • Time - Every 0.50 seconds of game time
    • Conditions
    • Actions
      • For each (Integer ShieldsRegenerateLoopInteger) from 1 to ShieldsIndexInteger, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsInitialValue[ShieldsRegenerateLoopInteger] Less than ShieldsMaxValue[ShieldsRegenerateLoopInteger]
            • Then - Actions
              • Set ShieldsInitialValue[ShieldsRegenerateLoopInteger] = (ShieldsInitialValue[ShieldsRegenerateLoopInteger] + 1)
              • Game - Display to (All players) the text: ((ShieldValue + (String(ShieldsRegenerateLoopInteger))) + (String(ShieldsMaxValue[ShieldsRegenerateLoopInteger])))
              • Floating Text - Change text of ShieldsFloatingText[ShieldsRegenerateLoopInteger] to ((String(ShieldsInitialValue[ShieldsRegenerateLoopInteger])) + ( / + (String(ShieldsMaxValue[ShieldsRegenerateLoopInteger])))) using font size 8.00
            • Else - Actions
          • -------- Surplus Decrease --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsInitialValue[ShieldsRegenerateLoopInteger] Greater than ShieldsMaxValue[ShieldsRegenerateLoopInteger]
            • Then - Actions
              • Set ShieldsInitialValue[ShieldsRegenerateLoopInteger] = (ShieldsInitialValue[ShieldsRegenerateLoopInteger] - 1)
              • Game - Display to (All players) the text: ((ShieldValue + (String(ShieldsRegenerateLoopInteger))) + (String(ShieldsMaxValue[ShieldsRegenerateLoopInteger])))
              • Floating Text - Change text of ShieldsFloatingText[ShieldsRegenerateLoopInteger] to ((String(ShieldsInitialValue[ShieldsRegenerateLoopInteger])) + ( / + (String(ShieldsMaxValue[ShieldsRegenerateLoopInteger])))) using font size 8.00
            • Else - Actions
          • -------- Floating Text with Armour --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsArmourValue[ShieldsRegenerateLoopInteger] Greater than 0
            • Then - Actions
              • Floating Text - Change text of ShieldsArmourFloatingText[ShieldsRegenerateLoopInteger] to ((+ + ((String(ShieldsArmourValue[ShieldsRegenerateLoopInteger])) + ))) using font size 8.00
            • Else - Actions



  • Shield Floating Texts Move
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • For each (Integer FloatingTextsLoopInteger) from 1 to ShieldsIndexInteger, do (Actions)
        • Loop - Actions
          • Set ShieldsTrainedUnitPoint[FloatingTextsLoopInteger] = (Position of ShieldsTrainedUnit[FloatingTextsLoopInteger])
          • Floating Text - Change the position of ShieldsFloatingText[FloatingTextsLoopInteger] to (Center of ((Region centered at ShieldsTrainedUnitPoint[FloatingTextsLoopInteger] with size (0.00, 0.00)) offset by (-45.00, 0.00))) with Z offset 160.00
          • Floating Text - Change the position of ShieldsArmourFloatingText[FloatingTextsLoopInteger] to (Center of ((Region centered at ShieldsTrainedUnitPoint[FloatingTextsLoopInteger] with size (0.00, 0.00)) offset by (70.00, 0.00))) with Z offset 160.00
          • Custom script: call RemoveLocation (udg_ShieldsTrainedUnitPoint[udg_FloatingTextsLoopInteger])



  • Shield Texts OFF
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • For each (Integer FloatingTextsOFFLoopInteger) from 1 to ShieldsIndexInteger, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Dying unit) Equal to ShieldsTrainedUnit[FloatingTextsOFFLoopInteger]
            • Then - Actions
              • Floating Text - Destroy ShieldsFloatingText[FloatingTextsOFFLoopInteger]
              • Floating Text - Destroy ShieldsArmourFloatingText[FloatingTextsOFFLoopInteger]
              • -------- Clean Up --------
              • Set ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger] = ShieldsTrainedUnit[ShieldsIndexInteger]
              • Set ShieldsTrainedUnit[FloatingTextsOFFLoopInteger] = ShieldsTrainedUnit[ShieldsIndexInteger]
              • Set ShieldsTrainedUnit[FloatingTextsLoopInteger] = ShieldsTrainedUnit[ShieldsIndexInteger]
              • Set ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] = ShieldsInitialValue[ShieldsIndexInteger]
              • Set ShieldsInitialValue[ShieldsRegenerateLoopInteger] = ShieldsInitialValue[ShieldsIndexInteger]
              • Set ShieldsMaxValue[ShieldsUnitDamagedLoopInteger] = ShieldsMaxValue[ShieldsIndexInteger]
              • Set ShieldsMaxValue[ShieldsRegenerateLoopInteger] = ShieldsMaxValue[ShieldsIndexInteger]
              • Set ShieldsArmourValue[ShieldsUnitDamagedLoopInteger] = ShieldsArmourValue[ShieldsIndexInteger]
              • Set ShieldsArmourValue[ShieldsRegenerateLoopInteger] = ShieldsArmourValue[ShieldsIndexInteger]
              • Set DamageSourceUnits[ShieldsUnitDamagedLoopInteger] = DamageSourceUnits[ShieldsIndexInteger]
              • Set DamageTakenReals[ShieldsUnitDamagedLoopInteger] = DamageTakenReals[ShieldsIndexInteger]
              • Set LifesTaken[ShieldsUnitDamagedLoopInteger] = LifesTaken[ShieldsIndexInteger]
              • Set ShieldsFloatingText[ShieldsUnitDamagedLoopInteger] = ShieldsFloatingText[ShieldsIndexInteger]
              • Set ShieldsFloatingText[ShieldsRegenerateLoopInteger] = ShieldsFloatingText[ShieldsIndexInteger]
              • Set ShieldsFloatingText[FloatingTextsLoopInteger] = ShieldsFloatingText[ShieldsIndexInteger]
              • Set ShieldsFloatingText[FloatingTextsOFFLoopInteger] = ShieldsFloatingText[ShieldsIndexInteger]
              • Set ShieldsArmourFloatingText[ShieldsUnitDamagedLoopInteger] = ShieldsArmourFloatingText[ShieldsIndexInteger]
              • Set ShieldsArmourFloatingText[ShieldsRegenerateLoopInteger] = ShieldsArmourFloatingText[ShieldsIndexInteger]
              • Set ShieldsArmourFloatingText[FloatingTextsLoopInteger] = ShieldsArmourFloatingText[ShieldsIndexInteger]
              • Set ShieldsArmourFloatingText[FloatingTextsOFFLoopInteger] = ShieldsArmourFloatingText[ShieldsIndexInteger]
              • Set ShieldsIndexInteger = (ShieldsIndexInteger - 1)
              • Set FloatingTextsOFFLoopInteger = (FloatingTextsOFFLoopInteger - 1)
              • Set FloatingTextsLoopInteger = (FloatingTextsLoopInteger - 1)
              • Set ShieldsRegenerateLoopInteger = (ShieldsRegenerateLoopInteger - 1)
              • Set ShieldsUnitDamagedLoopInteger = (ShieldsUnitDamagedLoopInteger - 1)
            • Else - Actions


I've also attached the map file (patch 1.31.1).
I only want to use GUI so don't tell me about JASS (detection systems) please :p





The protoss shield setup is pretty much done. All it needs is to get around normal armour calculation of damage events and a means to make the shield visible on the map similar to the health and mana bars. File updated.

Direct help from: Uncle (post). Basically integrated Bribe's JASS damage detection system and unit indexer among others.

Indirect help from Devalut's Kinetic Barrier and Hermit's model edits (1 & 2).
PurgeandFire's Dynamic Indexing.



Link to .gif: post.

Much input from FeelsGoodMan regarding interceptor movement (post).

A lot of advice from Wrda regarding a MUI version (post).



Basically it needs a MUI version.
Link to .gif: post.



Have to turn it to MUI.

Link to .gif: post.

Credits to Elvendan for his trigger here: Kill Nearest Unit


Still need help with the Carrier+Interceptors-like movement system.
post



Added a remade shield system based on unit get ability reals, mostly: post.
Remade it using real variables instead as advised by Uncle: post.
 

Attachments

  • ProtossShieldsTest.w3x
    93.5 KB · Views: 45
Last edited:
Level 24
Joined
Feb 9, 2009
Messages
1,783
Lets start by doing this:
  • Shield Units Training
    • Events
      • Unit - A unit owned by Player 1 (Red) Finishes training a unit
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of (Trained unit)) Equal to Irregular Footman
        • Then - Actions
          • Set ShieldsIndexInteger = (ShieldsIndexInteger + 1)
          • Set ShieldsTrainedUnit[ShieldsIndexInteger] = (Trained unit)
          • Set ShieldsInitialValue[ShieldsIndexInteger] = 500
          • Set ShieldsMaxValue[ShieldsIndexInteger] = ShieldsInitialValue[ShieldsIndexInteger]
          • Floating Text - Create floating text that reads ((String(ShieldsInitialValue[ShieldsIndexInteger])) + ( / + (String(ShieldsMaxValue[ShieldsIndexInteger])))) above ShieldsTrainedUnit[ShieldsIndexInteger] with Z offset 10.00, using font size 8.00, color (100.00%, 0.00%, 100.00%), and 0.00% transparency
          • Set ShieldsFloatingText[ShieldsIndexInteger] = (Last created floating text)
          • Floating Text - Create floating text that reads ((+ + ((String(ShieldsArmourValue[ShieldsIndexInteger])) + ))) above ShieldsTrainedUnit[ShieldsIndexInteger] with Z offset 10.00, using font size 8.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
          • Set ShieldsArmourFloatingText[ShieldsIndexInteger] = (Last created floating text)
          • -------- Floating Text with Armour --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsArmourValue[ShieldsIndexInteger] Equal to 0
            • Then - Actions
              • Floating Text - Change text of ShieldsArmourFloatingText[ShieldsIndexInteger] to <Empty String> using font size 8.00
            • Else - Actions
          • -------- Check If Ready to Go --------
          • Trigger - Add to Shield Units Damaged <gen> the event (Unit - ShieldsTrainedUnit[ShieldsIndexInteger] Takes damage)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsIndexInteger Equal to 1
            • Then - Actions
              • Trigger - Turn on Shield Units Damaged <gen>
              • Trigger - Turn on Shields Regenerate <gen>
              • Trigger - Turn on Shield Floating Texts Move <gen>
              • Trigger - Turn on Shield Texts OFF <gen>
            • Else - Actions
        • Else - Actions
I moved
  • Trigger - Add to Shield Units Damaged <gen> the event (Unit - ShieldsTrainedUnit[ShieldsIndexInteger] Takes damage)
out so it doesn't only trigger when the index starts but instead on every unit.


But now all the units seem to share the same shield value....
I'll keep looking

ETA: according to your damage trigger it simply attacks all units currently in the index!
need to single out the damaged unit (but I'm not sure if there is a "Damage Target")

ETA2: Huh (triggering unit) works! I added an ifandthen with (IS TRIGGER UNIT = SHIELDTRAINEDUNIT?) and it seems to work!
  • Shield Units Damaged
    • Events
    • Conditions
    • Actions
      • For each (Integer ShieldsUnitDamagedLoopInteger) from 1 to ShieldsIndexInteger, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Triggering unit) Equal to ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger]
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] Greater than 0
                • Then - Actions
                  • Set DamageSourceUnits[ShieldsUnitDamagedLoopInteger] = (Damage source)
                  • Set DamageTakenReals[ShieldsUnitDamagedLoopInteger] = (Damage taken)
                  • Unit - Set life of ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger] to ((Life of ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger]) + DamageTakenReals[ShieldsUnitDamagedLoopInteger])
                  • -------- Forbidden under 0 Shield Value --------
                  • Set ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] = (ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] - (Integer(DamageTakenReals[ShieldsUnitDamagedLoopInteger])))
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] Less than 0
                    • Then - Actions
                      • Set ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] = 0
                    • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Greater than (Real(ShieldsInitialValue[ShieldsUnitDamagedLoopInteger]))
                    • Then - Actions
                      • Set LifesTaken[ShieldsUnitDamagedLoopInteger] = ((Integer(DamageTakenReals[ShieldsUnitDamagedLoopInteger])) - ShieldsInitialValue[ShieldsUnitDamagedLoopInteger])
                      • Unit - Cause DamageSourceUnits[ShieldsUnitDamagedLoopInteger] to damage ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger], dealing (Real(LifesTaken[ShieldsUnitDamagedLoopInteger])) damage of attack type Chaos and damage type Normal
                    • Else - Actions
                  • -------- Bonus Shield Armour --------
                  • -------- Lower Damage than Armour --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Less than or equal to (Real(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger]))
                    • Then - Actions
                      • Set ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] = (ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] + (Integer(DamageTakenReals[ShieldsUnitDamagedLoopInteger])))
                      • Set DamageTakenReals[ShieldsUnitDamagedLoopInteger] = 0.00
                    • Else - Actions
                  • -------- Higher Damage than Armour --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • And - All (Conditions) are true
                        • Conditions
                          • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Greater than (Real(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger]))
                          • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Greater than 0.00
                    • Then - Actions
                      • Set DamageTakenReals[ShieldsUnitDamagedLoopInteger] = (DamageTakenReals[ShieldsUnitDamagedLoopInteger] - (Real(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger])))
                    • Else - Actions
                  • Game - Display to (All players) the text: ((ShieldArmour + (String(ShieldsUnitDamagedLoopInteger))) + (String(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger])))
                  • Floating Text - Change text of ShieldsFloatingText[ShieldsUnitDamagedLoopInteger] to ((String(ShieldsInitialValue[ShieldsUnitDamagedLoopInteger])) + ( / + (String(ShieldsMaxValue[ShieldsUnitDamagedLoopInteger])))) using font size 8.00
                  • -------- Floating Text with Armour --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ShieldsArmourValue[ShieldsUnitDamagedLoopInteger] Greater than 0
                    • Then - Actions
                      • Floating Text - Change text of ShieldsArmourFloatingText[ShieldsUnitDamagedLoopInteger] to ((+ + ((String(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger])) + ))) using font size 8.00
                    • Else - Actions
                  • Game - Display to (All players) the text: ((DamageTaken + (String(ShieldsUnitDamagedLoopInteger))) + (String(DamageTakenReals[ShieldsUnitDamagedLoopInteger])))
                • Else - Actions
            • Else - Actions
 
Last edited:

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
But now all the units seem to share the same shield value....
Yeah, that's the basic problem for some reason :|
ETA: according to your damage trigger it simply attacks all units currently in the index!
Weird. Shouldn't it damage them one by one depending on which unit is being damaged? The event checks the index through arrays so the index cannot be all the numbers at once :| can it? I've set the array size of each array based variable to the max.
ETA2: Huh (triggering unit) works! I added an ifandthen with (IS TRIGGER UNIT = SHIELDTRAINEDUNIT?) and it seems to work!
What the frenzied footman... so it needs a double check?



EDIT:
Moved the Add New Event trigger:

  • Shield Units Training
    • Events
      • Unit - A unit owned by Player 1 (Red) Finishes training a unit
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of (Trained unit)) Equal to Irregular Footman
        • Then - Actions
          • Set ShieldsIndexInteger = (ShieldsIndexInteger + 1)
          • Set ShieldsTrainedUnit[ShieldsIndexInteger] = (Trained unit)
          • Set ShieldsInitialValue[ShieldsIndexInteger] = 500
          • Set ShieldsMaxValue[ShieldsIndexInteger] = ShieldsInitialValue[ShieldsIndexInteger]
          • Floating Text - Create floating text that reads ((String(ShieldsInitialValue[ShieldsIndexInteger])) + ( / + (String(ShieldsMaxValue[ShieldsIndexInteger])))) above ShieldsTrainedUnit[ShieldsIndexInteger] with Z offset 10.00, using font size 8.00, color (100.00%, 0.00%, 100.00%), and 0.00% transparency
          • Set ShieldsFloatingText[ShieldsIndexInteger] = (Last created floating text)
          • Floating Text - Create floating text that reads ((+ + ((String(ShieldsArmourValue[ShieldsIndexInteger])) + ))) above ShieldsTrainedUnit[ShieldsIndexInteger] with Z offset 10.00, using font size 8.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
          • Set ShieldsArmourFloatingText[ShieldsIndexInteger] = (Last created floating text)
          • -------- Floating Text with Armour --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsArmourValue[ShieldsIndexInteger] Equal to 0
            • Then - Actions
              • Floating Text - Change text of ShieldsArmourFloatingText[ShieldsIndexInteger] to <Empty String> using font size 8.00
            • Else - Actions
          • -------- Check If Ready to Go --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsIndexInteger Equal to 1
            • Then - Actions
              • Trigger - Add to Shield Units Damaged <gen> the event (Unit - ShieldsTrainedUnit[ShieldsIndexInteger] Takes damage)
              • Trigger - Turn on Shields Regenerate <gen>
              • Trigger - Turn on Shield Floating Texts Move <gen>
              • Trigger - Turn on Shield Texts OFF <gen>
            • Else - Actions
        • Else - Actions


And added the triggering unit condition

  • Shield Units Damaged
    • Events
    • Conditions
    • Actions
      • For each (Integer ShieldsUnitDamagedLoopInteger) from 1 to ShieldsIndexInteger, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Triggering unit) Equal to ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger]
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] Greater than 0
                • Then - Actions
                  • Set DamageSourceUnits[ShieldsUnitDamagedLoopInteger] = (Damage source)
                  • Set DamageTakenReals[ShieldsUnitDamagedLoopInteger] = (Damage taken)
                  • Unit - Set life of ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger] to ((Life of ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger]) + DamageTakenReals[ShieldsUnitDamagedLoopInteger])
                  • -------- Forbidden under 0 Shield Value --------
                  • Set ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] = (ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] - (Integer(DamageTakenReals[ShieldsUnitDamagedLoopInteger])))
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] Less than 0
                    • Then - Actions
                      • Set ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] = 0
                    • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Greater than (Real(ShieldsInitialValue[ShieldsUnitDamagedLoopInteger]))
                    • Then - Actions
                      • Set LifesTaken[ShieldsUnitDamagedLoopInteger] = ((Integer(DamageTakenReals[ShieldsUnitDamagedLoopInteger])) - ShieldsInitialValue[ShieldsUnitDamagedLoopInteger])
                      • Unit - Cause DamageSourceUnits[ShieldsUnitDamagedLoopInteger] to damage ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger], dealing (Real(LifesTaken[ShieldsUnitDamagedLoopInteger])) damage of attack type Chaos and damage type Normal
                    • Else - Actions
                  • -------- Bonus Shield Armour --------
                  • -------- Lower Damage than Armour --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Less than or equal to (Real(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger]))
                    • Then - Actions
                      • Set ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] = (ShieldsInitialValue[ShieldsUnitDamagedLoopInteger] + (Integer(DamageTakenReals[ShieldsUnitDamagedLoopInteger])))
                      • Set DamageTakenReals[ShieldsUnitDamagedLoopInteger] = 0.00
                    • Else - Actions
                  • -------- Higher Damage than Armour --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • And - All (Conditions) are true
                        • Conditions
                          • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Greater than (Real(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger]))
                          • DamageTakenReals[ShieldsUnitDamagedLoopInteger] Greater than 0.00
                    • Then - Actions
                      • Set DamageTakenReals[ShieldsUnitDamagedLoopInteger] = (DamageTakenReals[ShieldsUnitDamagedLoopInteger] - (Real(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger])))
                    • Else - Actions
                  • Game - Display to (All players) the text: ((ShieldArmour + (String(ShieldsUnitDamagedLoopInteger))) + (String(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger])))
                  • Floating Text - Change text of ShieldsFloatingText[ShieldsUnitDamagedLoopInteger] to ((String(ShieldsInitialValue[ShieldsUnitDamagedLoopInteger])) + ( / + (String(ShieldsMaxValue[ShieldsUnitDamagedLoopInteger])))) using font size 8.00
                  • -------- Floating Text with Armour --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ShieldsArmourValue[ShieldsUnitDamagedLoopInteger] Greater than 0
                    • Then - Actions
                      • Floating Text - Change text of ShieldsArmourFloatingText[ShieldsUnitDamagedLoopInteger] to ((+ + ((String(ShieldsArmourValue[ShieldsUnitDamagedLoopInteger])) + ))) using font size 8.00
                    • Else - Actions
                  • Game - Display to (All players) the text: ((DamageTaken + (String(ShieldsUnitDamagedLoopInteger))) + (String(DamageTakenReals[ShieldsUnitDamagedLoopInteger])))
                • Else - Actions
            • Else - Actions


But the shield value is still shared. See the video:
Uploadfiles.io - ProtossShieldsWarcraftIIITest.mp4
 
Last edited:
Level 24
Joined
Feb 9, 2009
Messages
1,783
hmm, mine plays completely differently than yours...
Oh I turned all the triggers off in the initial start try that.

ETA: Move the highlighted item out of the if & then, see attached (Protossshebles.png)
 

Attachments

  • deepstrasz' protoss shield test 2019-08-12.w3x
    35.6 KB · Views: 55
  • protossshebles.png
    protossshebles.png
    89.1 KB · Views: 82
Last edited:

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
Use a Unit Indexer. You can make this a lot better by using Custom Value instead of all of those For Each Integer Loops. Also, why no Damage Detection System? It would make this much easier :p

Anyway, your main issue is these lines of code in your death trigger:
  • ShieldsIndexInteger = (ShieldsIndexInteger - 1)
  • //And the other variables that you reduce by 1
The problem: Whenever a Footman dies your ShieldsIndexInteger and the rest of those variables (ShieldLoop/TextLoop/etc) are reduced by 1.
So let's say we start the map and create 3 Footman.
Footman[1]
Footman[2]
Footman[3]
After creating the 3rd Footman, ShieldsIndexInteger will be = 3.

Then let's say Footman[2] dies. You subtract 1 from all of your Integer variables. ShieldsIndexInteger/ShieldLoop/TextLoop are all now = 2. However, Footman[3] is still alive but it's been removed from the loop.
  • For each (Integer FloatingTextsOFFLoopInteger) from 1 to ShieldsIndexInteger, do (Actions)
This is now only looping from 1 to 2, skipping Footman[3].
 

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
Anyway, your main issue is these lines of code in your death trigger:
Hey, but I tried to eliminate the dying unit, not those alive, similarly to:
Visualize: Dynamic Indexing

If I disable all the last part with Text OFF, the game text debug shows that multiple units are being hit when the last footman is being damaged.
It seems to be working until, for some reason, some footmen come out with armour text too. It takes the value of the shield and it starts regenerating :\ Of course armour doesn't work in this context, it's not considered.

The clean up is necessary to act as some sort of leak removal.
So, I'm not sure how to fix it so that the dead footmen are excluded and their variables taken by new trained ones.
 
Last edited:

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
I edited your map and added a Unit Indexer and adjusted your code so it would work using Unit Indexing instead of Loops. I think this is much better and will perform way better. Instead of having to loop through possibly 100's of units you can instead avoid that entirely using a Unit Indexer.

And if you don't wish to use this method here are some things you'll need to fix in your version:
1.
  • Unit - Cause DamageSourceUnits[ShieldsUnitDamagedLoopInteger] to damage ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger], dealing (Real(LifesTaken[ShieldsUnitDamagedLoopInteger])) damage of attack type Chaos and damage type Normal
This action will trigger the Damage Event trigger AGAIN. Turn Off the trigger before doing this and then turn it back on.

2.
  • Unit - Set life of ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger] to ((Life of ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger]) + DamageTakenReals[ShieldsUnitDamagedLoopInteger])
You'll notice that the Footman always takes damage (ignoring the Shield) on the first hit he receives. That's because you're healing the unit before the damage is dealt, therefore, if you heal a 500/500 hp footman then nothing happens and THEN the damage is dealt. I didn't fix this in my version either.
 

Attachments

  • ProtossShieldsTestX EDIT Uncle.w3x
    39.5 KB · Views: 64
Last edited:

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
I edited your map and added a Unit Indexer and adjusted your code so it would work using Unit Indexing instead of Loops. I think this is much better and will perform way better. Instead of having to loop through possibly 100's of units you can instead avoid that entirely using a Unit Indexer.
Thanks but that's a lot of custom script. I can barely understand GUI.
You'll notice that the Footman always takes damage (ignoring the Shield) on the first hit he receives. That's because you're healing the unit before the damage is dealt, therefore, if you heal a 500/500 hp footman then nothing happens and THEN the damage is dealt.
Aha, so that's why the first hit on full HP always took life. But the trigger runs after the event. So, where to put it?

Tried your edit. Worked quite well until I trained past 30 or so unit value number of footmen and the shield was just ignored, text and all for some of them.

Also, how could I use this for more than just one unit type? I basically need all protoss units. They have various shield values.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
Adding an Event to a Trigger like this:
  • Trigger - Add to Shield Units Damaged <gen> the event (Unit - ShieldsTrainedUnit[ShieldsIndexInteger] Takes damage)
is the reason why you can't go past 30 Footman (Or so I believe). This is why most people avoid this Action and use better systems instead.

That's why a Damage Detection System fixes all of these problems. And remember, you don't actually need to understand how the DD system works to take advantage of it. Bribe's Damage Detection System may be written in JASS but it's designed to be used in GUI. Meaning that all you have to worry about is figuring out which variables (global variables accessible in GUI) you need to use, which he makes very clear. "DamageEventSource" is a variable that will always represent the Source of the Damage. "DamageEventTarget" will always represent the unit that was Damaged. He even creates his own custom Event which is fired whenever a unit takes damage.
  • Game - DamageModifierEvent becomes Equal to 1.00

Also, you shouldn't ever need to look at or touch that Unit Indexing system. And it's extremely simple how it works: A unit enters the map -> Increase an Integer by 1 (very similar to what you were doing with your map) -> Then set that unit's custom value to that Integer. So now every single unit will have it's own unique Custom Value just like how every unit in your system had it's own unique ShieldsIndexInteger.

But what's great about that Unit Indexing system is that it will automatically recycle unused indices. Meaning that when Footman[2] dies the Unit Indexer will OPEN Index #2 and the next unit you create will replace that spot. So it sorts it all out for you and leaves you with nothing to worry about but your own triggers. And the only thing you have to do (which is simple GUI) is use the unit's Custom Value as it's Array. So instead of
  • Set ShieldsTrainedUnit[ShieldsIndexInteger] = (Trained unit)
you would do
  • Set ShieldsTrainedUnit[Custom value of trained unit] = (Trained unit)
. However, like you'll see in my version of the map, I like to set the variable "CV" to be the unit's custom value because it makes it a lot easier to reference it (it's a pain to have to put in "custom value of unit" every single time).

I can incorporate Bribe's Damage Detection System into your map if you want. It's very easy to use it once you realize that you can ignore 99.99% of the scary Wall of Text stuff.
 
Last edited:

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
Adding an Event to a Trigger like this: will eventually reach a limit.
Aw man, I really wanted to revolutionize GUI somehow :p

"DamageEventTarget" will always represent the unit that was Damaged. He even creates his own custom Event which is fired whenever a unit takes damage.
  • game.gif
    Game - DamageModifierEvent becomes Equal to 1.00
Can't that trigger when say a unit has a lot of armour to reduce enemy attack to 1?
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
I don't understand what you want. Do you want Armor to work like in Starcraft? Like 5 armor reduces damage taken by exactly 5?

Also, I accidentally forgot to delete some unneeded things so here's a "fixed" version (it still has the same problems with the 30+ footman):
 

Attachments

  • ProtossShieldsTestX EDIT Uncle.w3x
    39.5 KB · Views: 69

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
I don't understand what you want. Do you want Armor to work like in Starcraft? Like 5 armor reduces damage taken by exactly 5?
Yes but that's what it does.

If you're referring to
Can't that trigger when say a unit has a lot of armour to reduce enemy attack to 1?
I am asking if that 1 damage for the custom damage event can't be triggered by a unit dealing 1 damage for some other reason than the damage detection system.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
Yes but that's what it does.

If you're referring to

I am asking if that 1 damage for the custom damage event can't be triggered by a unit dealing 1 damage for some other reason than the damage detection system.

Oh, I see. You misunderstood me. Whenever a unit takes damage the system sets "DamageModifierEvent" (which is a Real variable) to be equal to 1. This is simply used to fire the trigger. You can pretend that the Event really says "Whenever any unit takes damage".

If this is confusing, don't worry. I'll upload you an example. It's just another thing you don't really have to worry about.
 

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
If this is confusing, don't worry. I'll upload you an example. It's just another thing you don't really have to worry about.
I think I get it. It's just a virtual thing. It's not affected by anything like a unit actually dealing a certain amount of damage.

Hey, I made it partially work like you without the unit index system by using a unit group. Problem is, it starts lagging and after a certain point in time with more than 12-20 units, it crashes due to a memory issue.

I know you hate me :D sorry. I'm quite stubborn.

So basically, I changed:


  • Shield Units Training
    • Events
      • Unit - A unit owned by Player 1 (Red) Finishes training a unit
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of (Trained unit)) Equal to Irregular Footman
        • Then - Actions
          • Set ShieldsIndexInteger = (ShieldsIndexInteger + 1)
          • Set ShieldsTrainedUnit[ShieldsIndexInteger] = (Trained unit)
          • Unit Group - Add ShieldsTrainedUnit[ShieldsIndexInteger] to ShieldUnitsGroup
          • Set ShieldsInitialValue[ShieldsIndexInteger] = 500
          • Set ShieldsMaxValue[ShieldsIndexInteger] = ShieldsInitialValue[ShieldsIndexInteger]
          • Floating Text - Create floating text that reads ((String(ShieldsInitialValue[ShieldsIndexInteger])) + ( / + (String(ShieldsMaxValue[ShieldsIndexInteger])))) above ShieldsTrainedUnit[ShieldsIndexInteger] with Z offset 10.00, using font size 8.00, color (100.00%, 0.00%, 100.00%), and 0.00% transparency
          • Set ShieldsFloatingText[ShieldsIndexInteger] = (Last created floating text)
          • Floating Text - Create floating text that reads ((+ + ((String(ShieldsArmourValue[ShieldsIndexInteger])) + ))) above ShieldsTrainedUnit[ShieldsIndexInteger] with Z offset 10.00, using font size 8.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
          • Set ShieldsArmourFloatingText[ShieldsIndexInteger] = (Last created floating text)
          • -------- Floating Text with Armour --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsArmourValue[ShieldsIndexInteger] Equal to 0
            • Then - Actions
              • Floating Text - Change text of ShieldsArmourFloatingText[ShieldsIndexInteger] to <Empty String> using font size 8.00
            • Else - Actions
          • -------- Check If Ready to Go --------
          • Trigger - Add to Shield Units Damaged <gen> the event (Unit - ShieldsTrainedUnit[ShieldsIndexInteger] Takes damage)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ShieldsIndexInteger Equal to 1
              • ShieldsIndexInteger Greater than DeadUnitsInteger
            • Then - Actions
              • Trigger - Turn on Shield Units Damaged <gen>
              • Trigger - Turn on Shields Regenerate <gen>
              • Trigger - Turn on Shield Floating Texts Move <gen>
              • Trigger - Turn on Shield Texts OFF <gen>
            • Else - Actions
        • Else - Actions

and

  • Shield Texts OFF
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • For each (Integer FloatingTextsOFFLoopInteger) from 1 to ShieldsIndexInteger, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Dying unit) Equal to ShieldsTrainedUnit[FloatingTextsOFFLoopInteger]
            • Then - Actions
              • Floating Text - Destroy ShieldsFloatingText[FloatingTextsOFFLoopInteger]
              • Floating Text - Destroy ShieldsArmourFloatingText[FloatingTextsOFFLoopInteger]
              • Unit Group - Remove (Dying unit) from ShieldUnitsGroup
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Number of units in ShieldUnitsGroup) Equal to 0
                • Then - Actions
                  • Set ShieldsIndexInteger = 0
                  • Game - Display to (All players) the text: (Index + (String(ShieldsIndexInteger)))
                  • Game - Display to (All players) the text: (UnitsInGroup + (String((Number of units in ShieldUnitsGroup))))
                  • Trigger - Turn off Shield Texts OFF <gen>
                  • Trigger - Turn off Shield Floating Texts Move <gen>
                  • Trigger - Turn off Shields Regenerate <gen>
                  • Trigger - Turn off Shield Units Damaged <gen>
                • Else - Actions


Probably, I need to destroy the group and make it again each time the unit count goes 0 so it won't leak?


EDIT:
The lag comes from the periodic event (0.01) that moves the floating text for all the trained units. If I turn that trigger off/disable that event, there's no lag anymore when there are many footmen.
 

Attachments

  • ProtossShieldsTestX.w3x
    36.2 KB · Views: 57
Last edited:

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
Here is a version with the Damage Detection System implemented. It's very easy to use and it looks to be leak free. I tested with 50+ footmen and it worked great.

I think you're leaking memory with these (if you haven't fixed them already):
  • Unit - Cause DamageSourceUnits[ShieldsUnitDamagedLoopInteger] to damage ShieldsTrainedUnit[ShieldsUnitDamagedLoopInteger], dealing (Real(LifesTaken[ShieldsUnitDamagedLoopInteger])) damage of attack type Chaos and damage type Normal
^This damage will cause the Damage Trigger to fire AGAIN. You don't want that to happen so Turn off the trigger before doing this and then Turn it back on afterwards.

  • Floating Text - Change the position of ShieldsFloatingText[FloatingTextsLoopInteger] to (Center of ((Region centered at ShieldsTrainedUnitPoint[FloatingTextsLoopInteger] with size (0.00, 0.00)) offset by (-45.00, 0.00))) with Z offset 160.00
^I think this Point leaks inside your Text Move trigger.

Instead try something like this:
  • Set TempPoint = ((Position of (Picked unit)) offset by (-45.00, 0.00))
  • Floating Text - Change the position of ShieldsFloatingText[CV] to TempPoint with Z offset 160.00
  • Custom script: call RemoveLocation (udg_TempPoint)
 

Attachments

  • ProtossShieldsTestX EDIT Uncle v.2.w3x
    60.8 KB · Views: 61

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
I'm going to go work on some of my own stuff. I highly recommend using my last map upload (v.2). I know it's no fun using other people's stuff but I really think there's no better way of doing this and restricting yourself to GUI is going to hurt your map's performance and greatly limit your capabilities.

Good luck!
 

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
^This damage will cause the Damage Trigger to fire AGAIN. You don't want that to happen so Turn off the trigger before doing this and then Turn it back on afterwards.
I did that, as you wrote about it the first time.
I'm positive it's the floating text being moved for each footman once in 0.01s. I disabled the text movement trigger and there's no more lag.
^I think this Point leaks inside your Text Move trigger.
Yeah, that's the one. Weird, since I use the point variable which is destroyed right after the text is moved.
Instead try something like this:
Well, this is how it is:
  • Shield Floating Texts Move
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • For each (Integer FloatingTextsLoopInteger) from 1 to ShieldsIndexInteger, do (Actions)
        • Loop - Actions
          • Set ShieldsTrainedUnitPoint[FloatingTextsLoopInteger] = (Position of ShieldsTrainedUnit[FloatingTextsLoopInteger])
          • Floating Text - Change the position of ShieldsFloatingText[FloatingTextsLoopInteger] to (Center of ((Region centered at ShieldsTrainedUnitPoint[FloatingTextsLoopInteger] with size (0.00, 0.00)) offset by (-45.00, 0.00))) with Z offset 160.00
          • Floating Text - Change the position of ShieldsArmourFloatingText[FloatingTextsLoopInteger] to (Center of ((Region centered at ShieldsTrainedUnitPoint[FloatingTextsLoopInteger] with size (0.00, 0.00)) offset by (70.00, 0.00))) with Z offset 160.00
          • Custom script: call RemoveLocation (udg_ShieldsTrainedUnitPoint[udg_FloatingTextsLoopInteger])
Do I need to set a different point for the armour as well? Or it leaks because of the loop and index?

I'm going to go work on some of my own stuff.
Thanks a lot for your time!

Also, don't doublepost :D

EDIT: a question. How did you import the systems so easily without needing to create each variable separately and so on?

Yeah, the one with DDS seems to work smoothly. I just gotta get myself to understand those two systems but I want to still try a bit more with GUI as an ambitious act.
 
Last edited:

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
In the World Editor go to: File -> Preferences -> Check on "Automatically create unknown variables".

Also, I just realized that Armor isn't being applied to the damage that is dealt to the Shield. It is being applied to damage dealt to life though. Did you want it this way?
 

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
Also, I just realized that Armor isn't being applied to the damage that is dealt to the Shield. It is being applied to damage dealt to life though. Did you want it this way?
Well, I based everything on damage to health. Like in StarCraft, armour is supposed to protect shields but since I didn't use a damage detection system, I could only make shield armour work on health and because of that every damage hit is reduced by the unit's normal armour and so happens with the shield.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
Well, In Starcraft there is Protoss Armor AND Protoss Shields. Protoss Shields protects the Shields and Armor protects the Health. If you want, I can make the system work like Starcraft.

Some guy on the blizzard forum's summed it up nicely:
1. Base damage is calculated from the attacker's weapon, including increases from weapon research and bonuses from unit attributes (Armored, Light, Biological, etc.).
2. If the target has at least one point of shielding, then the target's shield upgrade level is subtracted from the base damage.
2a. If the target is an Immortal and the damage is greater than 10, it is reduced to 10 now.
2b. The resulting damage is subtracted from the target's shielding.
3. If the target's shielding reaches zero and there is leftover damage, the remaining damage is reduced by the target's armor, and the resulting damage is subtracted from the target's health.

So, if you have an attack that does 10 damage, and the target has shield upgrade 2 and 1 armor, and 5 points of shielding left: Start with 10, shield upgrade is 2, so damage is reduced to 8. The target loses 5 points of shielding (so it has no shielding left), and 3 points of damage are left. The target has 1 armor, so 3 is reduced to 2, and then the target takes those 2 points of damage from health.

That's everything. Shielding works exactly like an extra layer of health, but it has its own damage reduction step, and damage that hits both shielding and health is affected by both reductions.
 

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
I know how it works, I think. Well I wanted to make it like in Brood War, not StarCraft II which has shields taking damage depending on the unit's armour type and the damage dealer's damage type.
I read about it on the wiki and liquidpedia. But I couldn't or didn't know how to implement it properly without the Warcraft III armour ignoring damage detection system.
Plasma shield

Yeah, basically, it's like Mana Shield in a way. If you have 1 shield but the upgrade for the shield armour is 3, you take 7 damage instead of 10 right? Well, assuming everyone deals no bonus damage against that unit's armour type.
But if your unit has 5 shield and 5 HP and the enemy deals 10 damage, you should get a reduction of +3 from the shield armour and +3 from the usual armour (assuming both are level 3) which means the protoss unit is left with 5HP because from 10 damage 8 is dealt on the shield and the remaining 2 is nulled by the HP's armour.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
I think a unit with 5 Shields and 5 Hp and +3 Armor/Shield Upgrades would be like this.

An Enemy deals 10 Damage:

First the damage is applied to Shields:
10 Damage - Shield Upgrade = 7 Damage
5 Unit Shields - 7 Damage = 2 Leftover Damage

Finally the Leftover damage is applied to Health:
2 Leftover Damage - Armor Upgrade = -1

Obviously you can't deal negative damage so any damage below 0 would be set to 0.
However, I believe in Brood War the minimum damage a unit can deal is 1. So the damage would be set to 1 instead of 0.
 

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
However, I believe in Brood War the minimum damage a unit can deal is 1. So the damage would be set to 1 instead of 0.
Yeah, basically what I wrote :D

Yeah, in Warcraft III we can have 0 :p
I think they used 1 in Brood War to be on the safe side for some reason? Maybe, because some units either regenerate or are being healed and that would be too advantageous for those units. Imagine zerglings dealing 0 damage :D

EDIT:
Lol, you used -11 for one of the racial ability positions. You can hide abilities via triggers now :D



EDIT:
For some reason modifying the trigger from:
  • Floating Text - Change the position of ShieldsArmourFloatingText[FloatingTextsLoopInteger] to (Center of ((Region centered at ShieldsTrainedUnitPoint[FloatingTextsLoopInteger] with size (0.00, 0.00)) offset by (70.00, 0.00))) with Z offset 160.00
to
  • Floating Text - Change the position of ShieldsArmourFloatingText[FloatingTextsLoopInteger] to ShieldsPoint with Z offset 160.00
reduced lag if not eliminated it. Have to test further.
But now, the position cannot be changed to slightly right or to the left but only the height of the text.
Other types of point settings seem to lag like hell.

Lag seems to be completely gone even with 100 food occupied at one time and fighting.
Just got to fix the rebel armour text.
 
Last edited:

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
Here's version 3 of my edit. I created a Brood War-like Armor/Shield system.

In the Damage Event trigger you'll see these:

If the unit has more than 0 Shields left it will reduce the damage taken by this variable: ShieldsUnitShieldUpgrade[CV].
  • Set DamageEventAmount = (DamageEventAmount - ShieldsUnitShieldUpgrade[CV])
Then after that if there is any Leftover damage (damage that went past the Shields) we reduce that damage taken by the unit's Armor stat. You could change this to be a variable like ShieldsUnitShieldUpgrade[CV] instead of using Warcraft 3's Armor stat. I figured it was just easier this way.
  • Set DamageEventAmount = (DamageEventAmount - (Armor of DamageEventTarget))
ShieldsUnitShieldUpgrade is a variable that I define when you Train the unit. Just like how you set the unit's InitialShieldValue when you train it. I set it to 1.0 for testing purposes but ideally you would set it to 1.0*Level of Protoss Shield Upgrade.
 

Attachments

  • ProtossShieldsTestX EDIT Uncle v.3.w3x
    61.5 KB · Views: 65

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
Here's version 3 of my edit.
Tested it somewhat thoroughly.

I've added more neutral hostile units, now there are 12 farms and footmen don't require food.

Looks like Warcraft III isn't made to sustain more than 100 units per player without them waiting turns to execute orders. Weird since Brood War is older than this game...
Also, past 120 footmen, shield text stops appearing. In my version past 60.
I sent 120 footmen to the northeast neutral hostile camp and 120 to the one in the northwest, somewhat at the same time. Did this for a couple of times and the game crashed due to memory issues.
The game lags when there are many footmen at a given time but resolves itself once they start dying getting close to 0.

I've also worked more on my version and improved performance by modifying the periodic event which moves the shield texts from 0.01 to 0.05.
However, the same thing happens as in your edit but faster, I think.

Attached both versions.



EDIT: forgot to mention that trying to load a saved game doesn't work. I get a red error saying it cannot be done. If I try to load the game through the game's menu, the map isn't read (no minimap, teams/players etc.). Possibly, because of the memory leaks that gather the map isn't actually saved or it is with lots of errors.

EDIT2:
Have to figure out how to disable the shield and shield armour text when a unit is being devoured and reappear when it is freed from the creature's belly :D

EDIT3:
Performance is fine if the 120/60 footmen limit is not passed so that the floating text would leak. However, loading the game doesn't work after many fights with under the limit footmen groups.
ShieldsTestLoadError.png
About that time, the game gained 1.38k of memory (Task Manager). Exiting it takes forever. It's better to just force close it.
Funny thing is that the memory usage still goes up.

EDIT4:
Disabled the floating texts and sent groups of 120 footmen, waiting for each group to die out before sending a new one. Memory upped to around 400mb this time. The difference is that now less groups are needed to finish off the neutral hostile camps. However 240 footmen at a time amount to around 300mb memory taken by the game.
Saving is fast, loading is also fast but crashes the game.

Question, do game-text messages leak?

EDIT5:
Past 100 footmen, whenever there are 0 of them left, the debug text doesn't say anything. I assume, they are not considered dead, at least not all of them. Er, at least sometimes.
I'll try using an ability which changes its tooltip instead of floating text. Without it, it's basically playable. I also need to sort out the load issue.

EDIT6:
Tried adding a passive ability but the description/tooltip is shared between the units probably because the ability has the same ID. I don't think there's a trigger to create abilities or change their IDs so that there would be more of the same ability type.

Another thing I could do is use inventories but that would kill the usage of inventories if I'd want/need them.

Would have been nice to be able to write under the units name. You can only do it on the same line where the name is.
OK! I did it! It's possible. There's a button called new line which adds a "|n" which acts like in normal object data descriptions/tooltips as a function to set the following text below, one line.
Although, I don't see this working on units with a visible classification as undead etc., neutral hostile units with visible level and heroes with experience bars.
Surprisingly, the classification is moved even lower. Wow!
However the issue is the classification text overlapping the secondary attack:
footmenShields.png
Not sure if you can make classifications not show. Maybe in game interface options?
Brood War doesn't have that, instead it has the unit's rank and kill number but since it's not like in Red Alert where units get promoted based on their kills and that the kill number limit to be shown is 255 in Brood War, it really serves no purpose to be there.
A fix could be to reduce the text size but I don't think it's possible.

EDIT7:
Ha-ha. Check this out:
footmenShieldsReanimated.png
They regenerate by the way.
Maybe that's why they weren't considered dead?

EDIT8:
This is weird. The map crashes on load even if I save it from the start without training any footmen...
Upon deleting all variables and triggers, this happens no more. First, tried with triggers shut off but nothing.
Deleting the variables, all of them, let's it work. I wonder if it's because of the huge array sizes I put in them.
Indeed, this was the issue.

EDIT9:
Regarding the disappearance of floating text after a certain number of units, might the info in this post be true?
Does floating text above unit leak?

EDIT10: for some reason the footmen reanimate with part of the shield text under their name although I set the name of the dying unit to change to just Irregular Footman.
 

Attachments

  • ProtossShieldsTestX EDIT Uncle v.3.w3x
    63.6 KB · Views: 57
  • ProtossShieldsTestX.w3x
    40.5 KB · Views: 57
Last edited:

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
With the new UI features you could probably make the Shields show up right next to the Health/Mana. Would require some UI knowledge though, Tasyen has a bunch of UI resources/tutorials that you could take a look at.

You can add/remove unit classifications in the Object Editor so you wouldn't need to hide "undead". But I guess if you still wanted to use Undead then you can edit the text in Game Interface to be a single " " space, this will make it show up blank ingame (at least last I think this works).
 

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
You can add/remove unit classifications in the Object Editor so you wouldn't need to hide "undead". But I guess if you still wanted to use Undead then you can edit the text in Game Interface to be a single " " space, this will make it show up blank ingame (at least last I think this works).
Yeah, since only one of them has priority anyway. If you put both undead and mechanical, undead is the one that appears.
 

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
Worked more on the GUI version. Seems pretty good until there are too many units and the game starts lagging as the units are trying to execute commands.

Still have to add an overhead shield bar and a hit FX. What you can see now is the shield text and armour underneath the unit's name.

Learned quite something from Uncle's edit.

My system isn't as refined as his because it doesn't use an inbuilt/JASS detection system and/or unit indexer but it's pure GUI, well except for some few custom scripts to kill leaks, and it's quite useful if you don't intend to use it on huge armies. Not sure if you can do that since past 100 units per player, they don't act normally anymore and wait in turns to execute their commands/orders.

I also want to point out Devalut's system:
[GUI] Prototype Kinetic Barrier & Shell Beta 0.02
It has overhead shield FX and StarCraft II shield regeneration type, acting only out of combat.
 

Attachments

  • ProtossShieldsTest.w3x
    41.4 KB · Views: 48
Last edited:

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
Updated the GUI version. Fixed an issue with armour which was adding again after units trained and it not being properly integrated in the damage event calculations.

Added:
-armour and shield upgrades;
-another aura (Paladin) but this time to decrease shield regeneration but not below 0;
-one more spell (Paladin) but which decreases armour and shields temporary;
-another unit type with its own shield but indexed in the same unit group/trigger chain;
-the system is shared with another shared control player which means it could work for all players on a map at the same time although it would probably be recommended to copy the system for each player or modify it accordingly for better performance.

Still have to find a proper way of representing the shield on the battlefield visually like a health/mana bar. Using a unit for it has its issues as units are covered by other units (flying ones especially).
I won't be able to make a shield bar on unit icons without modifying the UI through JASS.

Limitations: because it's not using a damage detection system, the shield takes damage depending on the wearer's unit/normal armour.



EDIT:
Updated with:
-shield regeneration upgrade;
-devalutian shield hit FX (basically ripped the poor feller alive: [GUI] Prototype Kinetic Barrier & Shell Beta 0.02 but since we're heading towards full fledged anarchic communism singularity anyway...). Shields scales/sizes and offsets depend on unit types.

You could make them based on get unit real field (scaling value) but some units are wider horizontally, others vertically, so your best option for lovely visuals is testing every unit you want to put a shield on it. For some reason, Warcraft III acts asymmetrically in that when the footman is hit from the east, the shield FX is farther from the footman as opposed to the unit being hit from the west not mattering where the footman faces.

"Funkiness" still "ensues" when DPS abilities like poison act on shields. Basically, the shield FX's orientation will be depending on the angle between the DPS caster (alive or dead) and the shield bearer.
Most teeth gritting funk is played wildly when shielded units are devoured as the FX dances near the hungry creatures until the ingested are thrown, partially, through and to the other side.

To drive the shield effect toward flawlessness, it should move along with the unit having it. Right now, it briefly remains still where the unit was hit until it disappears. I gather correcting this might lead to leaks or at least possible if not probable performance issues.

Also want to thank Hermit for the editing of the spirit touch model, requested by devalutian synapses: Model Request: Spirit Touch Recolour
But obviously you might want to delve more into devalutian and hermitian (murlocs and mathematics go together) neurosciences: Model Request: Spirit Touch Recolour

After some Red Bull testing, the system in love with the FX seems leakless. Well, there are some snail spikes when too many shield FX are triggered at a time but after those either stop or the units having them die out, performance resolves itself. Overall not more than 380mb memory did the executable needed.

Left the shield hit FX colouring to over the rainbow (not really, it's a random colour on each hit) for the funnies because who doesn't love blowing bubbles?. By the way, it looks really swell with neutral hostile's colour, some sort of metallic gray.
Note: some colours are more visible than others probably due to the terrain and or lightening hue.
 

Attachments

  • ProtossShieldsTest.w3x
    66.7 KB · Views: 53
Last edited:

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
So, since the GUI protoss shields and shield armours are 90% done except for the excluding of the normal unit armour/defense calculation until BlizzEnt fixes the weapon real field triggers, plus finding a proper always on top means to show it on screen, I went forward trying to make a system like that of the protoss Carrier and its Interceptors. It's work in progress.

I can't for the life of me figure out how to properly set different points, using one point with an array, for interceptors when they return to the Carrier. They always go to the last point array. Attached the map file. It's not MUI ready yet.
See the last trigger chain. Train a dragon from the "farm" and use the Berserk ability to create a max of 8 dragon whelps.



  • Interceptor Train
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (Unit-type of (Casting unit)) Equal to Whelp Carrying Red Dragon
              • (Ability being cast) Equal to Train Intercepting Red Dragon Whelp (Berserk)
              • CarrierInterceptorInteger Less than 8
        • Then - Actions
          • Set ShieldedUnitPal = (Casting unit)
          • Set CarrierInterceptorInteger = (CarrierInterceptorInteger + 1)
          • Unit - Create 1 Intercepting Red Dragon Whelp for Player 1 (Red) at (Position of ShieldedUnitPal) facing Default building facing degrees
          • Set CarrierInterceptorUnit[CarrierInterceptorInteger] = (Last created unit)
          • Unit Group - Add CarrierInterceptorUnit[CarrierInterceptorInteger] to InterceptorGroup
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CarrierInterceptorInteger Equal to 8
            • Then - Actions
              • Unit - For ShieldedUnitPal, Ability Train Intercepting Red Dragon Whelp (Berserk), Hide ability: True
            • Else - Actions
          • Trigger - Add to Carrier Acquires a Target <gen> the event (Unit - ShieldedUnitPal Acquires a target)
        • Else - Actions


  • Interceptor Clear
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • For each (Integer InterceptorDieInteger) from 1 to CarrierInterceptorInteger, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Dying unit) Equal to CarrierInterceptorUnit[InterceptorDieInteger]
            • Then - Actions
              • Unit Group - Remove CarrierInterceptorUnit[InterceptorDieInteger] from InterceptorGroup
              • Set CarrierInterceptorUnit[InterceptorDieInteger] = CarrierInterceptorUnit[CarrierInterceptorInteger]
              • Set CarrierInterceptorInteger = (CarrierInterceptorInteger - 1)
              • Set InterceptorDieInteger = (InterceptorDieInteger - 1)
            • Else - Actions
          • -------- Unhide Interceptor Train Ability --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CarrierInterceptorInteger Equal to 0
            • Then - Actions
              • Unit - For ShieldedUnitPal, Ability Train Intercepting Red Dragon Whelp (Berserk), Hide ability: False
            • Else - Actions


  • Carrier Acquires a Target
    • Events
    • Conditions
    • Actions
      • -------- Smart Target is an Enemy --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • ((Targeted unit) belongs to an enemy of Player 1 (Red)) Equal to True
              • CarrierInterceptorInteger Less than or equal to 8
        • Then - Actions
          • Game - Display to (All players) the text: ACQUIRE TARGET
          • Set CarrierAttacksON = True
          • Set InterceptorTargetUnit = (Targeted unit)
        • Else - Actions


  • Interceptor Order Type Set Target Order
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
    • Actions
      • -------- Smart Target is an Enemy --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (Ordered unit) Equal to ShieldedUnitPal
              • ((Target unit of issued order) belongs to an enemy of Player 1 (Red)) Equal to True
              • CarrierInterceptorInteger Less than or equal to 8
        • Then - Actions
          • Game - Display to (All players) the text: ATTACK ORDER SMART
          • Set CarrierAttacksON = True
          • Set InterceptorTargetUnit = (Target unit of issued order)
        • Else - Actions
      • -------- Smart Target is an Ally --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (Ordered unit) Equal to ShieldedUnitPal
              • ((Target unit of issued order) belongs to an ally of Player 1 (Red)) Equal to True
              • CarrierInterceptorInteger Less than or equal to 8
        • Then - Actions
          • Game - Display to (All players) the text: MOVE ORDER SMART
          • Set CarrierAttacksON = False
          • Set InterceptorTargetUnit = No unit
        • Else - Actions


  • Interceptor Order Type Set Point Order
    • Events
      • Unit - A unit Is issued an order targeting a point
    • Conditions
    • Actions
      • -------- Smart Target is a Point --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (Ordered unit) Equal to ShieldedUnitPal
              • CarrierInterceptorInteger Less than or equal to 8
        • Then - Actions
          • Game - Display to (All players) the text: POINT ORDER SMART
          • Set CarrierAttacksON = False
          • Set InterceptorTargetUnit = No unit
        • Else - Actions


  • Interceptor Attack n Move Order
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • -------- Interceptor Position Near Carrier on Return/Move --------
      • Set InterceptorCarrierPositionItgr = (InterceptorCarrierPositionItgr + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • InterceptorCarrierPositionItgr Greater than 8
        • Then - Actions
          • Set InterceptorCarrierPositionItgr = 0
        • Else - Actions
      • -------- Interceptors Move --------
      • For each (Integer InterceptorMoveOrderInteger) from 1 to InterceptorCarrierPositionItgr, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CarrierAttacksON Equal to False
            • Then - Actions
              • Game - Display to (All players) the text: Interceptor Move
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • InterceptorCarrierPositionItgr Equal to 1
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 270.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • InterceptorCarrierPositionItgr Equal to 2
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 315.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • InterceptorCarrierPositionItgr Equal to 3
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 0.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • InterceptorCarrierPositionItgr Equal to 4
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 45.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • InterceptorCarrierPositionItgr Equal to 5
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 90.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • InterceptorCarrierPositionItgr Equal to 6
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 135.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • InterceptorCarrierPositionItgr Equal to 7
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 180.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • InterceptorCarrierPositionItgr Equal to 8
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 225.00 degrees)
                • Else - Actions
              • -------- Move Interceptors Back --------
              • Unit - Order CarrierInterceptorUnit[InterceptorMoveOrderInteger] to Move To CarrierPoint[InterceptorMoveOrderInteger]
              • Custom script: call RemoveLocation (udg_CarrierPoint[udg_InterceptorMoveOrderInteger])
            • Else - Actions
      • -------- Interceptors Attack --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between (Position of ShieldedUnitPal) and (Position of InterceptorTargetUnit)) Greater than 1000.00
        • Then - Actions
          • Set CarrierAttacksON = False
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (Distance between (Position of ShieldedUnitPal) and (Position of InterceptorTargetUnit)) Less than or equal to 1000.00
              • InterceptorTargetUnit Not equal to No unit
        • Then - Actions
          • Set CarrierAttacksON = True
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (InterceptorTargetUnit is alive) Equal to True
              • CarrierAttacksON Equal to True
        • Then - Actions
          • For each (Integer InterceptorAttackOrderInteger) from 1 to CarrierInterceptorInteger, do (Actions)
            • Loop - Actions
              • Game - Display to (All players) the text: Interceptor Attack
              • Unit - Order CarrierInterceptorUnit[InterceptorAttackOrderInteger] to Attack InterceptorTargetUnit
        • Else - Actions



EDIT:
Figured it out. I was using the same +1 integer for the loop which obviously made it not work. Updated the map file.


  • Interceptor Attack n Move Order
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • -------- Interceptors Move --------
      • For each (Integer InterceptorMoveOrderInteger) from 1 to CarrierInterceptorInteger, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CarrierAttacksON Equal to False
            • Then - Actions
              • -------- Interceptor Position Near Carrier on Return/Move --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • InterceptorCarrierPositionItgr Greater than or equal to 8
                • Then - Actions
                  • Set InterceptorCarrierPositionItgr = 0
                • Else - Actions
              • Set InterceptorCarrierPositionItgr = (InterceptorCarrierPositionItgr + 1)
              • Game - Display to (All players) the text: (InterINTEG + (String(InterceptorCarrierPositionItgr)))
              • Game - Display to (All players) the text: Interceptor Move
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 1
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 270.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 2
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 315.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 3
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 0.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 4
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 45.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 5
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 90.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 6
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 135.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 7
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 180.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 8
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 225.00 degrees)
                • Else - Actions
              • -------- Move Interceptors Back --------
              • Unit - Order CarrierInterceptorUnit[InterceptorMoveOrderInteger] to Move To CarrierPoint[InterceptorMoveOrderInteger]
              • Custom script: call RemoveLocation (udg_CarrierPoint[udg_InterceptorMoveOrderInteger])
            • Else - Actions
      • -------- Interceptors Attack --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between (Position of ShieldedUnitPal) and (Position of InterceptorTargetUnit)) Greater than 1000.00
        • Then - Actions
          • Set CarrierAttacksON = False
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (Distance between (Position of ShieldedUnitPal) and (Position of InterceptorTargetUnit)) Less than or equal to 1000.00
              • InterceptorTargetUnit Not equal to No unit
        • Then - Actions
          • Set CarrierAttacksON = True
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (InterceptorTargetUnit is alive) Equal to True
              • CarrierAttacksON Equal to True
        • Then - Actions
          • For each (Integer InterceptorAttackOrderInteger) from 1 to CarrierInterceptorInteger, do (Actions)
            • Loop - Actions
              • Game - Display to (All players) the text: Interceptor Attack
              • Unit - Order CarrierInterceptorUnit[InterceptorAttackOrderInteger] to Attack InterceptorTargetUnit
        • Else - Actions


Now, the issue is that if one of the whelps die, all lose their positions and start circling like crazy like it happened before with all of them. Also happens when you train them and they are less than the max 8.

EDIT: fixed it although now whelps exchange locations with the dead one. Not a big deal, doesn't affect the gameplay. It's just a visual matter.
Basically had to verify if the position integer was greater than the number of interceptors not a fixed number 8 to put it back to 0.

  • Interceptor Attack n Move Order
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • -------- Interceptors Move --------
      • For each (Integer InterceptorMoveOrderInteger) from 1 to CarrierInterceptorInteger, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CarrierAttacksON Equal to False
            • Then - Actions
              • -------- Interceptor Position Near Carrier on Return/Move --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • InterceptorCarrierPositionItgr Greater than or equal to CarrierInterceptorInteger
                • Then - Actions
                  • Set InterceptorCarrierPositionItgr = 0
                • Else - Actions
              • Set InterceptorCarrierPositionItgr = (InterceptorCarrierPositionItgr + 1)
              • Game - Display to (All players) the text: (InterINTEG + (String(InterceptorCarrierPositionItgr)))
              • Game - Display to (All players) the text: Interceptor Move
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 1
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 270.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 2
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 315.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 3
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 0.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 4
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 45.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 5
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 90.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 6
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 135.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 7
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 180.00 degrees)
                • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • InterceptorCarrierPositionItgr Equal to 8
                      • (CarrierInterceptorUnit[InterceptorMoveOrderInteger] is alive) Equal to True
                • Then - Actions
                  • Set CarrierPoint[InterceptorMoveOrderInteger] = ((Position of ShieldedUnitPal) offset by 200.00 towards 225.00 degrees)
                • Else - Actions
              • -------- Move Interceptors Back --------
              • Unit - Order CarrierInterceptorUnit[InterceptorMoveOrderInteger] to Move To CarrierPoint[InterceptorMoveOrderInteger]
              • Custom script: call RemoveLocation (udg_CarrierPoint[udg_InterceptorMoveOrderInteger])
            • Else - Actions
      • -------- Interceptors Attack --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between (Position of ShieldedUnitPal) and (Position of InterceptorTargetUnit)) Greater than 1000.00
        • Then - Actions
          • Set CarrierAttacksON = False
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (Distance between (Position of ShieldedUnitPal) and (Position of InterceptorTargetUnit)) Less than or equal to 1000.00
              • InterceptorTargetUnit Not equal to No unit
        • Then - Actions
          • Set CarrierAttacksON = True
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • (InterceptorTargetUnit is alive) Equal to True
              • CarrierAttacksON Equal to True
        • Then - Actions
          • For each (Integer InterceptorAttackOrderInteger) from 1 to CarrierInterceptorInteger, do (Actions)
            • Loop - Actions
              • Game - Display to (All players) the text: Interceptor Attack
              • Unit - Order CarrierInterceptorUnit[InterceptorAttackOrderInteger] to Attack InterceptorTargetUnit
        • Else - Actions
 

Attachments

  • ProtossShieldsTest.w3x
    75.5 KB · Views: 49
Last edited:

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
I need help with the interceptor moving system. I can't figure how to check and when so that they randomly shift facing toward or not opposite the target and start moving toward that direction.

I'm thinking something with a unit comes within range and conditioning the distance between the interceptors and their target while checking every 0.1 so that if stunned or moved, the interceptors won't lose their orders.

Using regions and moving them isn't viable if the target is near the map edges because the regions will be moved past(?) the map boundary. But not sure checking the distance between the interceptors and their targets is viable in this context either.

An integer adds +1 to itself and is considered the phases necessary in the conditions of the 0.1s periodic event.

Any ideas, please?

Video of what I'm trying to come close to achieving:
Uploadfiles.io - ProtossCarrierInterceptor.mp4
ProtossCarrierInterceptorGif.gif

More interceptors:
Uploadfiles.io - ProtossCarrierInterceptor2.mp4
ProtossCarrierInterceptor2Gif.gif

Right now my simulation is like this:
Uploadfiles.io - ProtossCarrierInterceptorWcIIISimulation.mp4
ProtossCarrierInterceptorWcIIISimulationGif.gif
 

Attachments

  • ProtossShieldsTestX.w3x
    81.8 KB · Views: 51
Last edited:
I need help with the interceptor moving system. I can't figure how to check and when so that they randomly shift facing toward or not opposite the target and start moving toward that direction.

I'm thinking something with a unit comes within range and conditioning the distance between the interceptors and their target while checking every 0.1 so that if stunned or moved, the interceptors won't lose their orders.

Using regions and moving them isn't viable if the target is near the map edges because the regions will be moved past(?) the map boundary. But not sure checking the distance between the interceptors and their targets is viable in this context either.

An integer adds +1 to itself and is considered the phases necessary in the conditions of the 0.1s periodic event.

Any ideas, please?

Video of what I'm trying to come close to achieving:
Uploadfiles.io - ProtossCarrierInterceptor.mp4

More interceptors:
Uploadfiles.io - ProtossCarrierInterceptor2.mp4

Right now my simulation is like this:
Uploadfiles.io - ProtossCarrierInterceptorWcIIISimulation.mp4

Posting it here as well in case anyone wants to improve it.

This is absolutely not leakless, but it's something to work with. It gives the desired effect so it's just a matter of implementing it into your map in an efficient, leakless and MUI way if needed. There are some issues with acquiring new targets but it only happens sometimes.
 

Attachments

  • Movement stuff 3.w3x
    56.7 KB · Views: 47

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
Since I'm too retarded to turn GUI into MUI when it comes to secondary units indexed to the primary indexed units, I'll leave the carrier system and the newly made reaver system for one unit.

Sneak peak reaver-scarab system:
reaverScarabSimulation.gif

Both scarab and carrier interceptor creations are based on the Berserk spell.

EDIT: made following scarabs spawn once in 2 seconds, not immediately after impact.
 

Attachments

  • ProtossShieldsTest.w3x
    83 KB · Views: 46
Last edited:

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
@Uncle, I know you're gonna kill me but do you have any idea why the protoss shield text in the name of units (test with the footman; map in the opening/first post or in the post above) doesn't appear in 1.35? I understand it's related to the periodic regeneration trigger but I've no idea why the name doesn't want to properly change like in 1.31.1 or below.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
@Uncle, I know you're gonna kill me but do you have any idea why the protoss shield text in the name of units (test with the footman; map in the opening/first post or in the post above) doesn't appear in 1.35? I understand it's related to the periodic regeneration trigger but I've no idea why the name doesn't want to properly change like in 1.31.1 or below.
The SetUnitName function worked when I tested it in a different map. Also, it looks like a bunch of the Actions in the above map have become disabled. I reenabled them but it still doesn't work, so I'm not exactly sure what's going on.

Also, this system seems to be Adding individual units to the Shield Units Damaged trigger via the "Add Event" action, which seems a bit dated since we now have the "A unit Takes damage" and "A unit is about to Take damage" Events readily available in GUI. A lot of things about it are pretty strange or outdated if I'm being completely honest.

I think this could be improved a lot by implementing the mentioned Event + a Unit Indexer + a Hashtable + an ability that can be added to units in the OE as a Shield condition.
  • Shields Take Damage
    • Events
      • Unit - A unit Takes damage
    • Conditions
      • (Level of Uses Shields (Hidden) for (Damage target)) Greater than 0
    • Actions
      • Set Variable DamageTarget = (Damage target)
      • Set Variable DamageTaken = (Damage taken)
      • Set Variable CV = (Custom value of DamageTarget)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DamageTaken Greater than Shields_Current[CV]
        • Then - Actions
          • Event Response - Set Damage of Unit Damaged Event to (DamageTaken - Shields_Current[CV])
          • Set Variable Shields_Current[CV] = 0.00
        • Else - Actions
          • Event Response - Set Damage of Unit Damaged Event to 0.00
          • Set Variable Shields_Current[CV] = (Shields_Current[CV] - DamageTaken)
  • Shields Setup
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
      • (Level of Uses Shields (Hidden) for (Triggering unit)) Greater than 0
    • Actions
      • Set Variable CV = (Custom value of (Triggering unit))
      • Set Variable Shields_Max[CV] = Load some Real from a Hashtable using the unit's Unit-Type id as the Parent Key
      • Set Variable Shields_Current[CV] = Shields_Max[CV]
 
Last edited:

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
Thanks. Don't mind the disabled stuff. The unit name change works in 1.31.1 or 1.30.4 but not in 1.35 and I wanted to know if some triggers maybe related to changing unit names or strings don't properly work in 1.35.
I know there are better event triggers in 1.35 as it comes with an inbuilt damage detection system. I haven't yet started working with that.
By the way, what does "about to take damage" exactly do? When does it trigger? Is it something like "casts an ability or starts the effect of"?
Also, why do I need an ability for the indexing?
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
Thanks. Don't mind the disabled stuff. The unit name change works in 1.31.1 or 1.30.4 but not in 1.35 and I wanted to know if some triggers maybe related to changing unit names or strings don't properly work in 1.35.
I know there are better event triggers in 1.35 as it comes with an inbuilt damage detection system. I haven't yet started working with that.
By the way, what does "about to take damage" exactly do? When does it trigger? Is it something like "casts an ability or starts the effect of"?
Also, why do I need an ability for the indexing?
The ability serves as a Classification to simplify your Conditions. It's efficient and quick to the point.

Anyway, the name changing stuff works in 1.35, it's something else that's causing a problem with your system. Reworking it the way I suggested would more than likely fix it since you'd eliminate a lot of the weirdness that's likely causing the issues.
 
Last edited:

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
You have to understand that I'm a sublayman.

Well, the name change stops working if you add |n since I want the shield numbers to appear under the name. It works in the older patches mentioned above.
I see, you may need custom UI for the names then or maybe there's another easy way to do it still.

And the ability Condition idea is basically to simplify this:
  • A
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Unit-type of (Triggering unit)) Equal to Zealot
          • (Unit-type of (Triggering unit)) Equal to Dragoon
          • (Unit-type of (Triggering unit)) Equal to Archon
    • Actions
To this:
  • B
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
      • (Level of Uses Shields (Hidden) for (Triggering unit)) Equal to 1
    • Actions
If your Zealot, Dragoon, and Archon all have this ability then your trigger no longer needs to ask 3+ questions.
 

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
I see, you may need custom UI for the names then or maybe there's another way to do it still.
Meddling with the UI is a horror fest for me. I want to keep it as simple as possible.
And the Condition idea is basically to simplify this:
I see. Thanks. So, each number represents one of those unit types, right?

Also, a question. Is the action custom value modifying the point value (unit editor: Stats - Point Value: [number]) of units?
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
Meddling with the UI is a horror fest for me. I want to keep it as simple as possible.

I see. Thanks. So, each number represents one of those unit types, right?

Also, a question. Is the action custom value modifying the point value (unit editor: Stats - Point Value: [number]) of units?
Not exactly, I'm just checking to see if the unit has the ability or not. If a unit doesn't have an ability then the level will be Equal to 0. In this case the Uses Shield ability only has 1 level so checking if it's level is Equal to 1 is the equivalent to asking "Does this unit have the ability or not?" since it will either be 0 or 1.

Custom Value is not found in the Object Editor, it's meant to be used in triggers. All units have a default custom value of 0.

It's best to never set Custom Value yourself and instead use a Unit Indexer system which will manage the Custom Value of your units for you automatically. This allows you to create variable arrays that use Custom Value as their [index], which can then be used to store any data you want to a unit. In this case I was storing the unit's current and max shields in two Real array variables.
 
Last edited:

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
I was bored so I threw together something similar to your existing Shields system. It's definitely missing some of the goodies your system had but I believe it should be a bit more efficient. It was designed to be exactly like the Protoss Shields from Starcraft 2, although I reduced the shield delay for testing purposes.

I'm using the methods I described before as well as a timer system I made which manages the delay before the regen starts and the actual regeneration per second.
 

Attachments

  • Protoss Shields.w3m
    52.6 KB · Views: 3
Last edited:

deepstrasz

Map Reviewer
Level 68
Joined
Jun 4, 2009
Messages
18,706
I was bored so I threw together something similar to your existing Shields system. It's definitely missing some of the goodies your system had but I believe it should be a bit more efficient. It was designed to be exactly like the Protoss Shields from Starcraft 2, although I reduced the shield delay for testing purposes.

I'm using the methods I described before as well as a timer system I made which manages the delay before the regen starts and the actual regeneration per second.
Awesome. StarCraft II-like. You could upload that in the Spells section.

It's best to never set Custom Value yourself and instead use a Unit Indexer system which will manage the Custom Value of your units for you automatically. This allows you to create variable arrays that use Custom Value as their [index], which can then be used to store any data you want to a unit. In this case I was storing the unit's current and max shields in two Real array variables.
Being the rebel snake I am, I did quite the opposite.
So, I present to you a remade shield system that uses unit custom values (not entirely necessary though/could be replaced with the next mentioned) and unit get ability reals. The deal is that it doesn't use any arrays or loops but uses unit groups and periodic event triggers. It can also seem a bit convoluted since it uses dummy abilities and their real value changes and tracking.

What it offers:
  • a StarCraft-like shield system using the above mentioned stuff and 1.35's inbuilt GUI damage events and conditions that ignores or not (depending on the user's desire) unit armour; no Uncle-like out of combat regeneration only (post)
  • value based shield regeneration, percentage based shield and value based armour upgrades; these then become base values
  • auras: value shield regeneration and degeneration, value shield increase and decrease, percentage shield armour increase and decrease; these abilities are based on dummy tech to track the level of the caster's ability and also rely on get unit ability reals for value indexing
  • AoE abilities: percentage shield regeneration and degeneration (based on Silence which triggers a buff but cannot be simultaneously used on the same unit/hero caster due to the same order id; the first can be dispelled, the second cannot as it uses a dummy buff ability based on Cloak of Flames but also requires a dummy cooldown ability which was based on a huge amount of mana costing Berserk); the rest are based on Channel (different order ids so they can be used on the same unit/hero caster) and cannot be dispelled as they follow the same deal as shield degeneration: percentage shield increase and decrease, value shield armour increase and decrease

Limitations:
  • shield regeneration takes place once in 1 second; there's no sophisticated formula to calculate regeneration for milliseconds depending on how big the regeneration or decrease is
  • for some reason changing get unit ability real values once in 1 seconds for around 50 or more units makes the game lag each second
  • the game also lags quite badly if the shield carrying units are hit very fast and all at the same time like when being damaged by multiple Mutalisk/Huntress type units or by very fast attacking area splash damage units; the latter is mostly due to the shield hit FX rendering while the first is probably mostly related to get unit ability real changes as mentioned in the second point of this list
  • there is no custom UI to show the shield other than clicking on the unit and reading it near its name; there's a shield hit FX though so if it triggers it means the unit still has shields on
  • the |n feature is broken in 1.35 and the shield and shield armour values can't be put under the unit name and are after it which necessitates using a short unit name for all the text to show
  • in 1.35 hero proper and unit name changing is bugged so sadly, the shield doesn't work/show on heroes
  • custom abilities with percentage value increase or decrease act on base real values rather than being dynamic; I tried but I kept getting wrong values and soon lost interest or I'd have lost my sanity
  • the game's auras are in a way bugged as they do not perfectly apply or deactivate; there's a lag with the latter and they don't always if ever apply or deactivate at the same time when coming from the same caster
  • the shield FX might remain behind when very fast moving shield carrying units are hit
@Uncle do you think this is worthy of the Spells section somewhat?
 

Attachments

  • StarCraftLikeSystems.w3m
    89.2 KB · Views: 5
Last edited:
Status
Not open for further replies.
Top