1. Fill your cup and take your pick among the maps best suited for this year's Hive Cup. The 6th Melee Mapping Contest Poll is up!
    Dismiss Notice
  2. Shoot to thrill, play to kill. Sate your hunger with the 33rd Modeling Contest!
    Dismiss Notice
  3. Do you hear boss music? It's the 17th Mini Mapping Contest!
    Dismiss Notice
  4. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Why does this trigger ignore the invulnerable effect sometimes?

Discussion in 'Triggers & Scripts' started by Dinodin, Jul 11, 2014.

  1. Dinodin

    Dinodin

    Joined:
    Jul 19, 2007
    Messages:
    515
    Resources:
    2
    Maps:
    2
    Resources:
    2
    +SOLVED+

    I got a problem with one of my triggered spells and can't see why it crashes sometimes. It's meant to give the casting Hero and all other friendly Heroes in the map an invulnerability for a short period of time after the Hero has casted the spell sometimes it gives the invulnerability like it should and sometimes it ignores it, why does it happening?

    The triggers of the spell.
    • Divine Light Cast
      • Events
        • Unit - A unit Finishes casting an ability
      • Conditions
        • (Ability being cast) Equal to Divine Light
      • Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • DivineLightIndex Equal to 0
          • Then - Actions
            • Trigger - Turn on Divine Light Loop <gen>
          • Else - Actions
        • Custom script: set bj_wantDestroyGroup = true
        • Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
          • Loop - Actions
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • ((Picked unit) is A Hero) Equal to True
                • ((Picked unit) belongs to an ally of (Triggering player)) Equal to True
              • Then - Actions
                • Set DivineLightIndex = (DivineLightIndex + 1)
                • Set DivineLightUnit[DivineLightIndex] = (Picked unit)
                • Set DivineLightDur[DivineLightIndex] = (0.00 + (2.00 x (Real((Level of Divine Light for (Triggering unit))))))
                • Unit - Add Invulnerable (Divine Light) to DivineLightUnit[DivineLightIndex]
              • Else - Actions

    • Divine Light Loop
      • Events
        • Time - Every 0.25 seconds of game time
      • Conditions
      • Actions
        • For each (Integer DivineLightLoop) from 1 to DivineLightIndex, do (Actions)
          • Loop - Actions
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • DivineLightDur[DivineLightLoop] Less than or equal to 0.00
              • Then - Actions
                • Unit - Remove Invulnerable (Divine Light) from DivineLightUnit[DivineLightLoop]
                • Set DivineLightDur[DivineLightLoop] = DivineLightDur[DivineLightIndex]
                • Set DivineLightUnit[DivineLightLoop] = DivineLightUnit[DivineLightIndex]
                • Set DivineLightIndex = (DivineLightIndex - 1)
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • DivineLightIndex Equal to 0
                  • Then - Actions
                    • Trigger - Turn off (This trigger)
                  • Else - Actions
              • Else - Actions
                • Set DivineLightDur[DivineLightLoop] = (DivineLightDur[DivineLightLoop] - 0.25)
     
    Last edited: Aug 21, 2014
  2. Bannar

    Bannar

    Joined:
    Mar 19, 2008
    Messages:
    3,099
    Resources:
    20
    Spells:
    5
    Tutorials:
    1
    JASS:
    14
    Resources:
    20
    This is some bad indexing design.

    Let's assume you caught 100 units and made them invurneable. DivineLightIndex would be set to 100.
    Now, when a unit gets removed from loop the trigger, the so mentioned DivineLightIndex will be decreased. E.g removal of first unit (DivineLightUnit[] with index 1) from the loop would effectively reduce iteration size to 99. That doesn't mean that unit DivineLightUnit[100] has been already removed, thus reference to such unit is lost (or rather its just omited, since it's still being stored in global array).

    Fix your indexing method or use Bribe's UnitIndexer for GUI.
     
  3. Dinodin

    Dinodin

    Joined:
    Jul 19, 2007
    Messages:
    515
    Resources:
    2
    Maps:
    2
    Resources:
    2
    Well I didn't create this trigger, someone else helped me but I don't remember that user so he can't help me fix it and I'm kinda noobish at triggering..
     
  4. Gismo359

    Gismo359

    Joined:
    Jul 14, 2011
    Messages:
    780
    Resources:
    44
    Packs:
    4
    Maps:
    40
    Resources:
    44
    Well, unit variables dont cause leaks, afaik. Or is there some other reason it should be done in another way?

    Also, when you reduce DivineLightIndex, you should reduce DivineLightLoop, too.

    EDIT: Cant you just use a dummy unit with a spell based of Big Bad Voodoo, and add an expiration timer to him?
     
  5. Dinodin

    Dinodin

    Joined:
    Jul 19, 2007
    Messages:
    515
    Resources:
    2
    Maps:
    2
    Resources:
    2
    lol that sounds abit to complicated and i'm not sure that will be very effective.. there should be some way to fix the trigger of it instead because 50% of the times it works like it should and 50% of the times it doesn't..
     
  6. McQvaBlood

    McQvaBlood

    Joined:
    Jul 3, 2010
    Messages:
    529
    Resources:
    44
    Packs:
    4
    Maps:
    40
    Resources:
    44
    I have provided the simplest solution I could think of. It will completely replace these, by the way, non-MUI and terribly scripted triggers.
    I have also added detailed description of what each of these three triggers do so you can understand what you're doing, instead of adopting random triggers.

    (1) Cast Trigger
    • DivLight Cast
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Divine Light
      • Actions
        • Set TempInteger = 0
        • For each (Integer A) from 1 to 10, do (Actions)
          • Loop - Actions
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • TempInteger Equal to 0
                • (Number of units in Divine_Light_GROUP[(Integer A)]) Equal to 0
              • Then - Actions
                • Set TempInteger = (Integer A)
              • Else - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • TempInteger Not equal to 0
          • Then - Actions
            • Set Divine_Light_GROUP[TempInteger] = (Units in (Playable map area) matching ((((Matching unit) belongs to an ally of (Owner of (Casting unit))) Equal to True) and (((Matching unit) is A Hero) Equal to True)))
            • Unit Group - Pick every unit in Divine_Light_GROUP[TempInteger] and do (Actions)
              • Loop - Actions
                • Unit - Make (Picked unit) Invulnerable
            • Countdown Timer - Start Divine_Light_TIMER[TempInteger] as a One-shot timer that will expire in (0.00 + (2.00 x (Real((Level of Divine Light for (Casting unit)))))) seconds
          • Else - Actions

    • The first part is a very basic GUI indexing system. We set TempInteger, a global integer, to 0. Then we iterate with A from 0 to 10. If we find a Divine_Light_GROUP, a global unit group, that is empty, we set TempInteger to whatever index that has, say 3. This in turn stops the loop because we loop only while TempInteger is 0.
    • To ensure we don't run out of indexes we check if TempInteger is really not 0.
    • We add all heroes on the map to our DivineLight_GROUP[TempInteger] and run a DivineLight_TIMER, a global timer.
    (2) Expire Trigger
    • DivLight Timer
      • Events
      • Conditions
      • Actions
        • For each (Integer A) from 1 to 10, do (Actions)
          • Loop - Actions
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • (Remaining time for Divine_Light_TIMER[(Integer A)]) Equal to 0.00
                • (Number of units in Divine_Light_GROUP[(Integer A)]) Not equal to 0
              • Then - Actions
                • Unit Group - Pick every unit in Divine_Light_GROUP[(Integer A)] and do (Actions)
                  • Loop - Actions
                    • Set TempBoo = True
                    • For each (Integer B) from 1 to 10, do (Actions)
                      • Loop - Actions
                        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                          • If - Conditions
                            • (Integer A) Not equal to (Integer B)
                            • ((Picked unit) is in Divine_Light_GROUP[(Integer B)]) Equal to True
                          • Then - Actions
                            • Set TempBoo = False
                          • Else - Actions
                    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      • If - Conditions
                        • TempBoo Equal to True
                      • Then - Actions
                        • Unit - Make (Picked unit) Vulnerable
                      • Else - Actions
                • Custom script: call DestroyGroup(udg_Divine_Light_GROUP[GetForLoopIndexA()])
              • Else - Actions
    • You may notice that I declared no event. The event is that any of my 10 Divine_Light_TIMERS expire. However, I'm lazy enough to do this instead. Adding them one by one also works, but this is much faster when you need 100 timers for example.
      (3) Lazy
      • DivLight I
        • Events
          • Map initialization
        • Conditions
        • Actions
          • For each (Integer A) from 1 to 10, do (Actions)
            • Loop - Actions
              • Trigger - Add to DivLight Timer <gen> the event (Time - Divine_Light_TIMER[(Integer A)] expires)
    • I check to see if any of my Divine_Light_GROUPs are not empty while their timer expired, which would signal that it is time for them to turn vulnerable again.
    • However, I run a Loop with B to see if they are in another group making them invulnerable, as this would require them to stay invulnerable.
    • I null the group I loaded them into after turning them back vulnerable.
     
  7. Dinodin

    Dinodin

    Joined:
    Jul 19, 2007
    Messages:
    515
    Resources:
    2
    Maps:
    2
    Resources:
    2
    Oh that's a much more complicated triggers..but if it makes the ability work like it should then it's good. Btw I have an Invulnerable-ability for the spell, can I just replace the "Make (Picked Unit) Invulnerable" to "Add Invulnerable (Divine Light) to (Picked Unit)"?? Could also maybe post a map with the triggers so I can simply copy and paste them into my map?
     
  8. McQvaBlood

    McQvaBlood

    Joined:
    Jul 3, 2010
    Messages:
    529
    Resources:
    44
    Packs:
    4
    Maps:
    40
    Resources:
    44
    Yes, you can just replace it with an ability add line. I already did this in the map I'm posting for you.

    I didn't feel like creating any abilities in the object editor, so I'm currently using Animate Dead as the base spell and Evasion as the spell that it gives.

    You can very quickly change it to whatever you want. I added two more lines to Divine Light INIT.
    INIT
    • Divine Light INIT
      • Events
        • Map initialization
      • Conditions
      • Actions
        • Set zz_DivLight_SPELL = Animate Dead
        • Set zz_DivLight_SPELL_DUMMY = Evasion (Neutral Hostile)
        • For each (Integer A) from 1 to 10, do (Actions)
          • Loop - Actions
            • Trigger - Add to Divine Light DONE <gen> the event (Time - Divine_Light_TIMER[(Integer A)] expires)
    Simply replace these values:
    • zz_DivLight_SPELL should point to the ability the hero casts.
    • zz_DivLight_SPELL_DUMMY should point to the ability that you made to make the heroes invulnerable.

    EDIT
    If you want to perhaps change how long the spell lasts, you can change the very last line of Divine Light cast.
    • Countdown Timer - Start Divine_Light_TIMER[TempInteger] as a One-shot timer that will expire in (0.00 + (2.00 x (Real((Level of zz_DivLight_SPELL for (Casting unit)))))) seconds
    It currently lasts 2/4/6 seconds. If you wanted it to last 5/8/11 seconds instead, it would look like this:
    • Countdown Timer - Start Divine_Light_TIMER[TempInteger] as a One-shot timer that will expire in (2.00 + (3.00 x (Real((Level of zz_DivLight_SPELL for (Casting unit)))))) seconds
     

    Attached Files:

  9. Dat-C3

    Dat-C3

    Joined:
    Mar 15, 2012
    Messages:
    2,530
    Resources:
    10
    Models:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    1
    Resources:
    10
    Actually unit variables do indeed cause leaks, GUI'ers need to learn to set their unit variables to no unit.
     
  10. Dinodin

    Dinodin

    Joined:
    Jul 19, 2007
    Messages:
    515
    Resources:
    2
    Maps:
    2
    Resources:
    2
    Oh thank so much for the help! The spell works like it should now and I hope it will not cause any more bugs.