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

Chronosphere v1.1

Help I accidentally made a spell!!!

Chronosphere:
Opens a rip in spacetime, causing everything to be locked in time except the caster. Lasts 4/6/8 seconds.


Chronosphere by NightSkyAurora

No need to give credits to me. I didn't invent this spell, I just made an approved (almost) version for everyone to use.

Credits:
PGRU-Unexpected - Chronosphere model
Maker - Pause concept

note: I added a stand animation to the chronosphere model so it won't fade after 6 seconds. It's file size is also smaller than the one in dota.

How to import:
¯¯¯¯¯¯¯¯¯¯¯
1. File -> Preferences -> Automaticly create unknown variables while pasting trigger data
2. Export chronosphere model and add it to your map
3. Copy the Pause and Chronosphere spells to your map
4. Copy the Chronosphere unit to your map.
5. Copy the Chronosphere trigger folder to your map
6. Ensure that _Pause and CH_Model is set properly in the ini trigger and add the ini trigger's code to YUOR map's ini trigger
7. Rate this spell
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


  • ini
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- This following spell can be used anywhere in your map as an alternative to pause --------
      • Set _Pause = Pause
      • -------- configurable --------
      • Set Config_CH_Spell = Chronosphere
      • Set Config_CH_Unit = Chronosphere
      • Set Config_CH_Duration = 2.00
      • Set Config_CH_lvlDuration = 2.00
      • Set Config_CH_AoE = 400.00
      • Set Config_CH_lvlAoE = 0.00
      • -------- Model causes lag on first cast.... Preloading. --------
      • Custom script: call RemoveUnit(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), udg_Config_CH_Unit, 0, 0, 0))
  • Chronosphere ini
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Config_CH_Spell
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CH_Dex Equal to 0
        • Then - Actions
          • Trigger - Turn on Chronosphere loop <gen>
        • Else - Actions
      • Set CH_Dex = (CH_Dex + 1)
      • Set CH_Caster[CH_Dex] = (Triggering unit)
      • Set CH_lvl = (Level of Config_CH_Spell for CH_Caster[CH_Dex])
      • Set CH_p = (Target point of ability being cast)
      • -------- Chronosphere dummy must be owned by caster, otherwise true sight will not work --------
      • Unit - Create 1 Config_CH_Unit for (Owner of CH_Caster[CH_Dex]) at CH_p facing Default building facing degrees
      • Custom script: call RemoveLocation(udg_CH_p)
      • Set CH_Effect[CH_Dex] = (Last created unit)
      • Unit - Add a (Config_CH_Duration + ((Real(CH_lvl)) x Config_CH_lvlDuration)) second Generic expiration timer to CH_Effect[CH_Dex]
      • Set CH_AoE[CH_Dex] = (Config_CH_AoE + ((Real(CH_lvl)) x Config_CH_lvlAoE))
      • -------- Next function has no effect if AoE is 400 --------
      • -------- The chronosphere looks odd if it's size is not 100%. I'm not a modeler so I can't fix it. If that is a probelm, use a diffirent model or fix it yourself. --------
      • Animation - Change CH_Effect[CH_Dex]'s size to ((CH_AoE[CH_Dex] / 4.00)%, 0.00%, 0.00%) of its original size
  • Chronosphere loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer CH_i) from 1 to CH_Dex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (CH_Effect[CH_i] is alive) Equal to True
            • Then - Actions
              • Set CH_p = (Position of CH_Effect[CH_i])
              • Custom script: set bj_wantDestroyGroup=true
              • -------- I know I don't have to filter Chronosphere since it has locust and won't be picked, but for some reason - if I don't filter chronosphere - then the chronospheres can pause each other... --------
              • Unit Group - Pick every unit in (Units within CH_AoE[CH_i] of CH_p) and do (Actions)
                • Loop - Actions
                  • Set CH_unit = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • CH_unit Not equal to CH_Caster[CH_i]
                      • (Unit-type of CH_unit) Not equal to Chronosphere
                    • Then - Actions
                      • Unit Group - Add CH_unit to CH_Group
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (CH_unit is in CH_Group2) Equal to False
                        • Then - Actions
                          • Unit - Add _Pause to CH_unit
                          • Unit - Order CH_unit to Human Footman - Defend
                          • Unit - Pause the expiration timer for CH_unit
                          • Animation - Change CH_unit's animation speed to 0.00% of its original speed
                          • Unit Group - Add CH_unit to CH_Group2
                        • Else - Actions
                    • Else - Actions
              • Custom script: call RemoveLocation(udg_CH_p)
            • Else - Actions
              • Set CH_Caster[CH_i] = CH_Caster[CH_Dex]
              • Set CH_Effect[CH_i] = CH_Effect[CH_Dex]
              • Set CH_AoE[CH_i] = CH_AoE[CH_Dex]
              • Set CH_Dex = (CH_Dex - 1)
              • Set CH_i = (CH_i - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CH_Dex Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
      • Unit Group - Pick every unit in CH_Group2 and do (Actions)
        • Loop - Actions
          • Set CH_unit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (CH_unit is in CH_Group) Equal to False
            • Then - Actions
              • Unit - Remove _Pause from CH_unit
              • Unit - Unpause the expiration timer for CH_unit
              • Animation - Change CH_unit's animation speed to 100.00% of its original speed
              • Unit Group - Remove CH_unit from CH_Group2
            • Else - Actions
      • Unit Group - Remove all units from CH_Group



v1.1
-Changed filtering method
-Changed some variable names
-Use GUI function to clear groups

v1.0d
-Fixed as suggested here

v1.0c
-Moved the condition that turns looping trigger off back to the bottom
-Removed unnecessary group clear
-Removes unit from CH_Group

v1.0b
-Fixed configuration structure
-Only checks if spell instances are 0 upon de-index
Contents

Chronosphere (Map)

Reviews
00:12, 5th June 2016 Tank-Commander: V1.0c - Problems resolved, approved (might want to change the filename to match the version number though) - could do with some minor improvements for the filtering method (setting a variable to a picked unit and...

Moderator

M

Moderator

00:12, 5th June 2016
Tank-Commander: V1.0c - Problems resolved, approved (might want to change the filename to match the version number though) - could do with some minor improvements for the filtering method (setting a variable to a picked unit and then filtering) but it's short and sweet

10:58, 30th May 2016
Tank-Commander: V1.0 - The code still has needless structural issues from before (configuration should be part of the init and it is possible to only check if the group is empty upon recycling, while I know you said this glitches it, it doesn't make it impossible) given the simplicity of the spell I'd like to see these resolved - the spell is otherwise pretty good
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
  • Put all the configurables in a config trigger. There is no reason to always have to cache the configurables on cast
  • Add a configurable for the main ability
  • Avoid using single action functions (If/Then/Else)
  • Add a configurable for the chronosphere unit
  • For the Animation - Change Size function, you only need to change the value of the first field
  • You can merge the "spell" and "ini" trigger
  • For the unit group enumeration where you pause units in the area, add a filter that only pauses units that aren't already paused
  • Out of curiousity, why do you order paused units to "Human Footman - Defend" and why do you pause their "expiration timer"? Another question to add is why do they have an expiration timer in the first place?
  • You don't have to set Caster and Effect to "No unit"
  • I don't quite understand why you add them into a unit group like CH_Group and Temp_Targets when you remove them from the group every 0.03 seconds. You can just add them into a global unit group that makes it so that they don't get paused by another instance, and then a unit group array that pauses them from a specific instance. Maybe I'm just not understanding the logic completely, so an explanation would be nice.
 
Put all the configurables in a config trigger. There is no reason to always have to cache the configurables on cast
Isn't that the second trigger?

Add a configurable for the main ability
Avoid using single action functions (If/Then/Else)
Ok I will in next update

Add a configurable for the chronosphere unit
Check second action in second trigger

For the Animation - Change Size function, you only need to change the value of the first field
Thanks, didn't knew

You can merge the "spell" and "ini" trigger
Ok can work ^^

For the unit group enumeration where you pause units in the area, add a filter that only pauses units that aren't already paused
I wanted to do that but I forgot >.< I just fixed it.

Out of curiousity, why do you order paused units to "Human Footman - Defend"

The unit isn't paused. By casting that ability, the unit will look like it is paused (Defend is a cast ID of an channel ability)
why do you pause their "expiration timer"?
I intend to pause the life span of timed units such as illusions - a logical side effect when you are freezed in space time.

Another question to add is why do they have an expiration timer in the first place?
To improve performance, otherwise I have to store spell duration in a variable. You mean the targets? They don't.

You don't have to set Caster and Effect to "No unit"
Having a lot of variables that aren't null makes the game take long to exit. It is just good coding behaviour for me but I'll remove it.

I don't quite understand why you add them into a unit group like CH_Group and Temp_Targets when you remove them from the group every 0.03 seconds. You can just add them into a global unit group that makes it so that they don't get paused by another instance, and then a unit group array that pauses them from a specific instance. Maybe I'm just not understanding the logic completely, so an explanation would be nice.

That is the secret behind the spell's performance. Pausing units is easy, but how do you unpause them? "Pick every unit in all units matching unit is in pausedGroup equal to false"? Not only is that inefficient, it will also cause bugs with other spells that pauses units (unless you check if the unit is in pausedGroup in every other spell).

The dual group approach only compares units that WAS affected by chronosphere with the units that IS affected by chronosphere. If a unit is in CH_Group, it means that it WAS paused by chronosphere. I only need to check if that unit must still be paused by chronosphere (by checking if that unit is in Temp_Targets). In this way, I don't have to worry about units that was never paused in the first place.

Thank you for your review :grin:
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Isn't that the second trigger?
Check second action in second trigger
It's pointless to be caching constant variables on cast. They should only be once, and that is on map init.

The unit isn't paused. By casting that ability, the unit will look like it is paused (Defend is a cast ID of an channel ability)
Ahh I didn't test the map itself, I just looked at the triggers. Clever approach.

That is the secret behind the spell's performance. Pausing units is easy, but how do you unpause them? "Pick every unit in all units matching unit is in pausedGroup equal to false"? Not only is that inefficient, it will also cause bugs with other spells that pauses units (unless you check if the unit is in pausedGroup in every other spell)
And you think enumerating through unit group loops every 0.03 seconds is more efficient? xD On a side note, I didn't realize they weren't actually being paused. I still think it would be better to add affected units into a unit group array for the instance, and a global unit group to keep track of who is affected by all instances. This would mean you only clear the unit groups once, and that is during deindex.
 
  • Like
Reactions: ILH
I'm a little confused. What should be configurated in the config trigger?


What if the unit is in 2 chronospheres? If 1 chronosphere ends, the unit will be unpaused inside another chronospher,


Edit: dude after doing what you said in your 7th statement, the spell stops working!!!! I already uploaded that bug and now I cant fix it before I dont have wc3 with me :(
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I'm a little confused. What should be configurated in the config trigger?
Constant variables like duration, duration per level, the dummy unit, ability, etc.


What if the unit is in 2 chronospheres? If 1 chronosphere ends, the unit will be unpaused inside another chronospher
Why would they be unpaused if they are inside another chronosphere...?


dude after doing what you said in your 7th statement, the spell stops working!!!! I already uploaded that bug and now I cant fix it before I dont have wc3 with me :(
Please update the triggers so I can see what you did.
 
Most of the key things have already been said by KILLCIDE though I have this to add:
- Your spell has recycling errors - AOE is not recycled leading to other instances getting incorrect AOEs
- You only need to check to turn off the trigger when you recycle
- A stun system could be utilised to stop the units from acting, this way orders will not be cancelled and you don't need to worry about keeping track of affected units in a global group
- The spell is very functionally similar to Stop [v1.1] I would suggest adding some other features to make it stand out more
 
Constant variables like duration, duration per level, the dummy unit, ability, etc.
But that is what I did in the Chronosphere spell trigger. no?

Why would they be unpaused if they are inside another chronosphere...?
Sorry I think I misunderstood you. Do you mean each spell instance should have its own unit group? As well as a global unit group containing all the instance groups? If that is the case, I don't see the point of turning "Temp_Targets" into an array. Why not add all affected units to only 1 group? I then only need to compare 2 groups to each other when unpausing units.

Please update the triggers so I can see what you did.

Fixed. Spell is functioning again.
===================================
Your spell has recycling errors - AOE is not recycled leading to other instances getting incorrect AOEs
Thanks, I'll fix that.

You only need to check to turn off the trigger when you recycle
I tried that. It stops the spell from working...

A stun system could be utilised to stop the units from acting, this way orders will not be cancelled and you don't need to worry about keeping track of affected units in a global group
I try to make my spell as resource-independent as possible but I'll check out that system

The spell is very functionally similar to Stop [v1.1] I would suggest adding some other features to make it stand out more
I only intended to make an approved version of chronosphere from DotA but I get your point. I'll add features such as stopping life & mana regen and some eye candy :thumbs_up:
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Please update your triggers if you made changes!

But that is what I did in the Chronosphere spell trigger. no?
It should be in a map init trigger. Do you see any sense in constantly storing "3.00" into CH_Duration and "0.00" into CH_lvlAoE every single time the spell is casted? You only have to do them once, and not every single time on cast.


Sorry I think I misunderstood you. Do you mean each spell instance should have its own unit group? As well as a global unit group containing all the instance groups? If that is the case, I don't see the point of turning "Temp_Targets" into an array. Why not add all affected units to only 1 group? I then only need to compare 2 groups to each other when unpausing units.
Keeping them in a group array lets you "unpause" them when the instance is done. Keeping them in a global group lets you pause units that need to be paused.
 
Please update your triggers if you made changes!
I updated the triggers...

It should be in a map init trigger. Do you see any sense in constantly storing "3.00" into CH_Duration and "0.00" into CH_lvlAoE every single time the spell is casted? You only have to do them once, and not every single time on cast.
Right >.< I thought users might use it for various spells spells - each with its own configurations - but I guess its only used in systems. I'll fix that.

Keeping them in a group array lets you "unpause" them when the instance is done
How would you know if a unit is not in another instance group before unpausing it?
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I updated the triggers...
I was talking about the description. I still see the same triggers from when you first uploaded it.

How would you know if a unit is not in another instance group before unpausing it?
If they are in the global group, that means they are still affected by an instance. You add units to the global group when they are affected by a chronosphere. When the spell instance deindexes, you remove them from the global group.
 
31a74a423b.png


So if spell 1 ends, I remove it from the instance group and check if it is in the global group before unpausing it? It will ALWAYS be in the global group because instance 1 is in the global group.

If I remove instance 1 from the global group, it might remove units inside other chronospheres as well.

I'll add a change log in next update.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I never said anything about unpausing units. The global group is to make sure that you don't pause units that are already paused. You unpause units from an instance by using the unit group array like I suggested. On deindex, you select the units in the unit group array, "unpause" them, and then remove them from the global group so that they may be affected by another instance.
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
Gather around everyone, because this is the time again I'm going to explain to the reviewers as to why Pause is used instead of stun.

- A stun system could be utilised to stop the units from acting, this way orders will not be cancelled and you don't need to worry about keeping track of affected units in a global group

Ahh no. The purpose of the Chronosphere is to pause almost everything what's inside:
1) Buffs.
2) Animations
3) other states.

Why not stun???? first of all it can't do the 1 and 3.
About 2, Pause can preserve the current played animation meanwhile stun will reset the animation to "stand" and play the start of the animation.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Gather around everyone, because this is the time again I'm going to explain to the reviewers as to why Pause is used instead of stun.
The "reviewer" would like to know where units are ever paused in Night's triggers :) on a side note, I never suggested to use stun over pause, nor did I ever show a disagreement to actually using a pause.
 
I never said anything about unpausing units. The global group is to make sure that you don't pause units that are already paused. You unpause units from an instance by using the unit group array like I suggested. On deindex, you select the units in the unit group array, "unpause" them, and then remove them from the global group so that they may be affected by another instance.

If the unit is in 2 chronospheres and Chronospheres 2 ends, the unit will be unpaused for 0.03 seconds till the loop fires again...
 
Level 22
Joined
Aug 27, 2013
Messages
3,973
Pausing a unit using the channel ability? A clever approach indeed. It never occurred to me to do so.

Anyways, have you updated the spell and followed KILLCIDE's instructions? Please update the triggers in the description, add changelogs, and state the versions. I'm confused when looking at this.
 
Do you know how fast 30 milliseconds is? If you can catch the 0.03 seconds where the unit is "unpaused," then you can leave the code as it is and join the olympics.

Lol I wish... but it will just look ugly if the animation if the animation twitches. Also another possible bug in your method is if the unit is moved outside the chronosphere, the unit will remain paused until the sphere ends because units are only unpaused at the end of the spell instance.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Lol I wish... but it will just look ugly if the animation if the animation twitches.
Fair enough.

If the unit is moved outside the chronosphere, the unit will remain paused until the sphere ends because units are only unpaused at the end of the spell instance.
How would they move out if theyre paused?
 
The performance isn't that much of an issue. I just think it's more readable.
I'll add comments explaining what I do :)

I think units should be only under effect as long as they're really in range.
Also optimaly no time-gap should be at some moment in between.

You might think of using 2 data structures. One for looping through "effects" and one for handling all targets.
Thanks for you opinion. Just curious how do I use two data structures? I'm not really familiar with that.
 
Updated
By checking if there are 0 spell instances only on de-indexing forced me to make some redundant code. At least its more efficient.

I also thought about whether I should make this spell more unique or not. I decided that, since I intended on only make a simple spell from dota that is surprisingly hard to find, I prefer it to be this simple. I'm planning on making an advanced chronosphere that will use unit indexers and a DDS in the near future which can be used as an alternative if you don't like the simple version.
 
You don't need the added redundant code - you just need(ed) to fix the error you had in when you pick every unit in CH_Group at the bottom - note that when you check if they're not in temp targets you only remove them from temp targets, not CH_Group meaning CH_Group continues to contain all units ever affected by the spell (meaning they cannot be influenced by another casting of the spell) also the groupclear lines you do when recycling are also not needed
 
I unpaused all units in the group upon de-index:

  • Chronosphere loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer Temp_Int) from 1 to CH_Dex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (CH_Effect[Temp_Int] is alive) Equal to True
            • Then - Actions
              • Set Temp_Point = (Position of CH_Effect[Temp_Int])
              • Custom script: set bj_wantDestroyGroup=true
              • -------- I know I don't have to filter Chronosphere since it has locust and won't be picked, but for some reason - if I don't filter chronosphere - then the chronospheres can pause each other... --------
              • Unit Group - Pick every unit in (Units within CH_AoE[Temp_Int] of Temp_Point matching (((Matching unit) Not equal to CH_Caster[Temp_Int]) and ((Unit-type of (Matching unit)) Not equal to Config_CH_Unit))) and do (Actions)
                • Loop - Actions
                  • Set Temp_Unit = (Picked unit)
                  • Unit Group - Add Temp_Unit to Temp_Targets
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Temp_Unit is in CH_Group) Equal to False
                    • Then - Actions
                      • Unit - Add _Pause to Temp_Unit
                      • Unit - Order Temp_Unit to Human Footman - Defend
                      • Unit - Pause the expiration timer for Temp_Unit
                      • Animation - Change Temp_Unit's animation speed to 0.00% of its original speed
                      • Unit Group - Add Temp_Unit to CH_Group
                    • Else - Actions
              • Custom script: call RemoveLocation(udg_Temp_Point)
            • Else - Actions
              • Set CH_Caster[Temp_Int] = CH_Caster[CH_Dex]
              • Set CH_Effect[Temp_Int] = CH_Effect[CH_Dex]
              • Set CH_AoE[Temp_Int] = CH_AoE[CH_Dex]
              • Set CH_Dex = (CH_Dex - 1)
              • Set Temp_Int = (Temp_Int - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CH_Dex Equal to 0
                • Then - Actions
                  • Unit Group - Pick every unit in CH_Group and do (Actions)
                    • Loop - Actions
                      • Set Temp_Unit = (Picked unit)
                      • Unit - Remove _Pause from Temp_Unit
                      • Unit - Unpause the expiration timer for Temp_Unit
                      • Animation - Change Temp_Unit's animation speed to 100.00% of its original speed
                      • Unit Group - Remove Temp_Unit from CH_Group
                  • Custom script: call GroupClear(udg_CH_Group)
                  • Trigger - Turn off (This trigger)
                • Else - Actions
      • Unit Group - Pick every unit in CH_Group and do (Actions)
        • Loop - Actions
          • Set Temp_Unit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Temp_Unit is in Temp_Targets) Equal to False
            • Then - Actions
              • Unit - Remove _Pause from Temp_Unit
              • Unit - Unpause the expiration timer for Temp_Unit
              • Animation - Change Temp_Unit's animation speed to 100.00% of its original speed
              • Unit Group - Remove Temp_Unit from CH_Group
            • Else - Actions
      • Custom script: call GroupClear(udg_Temp_Targets)

This makes the trigger look much longer though
 
It isn't needed to make it functional - here's the solution I created through modifying your original code


  • Chronosphere loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer Temp_Int) from 1 to CH_Dex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (CH_Effect[Temp_Int] is alive) Equal to True
            • Then - Actions
              • Set Temp_Point = (Position of CH_Effect[Temp_Int])
              • Custom script: set bj_wantDestroyGroup=true
              • -------- I know I don't have to filter Chronosphere since it has locust and won't be picked, but for some reason - if I don't filter chronosphere - then the chronospheres can pause each other... --------
              • Unit Group - Pick every unit in (Units within CH_AoE[Temp_Int] of Temp_Point matching (((Matching unit) Not equal to CH_Caster[Temp_Int]) and ((Unit-type of (Matching unit)) Not equal to Config_CH_Unit))) and do (Actions)
                • Loop - Actions
                  • Set Temp_Unit = (Picked unit)
                  • Unit Group - Add Temp_Unit to Temp_Targets
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Temp_Unit is in CH_Group) Equal to False
                    • Then - Actions
                      • Unit - Add _Pause to Temp_Unit
                      • Unit - Order Temp_Unit to Human Footman - Defend
                      • Unit - Pause the expiration timer for Temp_Unit
                      • Animation - Change Temp_Unit's animation speed to 0.00% of its original speed
                      • Unit Group - Add Temp_Unit to CH_Group
                    • Else - Actions
              • Custom script: call RemoveLocation(udg_Temp_Point)
            • Else - Actions
              • Set CH_Caster[Temp_Int] = CH_Caster[CH_Dex]
              • Set CH_Effect[Temp_Int] = CH_Effect[CH_Dex]
              • Set CH_AoE[Temp_Int] = CH_AoE[CH_Dex]
              • Set CH_Dex = (CH_Dex - 1)
              • Set Temp_Int = (Temp_Int - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CH_Dex Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
      • Unit Group - Pick every unit in CH_Group and do (Actions)
        • Loop - Actions
          • Set Temp_Unit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Temp_Unit is in Temp_Targets) Equal to False
            • Then - Actions
              • Unit - Remove _Pause from Temp_Unit
              • Unit - Unpause the expiration timer for Temp_Unit
              • Animation - Change Temp_Unit's animation speed to 100.00% of its original speed
              • Unit Group - Remove Temp_Unit from CH_Group
            • Else - Actions
      • Custom script: call GroupClear(udg_Temp_Targets)
You don't clear the group upon deindex - all the units in the group will be removed by virtue of the spell ending as
  • (CH_Effect[Temp_Int] is alive) Equal to True
returns false causing Temp_Targets to contain no units (as it is cleared at the end of the previous iteration), resulting in the CH_Group pick at the bottom de-pausing and removing all units within CH_Group - when a trigger is turned off it still finishes executing, it just disables the event listener from starting it again
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
All though the spell is approved, I just have some minor suggestions:
  • Add prefixes to the variables _Pause, Temp_Point, Temp_Int, Temp_Unit, and Temp_Targets so that it doesn't conflict with global variables people might have in their maps
  • (Matching unit) is ugly and inefficient. I recommend using an If/Then/Else that directly compares your filters to the (Picked unit). It's not only easier to read, but much easier to add/remove filters if you need too
  • Not much of a suggestion, but more of a question... why do you use the JASS native to clear the unit group instead of the GUI function?
 
All though the spell is approved, I just have some minor suggestions:
  • Add prefixes to the variables _Pause, Temp_Point, Temp_Int, Temp_Unit, and Temp_Targets so that it doesn't conflict with global variables people might have in their maps
  • (Matching unit) is ugly and inefficient. I recommend using an If/Then/Else that directly compares your filters to the (Picked unit). It's not only easier to read, but much easier to add/remove filters if you need too
  • Not much of a suggestion, but more of a question... why do you use the JASS native to clear the unit group instead of the GUI function?

The Temp prefix means that the the variable holds useful data for only a very short period (temporarily). That same variable can be used in many spells without conflict (that is what I do and it works for me). If it conflicts with global variables in someone's map then the user is most likely abusing the Temp prefix.

What prefix would you suggest for pause? Remember that that spell variable may be used outside the chronospheres so I don't see point of adding CS in front of it just because chronospheres is one of its uses.

I only have 2 filters for matching and find that inefficient to add them and remove them later but, since you and tank recommend it, I'll fix it.

Wait there is a GUI function for group clear?? :nw:

Once again thanks for the review :thumbs_up:
 
All names of global/public variables, functions, triggers, etc, should be uniquly named to ensure integrity.
If "Temp_Unit" is used as global system variable, then it's more likely that the user also uses such a variable name for his own use.
If that's really the case, then it can easily result in an unwanted effect because the imported spell code can manipulate, or reset objects or variables outside it's own scope.

The user does maybe not take it into account that his "Temp_Unit" variable will have an other value after random units on map casts this spell, and so might get weird errors else where.
Finaly, it's good practice to create system-only data, so the system becomes foreclosed to any else manipulation for the user's map, but the wanted result - casting spells.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I only have 2 filters for matching and find that inefficient to add them and remove them later but, since you and tank recommend it, I'll fix it.
(Matching unit) is less efficient when you have multiple filters. The main reason also is how hard it is to read compared to using an If/Then/Else. It also wasn't just a suggestion for now, but for the future when you want to filter out units again. Take a look at this tutorial I made about this topic.
 
  • out of curiousity, why do you order paused units to "human footman - defend
the unit isn't paused. By casting that ability, the unit will look like it is paused (defend is a cast id of an channel ability)


I made the changes as suggested by KILLCIDE. I will upload right after 12 AM (UTC +2)
 
Top