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

Status
Not open for further replies.
Yup, the jass thing works! Thanks guys.

I've found that the jass chronosphere also have a bug. when I rip a victem out of the sphere then they stay paused. I'm gonna ask you guys a favour and I'm pretty sure that this would work:
  • Chronosphere spell
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Chronosphere
    • Actions
      • If (iChronosMaxIndex Greater than 23) then do (Set iChronosMaxIndex = 1) else do (Set iChronosMaxIndex = (iChronosMaxIndex + 1))
      • Set uChronosCaster[iChronosMaxIndex] = (Casting unit)
      • Set Temp_Point = (Target point of ability being cast)
      • Unit - Create 1 Chronosphere for (Owner of uChronosCaster[iChronosMaxIndex]) at Temp_Point facing Default building facing degrees
      • Custom script: call RemoveLocation(udg_Temp_Point)
      • Set uChronosEffect[iChronosMaxIndex] = (Last created unit)
      • Unit - Add a 6.00 second Generic expiration timer to (Last created unit)
      • Unit Group - Add (Last created unit) to gChronosTarget[0]
      • Trigger - Turn on Chronosphere loop <gen>
      • -------- Caster and dummy is saved --------
  • Chronosphere loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • If ((Number of units in gChronosEffect[0]) Equal to 0) then do (Trigger - Turn off (This trigger)) else do (Do nothing)
      • For each (Integer Temp_Int) from 1 to iChronosMaxIndex, do (Actions)
        • Loop - Actions
          • -------- Get group --------
          • Set pChronos[Temp_Int] = (Position of uChronosEffect[Temp_Int])
          • Set gChronosTarget[1] = (Units within 400.00 of pChronos[Temp_Int] matching ((Matching unit) Not equal to uChronosCaster[Temp_Int]))
          • Custom script: call RemoveLocation(udg_pChronos[udg_Temp_Int])
          • Unit Group - Pick every unit in gChronosTarget[1] and do (Actions)
            • Loop - Actions
              • Unit Group - Remove (Picked unit) from gChronosTarget[0]
Basicly what I want someone to do is paused every unit in target[1] and send them to [0]. (remove them from [1] ofcourse)
IF the target qualifies to be in target[1] (inside the sphere) then they should be removed from target[0] and remain paused.
ELSE they should stay in target[0] to be unpaused and removed from target[0]
I tried that but doesn't get it to work.

Please see my previous trigger post if you don't understand well.

Here is the file...

and +rep to death for all the general help :)
 

Attachments

  • Chronosphere.w3x
    25.6 KB · Views: 40
Level 20
Joined
Jul 14, 2011
Messages
3,213
There's no need for a group of "Units that are not in the other group"

U know, you can add a Tornado Aura to the Chronosphere with no effect wich doesn't show up in the Unit's Buff bar. You can then, when the Chrono is created, pick every unit in the map wit the ChronoAuraBuff and pause them. If the unit is pulled outside the Chrono the buff is removed and the unit is unpased. You could test.

Another work around is Pick every Chrono Sphere and Pick every unit around the Chronospheres and check if distance between Chrono and Target is less than or equal to 400, if so, pause, else, unpause and remove from group.
 
There's no need for a group of "Units that are not in the other group"

U know, you can add a Tornado Aura to the Chronosphere with no effect wich doesn't show up in the Unit's Buff bar. You can then, when the Chrono is created, pick every unit in the map wit the ChronoAuraBuff and pause them. If the unit is pulled outside the Chrono the buff is removed and the unit is unpased. You could test.

Another work around is Pick every Chrono Sphere and Pick every unit around the Chronospheres and check if distance between Chrono and Target is less than or equal to 400, if so, pause, else, unpause.

I tried that, but it takes about half a second for the units to get the buff :(
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
another work around is pick every chrono sphere and pick every unit around the chronospheres and check if distance between chrono and target is less than or equal to 400, if so, pause, else, unpause.
1234
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Behold :ogre_rage:

CAST CHRONOSPHERE TRIGGER
JASS:
globals
    hashtable ChronosphereHash = InitHashtable()
    group ChronosphereGroup = CreateGroup()
    group ChronosphereUnits = CreateGroup()
endglobals

// This happens when the Chronosphere Timer expires
function ChronosphereClear takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer i = GetHandleId(t)
    local unit u = LoadUnitHandle(ChronosphereHash, i, 0) 
    local unit fog 
    
    call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), 400, null)
    loop
        set fog = FirstOfGroup(bj_lastCreatedGroup)
        exitwhen fog == null
        call PauseUnit(fog, false)
        call GroupRemoveUnit(bj_lastCreatedGroup, fog)
        call GroupRemoveUnit(ChronosphereUnits, fog)
        call SetUnitTimeScale(fog, 1)
    endloop
    
    call GroupRemoveUnit(ChronosphereGroup, u)
    call FlushChildHashtable(ChronosphereHash, i)
    call KillUnit(u)
    call RemoveUnit(u)
    
    // Turn off Loop if ChronosphereGroup is empty
    set bj_groupCountUnits = 0
    call ForGroup(ChronosphereGroup, function CountUnitsInGroupEnum)
    if bj_groupCountUnits == 0 then
        call DisableTrigger(gg_trg_ChronoLoop)
        call BJDebugMsg("ChronosphereGroup empty. ChronoLOOP Disabled")
    endif
    
    set t = null
    set u = null
    set fog = null
endfunction

// ID of Chronosphere ability
function Trig_ChronoCast_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

// Chronosphere Cast
function Trig_ChronoCast_Actions takes nothing returns nothing
    local real x = GetSpellTargetX()
    local real y = GetSpellTargetY()
    local unit Chrono = CreateUnit(GetTriggerPlayer(), 'h000', x, y, 0)
    local timer t = CreateTimer()
    
    call TimerStart(t, 6, false, function ChronosphereClear)
    call SaveUnitHandle(ChronosphereHash, GetHandleId(t), 0, Chrono)
    call GroupAddUnit(ChronosphereGroup, Chrono)
    call EnableTrigger(gg_trg_ChronoLoop)
    
    set Chrono = null
    set t = null
endfunction

//===========================================================================
function InitTrig_ChronoCast takes nothing returns nothing
    set gg_trg_ChronoCast = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ChronoCast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_ChronoCast, Condition( function Trig_ChronoCast_Conditions ) )
    call TriggerAddAction( gg_trg_ChronoCast, function Trig_ChronoCast_Actions )
endfunction


CHRONOSPHERE LOOP
JASS:
// Pause Enum units around Chronospheres (Excep Caster type units)
function ChronosphereUnitsPause takes nothing returns nothing
    local unit u = GetEnumUnit()
        call PauseUnit(u, true)
        call SetUnitTimeScale(u, 0)
    set u = null
endfunction

// Enum units around Chronospheres, add them to ChronosphereUnits if they're not.
function ChronosphereUnitsEnum takes nothing returns nothing
    local unit u = GetEnumUnit()
    local unit fog
    
    // Add units in range to ChronosphereUnits (And pause them)
    call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), 400, null)
    loop
        set fog = FirstOfGroup(bj_lastCreatedGroup)
        exitwhen fog == null
        if IsUnitInGroup(fog, ChronosphereUnits) == FALSE and GetWidgetLife(fog) > 0 and GetUnitTypeId(fog) != 'Hpal' then
            call GroupAddUnit(ChronosphereUnits, fog)
            call SaveUnitHandle(ChronosphereHash, GetHandleId(fog), 0, u)
            call BJDebugMsg("Unit is alive, not in ChronosphereUnits, and it's not a CasterType. Added to ChronosphereUnits")
        endif
        call GroupRemoveUnit(bj_lastCreatedGroup, fog)
    endloop
    
    call ForGroup(ChronosphereUnits, function ChronosphereUnitsPause)
    
    set u = null
endfunction

// Unpause if Distance between Unit and Chronosphere is greater than 400
function ChronosphereUnitsActions takes nothing returns nothing
    local unit u = GetEnumUnit()
    local integer i = GetHandleId(u)
    local unit Chrono = LoadUnitHandle(ChronosphereHash, i, 0)
    local real x = GetUnitX(Chrono) - GetUnitX(u)
    local real y = GetUnitY(Chrono) - GetUnitY(u)

    if /*This is the Distance -> */ SquareRoot(x*x + y*y) > 400 then 
        call BJDebugMsg("Distance is greater than 400. Unit unpaused")
        call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\DispelMagic\\DispelMagicTarget.mdl", GetUnitX(u), GetUnitY(u)))
        
        call PauseUnit(u, false)
        call SetUnitTimeScale(u, 1)
        call GroupRemoveUnit(ChronosphereUnits, u)
        call FlushChildHashtable(ChronosphereHash, i)
    endif
    
    set u = null
    set Chrono = null
endfunction

// Do the Pause around Chronospheres and Unpause if they're far away.
function ChronosphereGroupActions takes nothing returns nothing
    call ForGroup(ChronosphereGroup, function ChronosphereUnitsEnum )
    call ForGroup(ChronosphereUnits, function ChronosphereUnitsActions)
endfunction

//===========================================================================
function InitTrig_ChronoLoop takes nothing returns nothing
    set gg_trg_ChronoLoop = CreateTrigger(  )
    call DisableTrigger( gg_trg_ChronoLoop )
    call TriggerRegisterTimerEvent(gg_trg_ChronoLoop, 0.03, true)
    call TriggerAddAction( gg_trg_ChronoLoop, function ChronosphereGroupActions )
endfunction
 

Attachments

  • Chronosphere.w3x
    20 KB · Views: 27
Last edited:
Behold :ogre_rage:

CAST CHRONOSPHERE TRIGGER
JASS:
globals
    hashtable ChronosphereHash = InitHashtable()
    group ChronosphereGroup = CreateGroup()
    group ChronosphereUnits = CreateGroup()
endglobals

// This happens when the Chronosphere Timer expires
function ChronosphereClear takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer i = GetHandleId(t)
    local unit u = LoadUnitHandle(ChronosphereHash, i, 0) 
    local unit fog 
    
    call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), 400, null)
    loop
        set fog = FirstOfGroup(bj_lastCreatedGroup)
        exitwhen fog == null
        call PauseUnit(fog, false)
        call GroupRemoveUnit(bj_lastCreatedGroup, fog)
        call GroupRemoveUnit(ChronosphereUnits, fog)
        call SetUnitTimeScale(fog, 1)
    endloop
    
    call GroupRemoveUnit(ChronosphereGroup, u)
    call FlushChildHashtable(ChronosphereHash, i)
    call KillUnit(u)
    call RemoveUnit(u)
    
    // Turn off Loop if ChronosphereGroup is empty
    set bj_groupCountUnits = 0
    call ForGroup(ChronosphereGroup, function CountUnitsInGroupEnum)
    if bj_groupCountUnits == 0 then
        call DisableTrigger(gg_trg_ChronoLoop)
        call BJDebugMsg("ChronosphereGroup empty. ChronoLOOP Disabled")
    endif
    
    set t = null
    set u = null
    set fog = null
endfunction

// ID of Chronosphere ability
function Trig_ChronoCast_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

// Chronosphere Cast
function Trig_ChronoCast_Actions takes nothing returns nothing
    local real x = GetSpellTargetX()
    local real y = GetSpellTargetY()
    local unit Chrono = CreateUnit(GetTriggerPlayer(), 'h000', x, y, 0)
    local timer t = CreateTimer()
    
    call TimerStart(t, 6, false, function ChronosphereClear)
    call SaveUnitHandle(ChronosphereHash, GetHandleId(t), 0, Chrono)
    call GroupAddUnit(ChronosphereGroup, Chrono)
    call EnableTrigger(gg_trg_ChronoLoop)
    
    set Chrono = null
    set t = null
endfunction

//===========================================================================
function InitTrig_ChronoCast takes nothing returns nothing
    set gg_trg_ChronoCast = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_ChronoCast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_ChronoCast, Condition( function Trig_ChronoCast_Conditions ) )
    call TriggerAddAction( gg_trg_ChronoCast, function Trig_ChronoCast_Actions )
endfunction


CHRONOSPHERE LOOP
JASS:
// Pause Enum units around Chronospheres (Excep Caster type units)
function ChronosphereUnitsPause takes nothing returns nothing
    local unit u = GetEnumUnit()
        call PauseUnit(u, true)
        call SetUnitTimeScale(u, 0)
    set u = null
endfunction

// Enum units around Chronospheres, add them to ChronosphereUnits if they're not.
function ChronosphereUnitsEnum takes nothing returns nothing
    local unit u = GetEnumUnit()
    local unit fog
    
    // Add units in range to ChronosphereUnits (And pause them)
    call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), 400, null)
    loop
        set fog = FirstOfGroup(bj_lastCreatedGroup)
        exitwhen fog == null
        if IsUnitInGroup(fog, ChronosphereUnits) == FALSE and GetWidgetLife(fog) > 0 and GetUnitTypeId(fog) != 'Hpal' then
            call GroupAddUnit(ChronosphereUnits, fog)
            call SaveUnitHandle(ChronosphereHash, GetHandleId(fog), 0, u)
            call BJDebugMsg("Unit is alive, not in ChronosphereUnits, and it's not a CasterType. Added to ChronosphereUnits")
        endif
        call GroupRemoveUnit(bj_lastCreatedGroup, fog)
    endloop
    
    call ForGroup(ChronosphereUnits, function ChronosphereUnitsPause)
    
    set u = null
endfunction

// Unpause if Distance between Unit and Chronosphere is greater than 400
function ChronosphereUnitsActions takes nothing returns nothing
    local unit u = GetEnumUnit()
    local integer i = GetHandleId(u)
    local unit Chrono = LoadUnitHandle(ChronosphereHash, i, 0)
    local real x = GetUnitX(Chrono) - GetUnitX(u)
    local real y = GetUnitY(Chrono) - GetUnitY(u)

    if /*This is the Distance -> */ SquareRoot(x*x + y*y) > 400 then 
        call BJDebugMsg("Distance is greater than 400. Unit unpaused")
        call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\DispelMagic\\DispelMagicTarget.mdl", GetUnitX(u), GetUnitY(u)))
        
        call PauseUnit(u, false)
        call SetUnitTimeScale(u, 1)
        call GroupRemoveUnit(ChronosphereUnits, u)
        call FlushChildHashtable(ChronosphereHash, i)
    endif
    
    set u = null
    set Chrono = null
endfunction

// Do the Pause around Chronospheres and Unpause if they're far away.
function ChronosphereGroupActions takes nothing returns nothing
    call ForGroup(ChronosphereGroup, function ChronosphereUnitsEnum )
    call ForGroup(ChronosphereUnits, function ChronosphereUnitsActions)
endfunction

//===========================================================================
function InitTrig_ChronoLoop takes nothing returns nothing
    set gg_trg_ChronoLoop = CreateTrigger(  )
    call DisableTrigger( gg_trg_ChronoLoop )
    call TriggerRegisterTimerEvent(gg_trg_ChronoLoop, 0.03, true)
    call TriggerAddAction( gg_trg_ChronoLoop, function ChronosphereGroupActions )
endfunction

erm... sometimes the heroes runs right through without being paused, however you gave me a great idea; HASHTABLES :D. I can't believe I forgot about those. I got so obsessed with arrays. Right now I''m studying for IT but I'll try again tomorrow with hastables and please I prefere GUI. Thanks for sharing by the way :)

EDIT: Ey guys I made a request yesterday for a spell and scourge096 sloved it without even thinking.

+rep to everyone for your effort in this thread. You guys deserve it! :goblin_yeah:
 
Last edited:
Level 20
Joined
Jul 14, 2011
Messages
3,213
Actually, i got confused with another post who asked to create a Dota's ability. in Dota the caster unit type (Void) can go through any chronosphere. That's why i did it this way. Thankfully it's easy to solve :)
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
If you solved the thing with this Chronosphere you should post the final result so others with the same doubt/problem may use it instead of having to discuss all this again :p
 
:ogre_hurrhurr:
  • Chronosphere A
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Chronosphere
    • Actions
      • -------- If CS_Switch is equal to 0, turn on trigger B --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CS_Switch Equal to 0
        • Then - Actions
          • Trigger - Turn on Chronosphere B <gen>
        • Else - Actions
      • -------- Increase CS_CastNumber by 1, this determines the number of times the spell has been casted --------
      • Set CS_CastNumber = (CS_CastNumber + 1)
      • -------- Increase CS_Switch --------
      • Set CS_Switch = (CS_Switch + 1)
      • Set CS_Off[CS_CastNumber] = True
      • -------- Set other variables --------
      • Set CS_Caster[CS_CastNumber] = (Triggering unit)
      • Set CS_Point[0] = (Target point of ability being cast)
      • -------- Set duration to 150 because 6 devided by 0.04(interval in trigger B) is equal to 150. --------
      • -------- Every second is equal to 25! --------
      • Set CS_Duration[CS_CastNumber] = 150
      • -------- Create a dummy unit at target location and store it to a variable --------
      • Unit - Create 1 Dummy Unit - UNIVERSAL UNIT for (Owner of CS_Caster[CS_CastNumber]) at CS_Point[0] facing Default building facing degrees
      • Set CS_Dummy[CS_CastNumber] = (Last created unit)
      • Custom script: set udg_CS_Hit[udg_CS_CastNumber] = CreateGroup()
      • -------- Removing leaks --------
      • Custom script: call RemoveLocation (udg_CS_Point[0])
  • Chronosphere B
    • Events
      • Time - Every 0.04 seconds of game time
    • Conditions
    • Actions
      • For each (Integer CS) from 1 to CS_CastNumber, do (Actions)
        • Loop - Actions
          • -------- Checks if CS_Off is set to true to execute the following lines. --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CS_Off[CS] Equal to True
            • Then - Actions
              • -------- Store the location of CS_Dummy to CS_Point[0] --------
              • Set CS_Point[0] = (Position of CS_Dummy[CS])
              • -------- Pick every units within 600 AoE of CS_Dummy's point excluding caster then add it to CS_Hit --------
              • Custom script: set bj_wantDestroyGroup=true
              • Unit Group - Pick every unit in (Units within 600.00 of CS_Point[0] matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is in CS_Hit[CS]) Not equal to True) and ((Matching unit) Not equal to CS_Caster[CS])))) and do (Actions)
                • Loop - Actions
                  • Unit Group - Add (Picked unit) to CS_Hit[CS]
              • -------- Pause units in CS_Hit --------
              • Unit Group - Pick every unit in CS_Hit[CS] and do (Actions)
                • Loop - Actions
                  • Set CS_Point[1] = (Position of (Picked unit))
                  • -------- Pauses and sets the animation speed of units in CS_Hit to 0 to stop their motion. --------
                  • Unit - Pause (Picked unit)
                  • Animation - Change (Picked unit)'s animation speed to 0.00% of its original speed
                  • -------- Since the spell does not include special effects I will just change the color of affected units. --------
                  • Animation - Change (Picked unit)'s vertex coloring to (100.00%, 75.00%, 0.00%) with 0.00% transparency
                  • -------- If targets distance from CS_Point[0] is greater than 600, it is automatically unpaused. --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Distance between CS_Point[0] and CS_Point[1]) Greater than 600.00
                    • Then - Actions
                      • Unit - Unpause (Picked unit)
                      • Animation - Change (Picked unit)'s animation speed to 100.00% of its original speed
                      • Animation - Change (Picked unit)'s vertex coloring to (100.00%, 100.00%, 100.00%) with 0.00% transparency
                      • Unit Group - Remove (Picked unit) from CS_Hit[CS]
                    • Else - Actions
              • Set CS_Duration[CS] = (CS_Duration[CS] - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CS_Duration[CS] Equal to 0
                • Then - Actions
                  • Set CS_Off[CS] = False
                  • -------- Returns paused units to normal --------
                  • Unit Group - Pick every unit in CS_Hit[CS] and do (Actions)
                    • Loop - Actions
                      • Unit - Unpause (Picked unit)
                      • Animation - Change (Picked unit)'s animation speed to 100.00% of its original speed
                      • Animation - Change (Picked unit)'s vertex coloring to (100.00%, 100.00%, 100.00%) with 0.00% transparency
                      • Unit Group - Remove (Picked unit) from CS_Hit[CS]
                  • Custom script: call DestroyGroup (udg_CS_Hit[udg_CS])
                  • Set CS_Switch = (CS_Switch - 1)
                • Else - Actions
              • Custom script: call RemoveLocation (udg_CS_Point[0])
            • Else - Actions
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
I'm not sure of how much you NEEDED this to be GUI. The main difference here is you're using several global variables arrays (I use one hash and locals) and unit groups (I used 2 groups) 3 "Pick every Unit" Loops inside a "For Each Integer" loop. (Pretty heavy), a bunch of BJ's (I used Natives) and use of Location (i used X/Y) and a Variable-Timer, while i use a real timer. My point here is that those GUI triggers are slower and heavier that the ones I provided.

-.-

Anyway, it's good to know you got a solution, and I improved a bit my "coding" skills
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
I did it already for you :) What do you want to customize?

I added these to configure:
JASS:
globals    
    integer SpartChronoS_UnitId = 'h000'           // ID of the Chronosphere Dummy
    integer SpartChronoS_AbilityId = 'A000'        // ID of the Chronosphere Ability 
    real SpartChronoS_Radius = 400                 // The Chronosphere Radius
    real SpartChronoS_ALI = 1                      // ALI = Ability Level Influence.
    real SpartChronoS_Duration = 3                 // Default duration. Formula is: "Duration + (AbiLvl * ALI)"
    hashtable SpartChronoS_Hash = InitHashtable()  // Don't touch this
    group SpartChronoS_Spheres = CreateGroup()     // Don't touch this
    group SpartChronoS_Targets = CreateGroup()     // Don't touch this
endglobals

I already solved the enemy players not being paused. What else would you like to customize, besides DummyId, AbilityId, Radius, Duration and level Influence?

The only "bug" right now is that the units that are in two chronospheres at the same time becomes unpaused for 0.03 seconds after one of them expires. Not really important and can be solved if it's really necessary.
 

Attachments

  • Chronosphere.w3x
    19.9 KB · Views: 27
I was playing around with chronosphere in my free time and came up with this.
  • Chronosphere spell
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Chronosphere
    • Actions
      • If (iChronosIndex Greater than 23) then do (Set iChronosIndex = 1) else do (Set iChronosIndex = (iChronosIndex + 1))
      • Set uChronosCaster[iChronosIndex] = (Casting unit)
      • Set Temp_Point = (Target point of ability being cast)
      • Unit - Create 1 Chronosphere for (Owner of uChronosCaster[iChronosIndex]) at Temp_Point facing Default building facing degrees
      • Custom script: call RemoveLocation(udg_Temp_Point)
      • Set uChronosEffect[iChronosIndex] = (Last created unit)
      • Unit - Add a 6.00 second Generic expiration timer to (Last created unit)
      • Unit Group - Add (Last created unit) to gChronosTarget[0]
      • Trigger - Turn on Chronosphere loop <gen>
      • -------- Caster and dummy is saved --------
  • Chronosphere loop
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • If ((Number of units in gChronosEffect[0]) Equal to 0) then do (Trigger - Turn off (This trigger)) else do (Do nothing)
      • For each (Integer Temp_Int) from 1 to 24, do (Actions)
        • Loop - Actions
          • -------- Get 'pause' group --------
          • Set pChronos[Temp_Int] = (Position of uChronosEffect[Temp_Int])
          • Set gChronosTarget[1] = (Units within 400.00 of pChronos[Temp_Int] matching ((Matching unit) Not equal to uChronosCaster[Temp_Int]))
          • Custom script: call RemoveLocation(udg_pChronos[udg_Temp_Int])
          • -------- Remove units from 'unpause' group --------
          • Unit Group - Pick every unit in gChronosTarget[1] and do (Actions)
            • Loop - Actions
              • Unit Group - Remove (Picked unit) from gChronosTarget[0]
      • -------- unpause units in 'unpause' group --------
      • Unit Group - Pick every unit in gChronosTarget[0] and do (Actions)
        • Loop - Actions
          • -------- I used vertex coloring to see if the unit is in this group --------
          • Animation - Change (Picked unit)'s vertex coloring to (0.00%, 0.00%, 0.00%) with 0.00% transparency
          • Unit - Unpause (Picked unit)
          • Animation - Change (Picked unit)'s animation speed to 100.00% of its original speed
          • Custom script: call DestroyGroup(udg_gChronosTarget[0])
      • -------- Pause units in 'pause' group --------
      • Unit Group - Pick every unit in gChronosTarget[1] and do (Actions)
        • Loop - Actions
          • Unit - Pause (Picked unit)
          • Animation - Change (Picked unit)'s animation speed to 0.00% of its original speed
          • Unit Group - Add (Picked unit) to gChronosTarget[0]
          • Custom script: call DestroyGroup(udg_gChronosTarget[1])
In my opinion is this very simple programmed but still it doesn't work. Do you guys think that I'm far off the track or could this work? If it can, then what am I doing wrong?
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
No. That in the UniTGroup variable you have to set the default size of the variable to the number of array index you're going to use. IF you use 0 and 1, set the size of the array to 1 for that variable.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
I give up. I've tried to do this several times without achieving it. I can't avoid the small 0.03 time gap between one Sphere unpause and the next one pausing it when they're simultaneously over the same unit :(
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
The thing is Adding the Chronosphere to a Group (g1)
Pick all units in g1 , and add them to a anotherGroup (g2)
Then check distance between each unit of g2 and each unit of g1, and check if the Chronosphere is still alive

Right before the chronosphere expires (0.031 seconds before) kill it, so in the next timer expiration (0.03 duration) it's dead, so they will be unpaused, BUT if there is any other chronosphere over the unit, it will be paused again so fast that's not even noticeable so, there won't be 0.03 unpause gap.

If you have 3 Chronospheres and 12 units around, that would make 3 GroupEnum and 36 distance checks for each ChronosphereTimer, making it 9 GroupEnum, 108 distance checks :( I'd would love a way to avoid those nested loops, and be able to detect somehow the event without having to loop every 0.03. Maybe with Bribe's system that detects a unit movement you could check that, if the unit moves, and it's in the g2, then, and only then, check distance.

I already have it in a single trigger with timers.

JASS:
/************************************************
 *****            Configurables             *****
*************************************************/    
globals    
    integer SpartChronoS_UnitId = 'h000'           // ID of the Chronosphere Dummy
    integer SpartChronoS_AbilityId = 'A000'        // ID of the Chronosphere Ability 
    real SpartChronoS_Radius = 400                 // The Chronosphere Radius
    real SpartChronoS_ALI = 1                      // ALI = Ability Level Influence.
    real SpartChronoS_Duration = 3                 // Default duration. Formula is: "Duration + (AbiLvl * ALI)"
    hashtable SpartChronoS_Hash = InitHashtable()  // Don't touch this
    group SpartChronoS_Units = CreateGroup()       // Don't touch this
    group SpartChronoS_Targets = CreateGroup()     // Don't touch this
endglobals


/************************************************
 *****             Don't touch              *****
 ************************************************/

function SpartChronoS_TargetsActions takes nothing returns nothing
    local unit u = GetEnumUnit()
    local integer i = GetHandleId(u)
    local unit chrono = LoadUnitHandle(SpartChronoS_Hash, i, 0)
    local real x = GetUnitX(u) - GetUnitX(chrono)
    local real y = GetUnitY(u) - GetUnitY(chrono)
    local real distance = SquareRoot(x*x + y*y)
    
    if distance < SpartChronoS_Radius and GetWidgetLife(chrono) > 0 then
        call PauseUnit(u, true)
        call SetUnitTimeScale(u, 0)
    else
        call PauseUnit(u, false)
        call SetUnitTimeScale(u, 1)
        call GroupRemoveUnit(SpartChronoS_Targets, u)
        call FlushChildHashtable(SpartChronoS_Hash, i)
    endif

    set u = null
    set chrono = null
endfunction

function SpartChronoS_UnitsActions takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer i = GetHandleId(t)
    local unit caster = LoadUnitHandle(SpartChronoS_Hash, i, 0)
    local unit chrono = LoadUnitHandle(SpartChronoS_Hash, i, 1)
    local real duration = LoadReal(SpartChronoS_Hash, i, 2) - 0.03
    local group g = bj_lastCreatedGroup
    local unit fog
    
    if duration > 0.031 then
        call SaveReal(SpartChronoS_Hash, i, 2, duration)
        call GroupEnumUnitsInRange(g, GetUnitX(chrono), GetUnitY(chrono), SpartChronoS_Radius, null)
        loop
            set fog = FirstOfGroup(g)
            exitwhen fog == null
            if GetWidgetLife(fog) > 0 and fog != caster and IsUnitInGroup(fog, SpartChronoS_Targets) == false then
                call GroupAddUnit(SpartChronoS_Targets, fog)
                call SaveUnitHandle(SpartChronoS_Hash, GetHandleId(fog), 0, chrono)
            endif
            call GroupRemoveUnit(g, fog)
        endloop
    elseif duration < 0.031 and duration > 0 then
        call KillUnit(chrono)
    elseif duration <= 0 then
        call FlushChildHashtable(SpartChronoS_Hash, i)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif
    
    call ForGroup(SpartChronoS_Targets, function SpartChronoS_TargetsActions)
    
    set t = null
    set caster = null
    set chrono = null
    set g = null
endfunction

// If Ability Being Cast = Chronosphere...
function SpartChronoS_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == SpartChronoS_AbilityId
endfunction

// Chronosphere Cast
function SpartChronoS_Actions takes nothing returns nothing
    local real x = GetSpellTargetX()
    local real y = GetSpellTargetY()
    local unit Chrono = CreateUnit(GetTriggerPlayer(), SpartChronoS_UnitId, x, y, 0)
    local unit u = GetTriggerUnit()
    local real duration = SpartChronoS_Duration + (GetUnitAbilityLevel(u, SpartChronoS_AbilityId) * SpartChronoS_ALI)
    local timer t = CreateTimer()
    local integer i = GetHandleId(t)
    
    call TimerStart(t, 0.03, true, function SpartChronoS_UnitsActions)
    call SaveUnitHandle(SpartChronoS_Hash, i, 0, u)
    call SaveUnitHandle(SpartChronoS_Hash, i, 1, Chrono)
    call SaveReal(SpartChronoS_Hash, i, 2, duration)
    
    set Chrono = null
    set u = null
    set t = null
endfunction

//===========================================================================
function InitTrig_SpartChronoS takes nothing returns nothing
    set gg_trg_SpartChronoS = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_SpartChronoS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_SpartChronoS, Condition( function SpartChronoS_Conditions ) )
    call TriggerAddAction( gg_trg_SpartChronoS, function SpartChronoS_Actions )
endfunction
 

Attachments

  • SpartChronoSphere.w3x
    19 KB · Views: 26
Last edited:
Level 20
Joined
Jul 14, 2011
Messages
3,213
Huh? I didn't test with more players, but I cast about 6 Chronos at the same time with the hero in the map a there was no crash.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
:O What a shame. I'm sorry. I must apologize. You're right, the map was crashing, thankfully i found the problem instantly: the SetUnitX and SetUnitY of the Chronosphere before it dies isn't a good method. If those x/y are outside the map bounds the map crashes. I just tested with 99999 instead of 9999999 and it doesn't crash. I'll fix that right away and update my previous post.

EDIT: Done, already corrected the main idea, description, script and map. Now I'm killing the Chronosphere 0.031 seconds before the timer reaches the final expiration, and I pause units only if the Chrono is alive and unit is within range, so, in the final tick the Chrono is dead, therefore the units gets unpased.

No crash this time :)
 
Hey guys, now that I have more experience with GUI, I made another attempt to trigger a chronosphere.
  • Chronosphere spell
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Chronosphere
    • Actions
      • If (iChrono Equal to 0) then do (Trigger - Turn on Chronosphere loop <gen>) else do (-------- 0 --------)
      • Set iChrono = (iChrono + 1)
      • Set uChronoC[iChrono] = (Triggering unit)
      • Set Temp_Point = (Target point of ability being cast)
      • Unit - Create 1 Chronosphere for Player 1 (Red) at Temp_Point facing Default building facing degrees
      • Custom script: call RemoveLocation(udg_Temp_Point)
      • Set uChronoE[iChrono] = (Last created unit)
      • Unit - Add a 6.00 second Generic expiration timer to uChronoE[iChrono]
  • Chronosphere loop
    • Events
      • Time - Every 0.04 seconds of game time
    • Conditions
    • Actions
      • For each (Integer Temp_Int) from 1 to iChrono, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (uChronoE[Temp_Int] is dead) Equal to False
            • Then - Actions
              • Set Temp_Point = (Position of uChronoE[Temp_Int])
              • Set gChrono[Temp_Int] = (Units within 400.00 of Temp_Point matching (((Unit-type of (Matching unit)) Not equal to Chronosphere) or ((Matching unit) Not equal to uChronoC[Temp_Int])))
              • Custom script: call RemoveLocation(udg_Temp_Point)
              • Unit Group - Add all units of gChrono[Temp_Int] to gPaused
              • Custom script: call DestroyGroup(udg_gChrono[udg_Temp_Int])
            • Else - Actions
              • Set uChronoC[Temp_Int] = uChronoC[iChrono]
              • Set uChronoC[iChrono] = No unit
              • Set uChronoE[Temp_Int] = uChronoE[iChrono]
              • Set uChronoE[iChrono] = No unit
              • Set iChrono = (iChrono - 1)
              • Set Temp_Int = (Temp_Int - 1)
              • If (iChrono Equal to 0) then do (Trigger - Turn off (This trigger)) else do (-------- 0 --------)
      • Set Temp_Group = (Units in (Playable map area))
      • Unit Group - Pick every unit in Temp_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 gPaused) Equal to True
            • Then - Actions
              • Unit - Pause Temp_Unit
            • Else - Actions
              • Unit - Unpause Temp_Unit
      • Custom script: call DestroyGroup(udg_Temp_Group)
      • Custom script: call DestroyGroup(udg_gPaused)
For some reason they still don't get paused. I checked if they are added to gPAused by killing tehm and they dies, but in the 'pick every unit in Temp_Group' they don't get paused. Can you help please?

And what do you think about the method? is it even better than the jass version or would you recommand me to use the jass one instead?
 
Last edited:
Status
Not open for further replies.
Top