- Joined
- May 4, 2007
- Messages
- 2,260
Hi guys, I need a creep system for my project and so I decided to look here for one. However I feel bad because there is only 1 which is old and outdated so I decided to create my own system.
What is a CreepSpot System?
- Well, a creep spot is a spot with creeps. When the creeps die, you can use my system to revive them after X seconds in a periodic cycle, it is a respawn creep system.
Why use my system?
1 - Create CreepSpots with only 1 line of code! After that you can forget about them, the system will make all the job for you.
2 - Works for all kinds of units from all kinds of players.
3 - When creating the creeps their facing degree is the same.
4 - The initial position of the creeps is always the same as well
5 - The system will prevent the respawn of creeps if nearby units are near and you can change this condition very easily.
6 - Unlike Dota this system won't bug at all! With my system this movie would never happen:
YouTube - DotA jungling tricks
Meaning? As long as 1 unit of the group remains alive, there will be no respawn.
7 - You can customize your creep spawns to many levels, including the refresh rate, and the verification range.
8 - You can create effects when the creeps are created, this eye-candy feature is also very easy to customize.
This system requires TimerUtils.
So far this is what I have. I tested it and I don't think it bugs under any occasion, so I feel confident enough to say that this system is quite stable, however is what I call "static" respawn system. What does this mean? Well, it basically means that you can't change the types and numbers of units that spawn under a creep spot.
History:
Version 1.0:
- Initial release to the foruns to ask for oppinions and suggestions.
Version 1.1 and 1.2:
- Fixed and improved a few sections of the code and added new functionalities.
Version 1.3:
- Greatly improved the efficiency of the code and now it is a lot easier to understand.
- Replace groups with arrays that now keep all needed information about the units.
- Now when teh creeps spawn there can be effects for eye candy purposes.
- Added and fixed other stuff.
Version 1.4:
- Added change log to keep track of changes.
- Added a debug message that lets the user know if something is not well configured.
- Added GUI example and improved the test map.
Version 1.5:
- Added new functionalities to the system and changed its name, it is no longer static.
Version 1.51:
- Added a new functionality, "getCreepGroup".
- Fixed a bug with the restartSpawnTimer method.
- Added Element of Water to the credits.
- Fixed a bug with addUnit method, now it works properly.
- Added a new functionality, "removeUnit".
- Added Documentation that explains the system.
Version 1.6:
- Added a new method addGroup.
- Added a new method removeGroup.
- Added a new method killAll.
- Added a new method setUnitPosition.
- Improved the documentation.
- Change the name of the system, the structure is no longer public. Now newbies will
find it easier to use the system.
Version 1.7:
- Added new method addNum.
- Added new method removeNum.
- Changed the name of the constructor to createFromRect.
- Added a new constructor called createFromGroup.
- Improved the AddUnit method, now when a unit is created it also plays the effect.
- Improved the documentation, special thx to "Water Elemental".
- Improved the system so now it doesnt use the bj_lastCreatedUnit variable.
- Added setRefresh method.
- Added setRange method.
How to use? Well, using this system can't get any easier, you only need 1 line and all the job is done.
If you are lazy and don't want the hassle of reading all my system or importing the map, here is the documentation:
This "CreepSpot" system is a system designed to allow map makers to create creep
respawn regions as easily and in the most userfriendly way possible, requiring very
little effort. This system is based on the notion of an object and its use is quite
similar to the use of an object in Java, allowing you to create a variable for each
CreepSpot which you can modify very easily using the methods below. The system has
many methods and it is advisable to know each one of them so you can use the system
in the best possible way:
static method createFromRect takes rect place, real rate, real range,
string bornEff returns CreepSpot
This method creates a CreepSpot variable from an already created rect in the map.
It simply saves all units inside the rect and after that it will spawn them as a group
of creeps in a periodic fashion. For more information see the sample trigger.
static method createFromGroup takes group g, real rate, real range,
string bornEff returns CreepSpot
This is another create method. It creates a CreepSpot variable from an already
created group of units. Note that the units MUST ALREADY BE PLACED ON THE MAP before
you can call this method in a safe and sane way. This method allows the creation of
dynamic CreepSpots anywhere at anytime during the game and will also respawn
the creeps of the group according to their original positions and angles periodicaly.
method onDestroy takes nothing returns nothing
Well, I dont know if this will be useful, but it is a good idea to have it.
If you no longer want the CreepSpot alive, just destroy it to release resources.
method addUnit takes player owner, integer unitId, real unitX, real unitY,
real unitFace returns unit
This method allows you to add a single unit to the creepSpot. This can be
useful if you want to increase the number of creeps with time or depending on some
other event.
method removeUnit takes unit who returns nothing
As well as there is a method to add units, it makes sense to create one to remove
them. This method removes a unit from the CreepSpot group. It kills the unit and does
not show its death animation, just like removing it. A removed unit will not spawn
again, unless it is added again.
method getCreepGroup takes nothing returns group
This method returns a group with all the units of a creep spot. This is usefull,
you can use this to select all creeps of the group and then order them to do something or
if you want, or to add/remove something for them. Just use your imagination.
method pauseSpawnTimer takes nothing returns nothing
method restartSpawnTimer takes nothing returns nothing
These methods pause or re-start the timer that controls the spawns. This
functionality can be usefull if for some reason you want to make a pause.
method addGroup takes group g returns group
This method adds a group of units to the creepSpot. Please note that the units
'must already be created and placed on the map', else bugs will occur. There is no way
for me to check if a unit has a valid X or Y, so the user must be careful with this
functionality. This method returns a group with all units of the creepSpot, after the
addition is complete.
method removeGroup takes group g returns group
If we can add groups of units, than we should also be able to remove groups of
units. This method removes units in a group from the creepSpot and returns a group
with the remaining units.
method killAll takes nothing returns nothing
Simply kills all creeps of a CreepSpot =P Just wanted to add this for fun lol.
method setUnitPosition takes unit who, real newX, real newY, real newFacing
returns nothing
This method changes the position of a unit in the creepSpot.
method addNum takes integer num, player owner, integer unitIds, boolean randomPos
returns nothing
This method adds a number of units with the same id to a creep spot and immediatly
spawns them.
method removeNum takes integer num, integer unitIds returns nothing
This method removes a number of units with the same id from a creep spot. The
units are simply removed and wont spawn again. The units are removed in a random way.
method setRefresh takes real newVal returns nothing
method setRange takes real newVal returns nothing
This methods allow the user to change the range of already created CreepSpots.
Note that the modificated variables will not be applied immediatly, but only the next
spawn of the units. Meaning? Well basically it means that if you create a CreepSpot
with a certain value, say A and B, for range and rate, and after that you change the
values using this methods, that the timer will only start using the new values after
the first spawn.
Ok guys, I am posting this here for suggestions and bug reports. If you think there is something I should improve, go ahead and make a post.
What is a CreepSpot System?
- Well, a creep spot is a spot with creeps. When the creeps die, you can use my system to revive them after X seconds in a periodic cycle, it is a respawn creep system.
Why use my system?
1 - Create CreepSpots with only 1 line of code! After that you can forget about them, the system will make all the job for you.
2 - Works for all kinds of units from all kinds of players.
3 - When creating the creeps their facing degree is the same.
4 - The initial position of the creeps is always the same as well
5 - The system will prevent the respawn of creeps if nearby units are near and you can change this condition very easily.
6 - Unlike Dota this system won't bug at all! With my system this movie would never happen:
YouTube - DotA jungling tricks
Meaning? As long as 1 unit of the group remains alive, there will be no respawn.
7 - You can customize your creep spawns to many levels, including the refresh rate, and the verification range.
8 - You can create effects when the creeps are created, this eye-candy feature is also very easy to customize.
This system requires TimerUtils.
So far this is what I have. I tested it and I don't think it bugs under any occasion, so I feel confident enough to say that this system is quite stable, however is what I call "static" respawn system. What does this mean? Well, it basically means that you can't change the types and numbers of units that spawn under a creep spot.
History:
Version 1.0:
- Initial release to the foruns to ask for oppinions and suggestions.
Version 1.1 and 1.2:
- Fixed and improved a few sections of the code and added new functionalities.
Version 1.3:
- Greatly improved the efficiency of the code and now it is a lot easier to understand.
- Replace groups with arrays that now keep all needed information about the units.
- Now when teh creeps spawn there can be effects for eye candy purposes.
- Added and fixed other stuff.
Version 1.4:
- Added change log to keep track of changes.
- Added a debug message that lets the user know if something is not well configured.
- Added GUI example and improved the test map.
Version 1.5:
- Added new functionalities to the system and changed its name, it is no longer static.
Version 1.51:
- Added a new functionality, "getCreepGroup".
- Fixed a bug with the restartSpawnTimer method.
- Added Element of Water to the credits.
- Fixed a bug with addUnit method, now it works properly.
- Added a new functionality, "removeUnit".
- Added Documentation that explains the system.
Version 1.6:
- Added a new method addGroup.
- Added a new method removeGroup.
- Added a new method killAll.
- Added a new method setUnitPosition.
- Improved the documentation.
- Change the name of the system, the structure is no longer public. Now newbies will
find it easier to use the system.
Version 1.7:
- Added new method addNum.
- Added new method removeNum.
- Changed the name of the constructor to createFromRect.
- Added a new constructor called createFromGroup.
- Improved the AddUnit method, now when a unit is created it also plays the effect.
- Improved the documentation, special thx to "Water Elemental".
- Improved the system so now it doesnt use the bj_lastCreatedUnit variable.
- Added setRefresh method.
- Added setRange method.
How to use? Well, using this system can't get any easier, you only need 1 line and all the job is done.
If you are lazy and don't want the hassle of reading all my system or importing the map, here is the documentation:
This "CreepSpot" system is a system designed to allow map makers to create creep
respawn regions as easily and in the most userfriendly way possible, requiring very
little effort. This system is based on the notion of an object and its use is quite
similar to the use of an object in Java, allowing you to create a variable for each
CreepSpot which you can modify very easily using the methods below. The system has
many methods and it is advisable to know each one of them so you can use the system
in the best possible way:
static method createFromRect takes rect place, real rate, real range,
string bornEff returns CreepSpot
This method creates a CreepSpot variable from an already created rect in the map.
It simply saves all units inside the rect and after that it will spawn them as a group
of creeps in a periodic fashion. For more information see the sample trigger.
static method createFromGroup takes group g, real rate, real range,
string bornEff returns CreepSpot
This is another create method. It creates a CreepSpot variable from an already
created group of units. Note that the units MUST ALREADY BE PLACED ON THE MAP before
you can call this method in a safe and sane way. This method allows the creation of
dynamic CreepSpots anywhere at anytime during the game and will also respawn
the creeps of the group according to their original positions and angles periodicaly.
method onDestroy takes nothing returns nothing
Well, I dont know if this will be useful, but it is a good idea to have it.
If you no longer want the CreepSpot alive, just destroy it to release resources.
method addUnit takes player owner, integer unitId, real unitX, real unitY,
real unitFace returns unit
This method allows you to add a single unit to the creepSpot. This can be
useful if you want to increase the number of creeps with time or depending on some
other event.
method removeUnit takes unit who returns nothing
As well as there is a method to add units, it makes sense to create one to remove
them. This method removes a unit from the CreepSpot group. It kills the unit and does
not show its death animation, just like removing it. A removed unit will not spawn
again, unless it is added again.
method getCreepGroup takes nothing returns group
This method returns a group with all the units of a creep spot. This is usefull,
you can use this to select all creeps of the group and then order them to do something or
if you want, or to add/remove something for them. Just use your imagination.
method pauseSpawnTimer takes nothing returns nothing
method restartSpawnTimer takes nothing returns nothing
These methods pause or re-start the timer that controls the spawns. This
functionality can be usefull if for some reason you want to make a pause.
method addGroup takes group g returns group
This method adds a group of units to the creepSpot. Please note that the units
'must already be created and placed on the map', else bugs will occur. There is no way
for me to check if a unit has a valid X or Y, so the user must be careful with this
functionality. This method returns a group with all units of the creepSpot, after the
addition is complete.
method removeGroup takes group g returns group
If we can add groups of units, than we should also be able to remove groups of
units. This method removes units in a group from the creepSpot and returns a group
with the remaining units.
method killAll takes nothing returns nothing
Simply kills all creeps of a CreepSpot =P Just wanted to add this for fun lol.
method setUnitPosition takes unit who, real newX, real newY, real newFacing
returns nothing
This method changes the position of a unit in the creepSpot.
method addNum takes integer num, player owner, integer unitIds, boolean randomPos
returns nothing
This method adds a number of units with the same id to a creep spot and immediatly
spawns them.
method removeNum takes integer num, integer unitIds returns nothing
This method removes a number of units with the same id from a creep spot. The
units are simply removed and wont spawn again. The units are removed in a random way.
method setRefresh takes real newVal returns nothing
method setRange takes real newVal returns nothing
This methods allow the user to change the range of already created CreepSpots.
Note that the modificated variables will not be applied immediatly, but only the next
spawn of the units. Meaning? Well basically it means that if you create a CreepSpot
with a certain value, say A and B, for range and rate, and after that you change the
values using this methods, that the timer will only start using the new values after
the first spawn.
JASS:
//===========================================================================
//A system that allows the user to have creep spots in the easier possible
//way using only 1 line.
//
//Requires TimerUtils
//
//@author Flame_Phoenix
//
//@credits
//- Deaod, for helping me with a detail
//- Element of Water, for many ideas and suggestions
//
//@version 1.7
//===========================================================================
library CreepSys initializer Init requires TimerUtils
//===========================================================================
//=============================SETUP START===================================
//===========================================================================
globals
private constant real VERIFY = 5. //if the creep spot has intruders preventing the spawn of the creeps, we make a check every 5. secs
private constant integer MAX_UNITS_NUMBER = 5 //the maximum amount of units a creep spot can have
endglobals
private function ValidUnit takes unit who returns boolean
//Here we select the units that will PREVENT the spawning of our creeps.
//In this case, if a unit which owner is not a passive player is inside the
//range of the CreepSpot, than the creeps will NOT re-spawn again.
return GetWidgetLife(who) > 0.405 and GetOwningPlayer(who) != Player(PLAYER_NEUTRAL_PASSIVE)
endfunction
//===========================================================================
//=============================SETUP END=====================================
//===========================================================================
globals
private group checkGroup
private boolexpr checkConds
private group initGroup
endglobals
//===========================================================================
private function RangeConds takes nothing returns boolean
return ValidUnit(GetFilterUnit())
endfunction
//===========================================================================
struct CreepSpot
rect spawnPlace
real refresh
real checkRange
timer t
real array spawnX[MAX_UNITS_NUMBER]
real array spawnY[MAX_UNITS_NUMBER]
real array facing[MAX_UNITS_NUMBER]
unit array units[MAX_UNITS_NUMBER]
integer creepNum
string bornEffect
//recursive method
static method SpawnUnits takes nothing returns nothing
local CreepSpot data = CreepSpot(GetTimerData(GetExpiredTimer()))
local integer i
local integer alive = data.creepNum
local unit created
call PauseTimer(data.t)
//here we update the number of creeps belonging to the creep spot that
//are alive
set i = 0
loop
exitwhen(i == data.creepNum)
if GetWidgetLife(data.units[i]) < 0.405 then
set alive = alive - 1
endif
set i = i + 1
endloop
call GroupEnumUnitsInRange(checkGroup, GetRectCenterX(data.spawnPlace), GetRectCenterY(data.spawnPlace), data.checkRange, checkConds)
if CountUnitsInGroup(checkGroup) == 0 and alive == 0 then
call GroupClear(checkGroup)
//in this loop I create the new spawn which is exactly like the one
//before it
set i = 0
loop
exitwhen(i == data.creepNum)
set created = CreateUnit(GetOwningPlayer(data.units[i]), GetUnitTypeId(data.units[i]), data.spawnX[i], data.spawnY[i], data.facing[i])
set data.units[i] = created
call DestroyEffect(AddSpecialEffectTarget(data.bornEffect, data.units[i], "origin"))
set i = i + 1
endloop
//start the timer!
call SetTimerData(data.t, integer(data))
call TimerStart(data.t, data.refresh, true, function CreepSpot.SpawnUnits)
else
call GroupClear(checkGroup)
//wait VERIFY secs
call SetTimerData(data.t, integer(data))
call TimerStart(data.t, VERIFY, true, function CreepSpot.SpawnUnits)
endif
endmethod
method setRefresh takes real newVal returns nothing
set .refresh = newVal
endmethod
method setRange takes real newVal returns nothing
set .checkRange = newVal
endmethod
method setUnitPosition takes unit who, real newX, real newY, real newFacing returns nothing
local integer i = 0
loop
exitwhen(i == .creepNum)
if .units[i] == who then
set .spawnX[i] = newX
set .spawnY[i] = newY
set .facing[i] = newFacing
endif
set i = i + 1
endloop
endmethod
//pauses the timer that spawns the units
method pauseSpawnTimer takes nothing returns nothing
call PauseTimer(.t)
endmethod
//restarts the timer that spawns the units
method restartSpawnTimer takes nothing returns nothing
call TimerStart(.t, .refresh, true, function CreepSpot.SpawnUnits)
endmethod
//returns a group with the units of the CreepSpot
method getCreepGroup takes nothing returns group
local group ret = CreateGroup()
local integer i = 0
loop
exitwhen(i == .creepNum)
call GroupAddUnit(ret, .units[i])
set i = i + 1
endloop
return ret
endmethod
//removes a unit from the group
method removeUnit takes unit who returns nothing
local integer i = 0
local integer k
loop
exitwhen(i == .creepNum)
if .units[i] == who then
//here we kill the unit without people seeing it
call ShowUnit(.units[i], false)
call KillUnit(.units[i])
//now to remove it from the array...
//we move all indexes after this unit 1 spot behind
set k = i
loop
exitwhen(k == .creepNum)
set .units[k] = .units[i + 1]
set .spawnX[k] = .spawnX[i + 1]
set .spawnY[k] = .spawnY[i + 1]
set .facing[k] = .facing[i + 1]
set k = k + 1
endloop
endif
set i = i + 1
endloop
//we have -1 unit now
set .creepNum = .creepNum - 1
endmethod
//adds a unit to the CreepSpot
method addUnit takes player owner, integer unitId, real unitX, real unitY, real unitFace returns unit
//increase the counter
set .creepNum = .creepNum + 1
//safety check
if .creepNum > MAX_UNITS_NUMBER then
call BJDebugMsg("The addUnit call has passed the MAX_UNITS_NUMBER variable. Update this variable to accomodate the changes.")
endif
//add the unit to the last position of the array
set .spawnX[.creepNum-1] = unitX
set .spawnY[.creepNum-1] = unitY
set .facing[.creepNum-1] = unitFace
set .units[.creepNum-1] = CreateUnit(owner, unitId, unitX, unitY, unitFace)
call DestroyEffect(AddSpecialEffectTarget(.bornEffect, .units[.creepNum-1], "origin"))
return .units[.creepNum-1]
endmethod
method removeNum takes integer num, integer unitIds returns nothing
local integer i = 0
local integer k = 0
if (.creepNum - num < 0) then
call BJDebugMsg("The removeNum call failed, you are removing too many untis.")
endif
loop
exitwhen(i == .creepNum)
if GetUnitTypeId(.units[i]) == unitIds and k <= num then
call .removeUnit(.units[i])
set k = k + 1
endif
set i = i + 1
endloop
endmethod
method addNum takes integer num, player owner, integer unitIds, boolean randomPos returns nothing
local integer i = 0
if (.creepNum + num > MAX_UNITS_NUMBER) then
call BJDebugMsg("The addNum call has passed the MAX_UNITS_NUMBER variable. Update this variable to accomodate the changes.")
endif
loop
exitwhen(i == num)
if randomPos then
call .addUnit(owner, unitIds, GetRandomReal(GetRectMinX(.spawnPlace), GetRectMaxX(.spawnPlace)), GetRandomReal(GetRectMinY(.spawnPlace), GetRectMaxY(.spawnPlace)), 0.)
else
call .addUnit(owner, unitIds, GetRectCenterX(.spawnPlace), GetRectCenterY(.spawnPlace), 0.)
endif
set i = i + 1
endloop
endmethod
method killAll takes nothing returns nothing
local integer i = 0
loop
exitwhen(i == .creepNum)
call KillUnit(.units[i])
set i = i + 1
endloop
endmethod
method removeGroup takes group g returns group
local unit f
local group ret = CreateGroup()
local integer i = 0
//here we remove the units of this group from the creepSpot
loop
set f = FirstOfGroup(g)
exitwhen(f == null)
call GroupRemoveUnit(g, f)
call .removeUnit(f)
endloop
//here we add all units of the creepSpot to the
//group ret
loop
exitwhen(i == .creepNum)
call GroupAddUnit(ret, .units[i])
set i = i + 1
endloop
//now we return the group with all units
return ret
endmethod
method addGroup takes group g returns group
local unit f
local group ret = CreateGroup()
local integer i = 0
if .creepNum + CountUnitsInGroup(g) > MAX_UNITS_NUMBER then
call BJDebugMsg("Cannot add group to CreepSpot, it passes the maximum number of units allowed.")
endif
//here we add all units of the creepSpot to the
//group ret
loop
exitwhen(i == .creepNum)
call GroupAddUnit(ret, .units[i])
set i = i + 1
endloop
//here we remove units from group g and add them to the array and
//to the return group
loop
set f = FirstOfGroup(g)
exitwhen(f == null)
call GroupRemoveUnit(g, f)
call .addUnit(GetOwningPlayer(f), GetUnitTypeId(f), GetUnitX(f), GetUnitY(f), GetUnitFacing(f))
call GroupAddUnit(ret, f)
endloop
//now we return the group with all units
return ret
endmethod
static method createFromGroup takes group g, real rate, real range, string bornEff returns CreepSpot
local CreepSpot data = CreepSpot.allocate()
local integer i = 0
local unit f
local real maxX
local real minX
local real maxY
local real minY
//setting our members
set data.refresh = rate
set data.checkRange = range
set data.bornEffect = bornEff
set data.creepNum = CountUnitsInGroup(g)
//now we save information about the units
loop
set f = FirstOfGroup(g)
exitwhen(f == null)
call GroupRemoveUnit(g, f)
set data.units[i] = f
set data.spawnX[i] = GetUnitX(f)
set data.spawnY[i] = GetUnitY(f)
set data.facing[i] = GetUnitFacing(f)
set i = i + 1
endloop
//now we search for the X and Y values to create our rect
set i = 0
set maxX = data.spawnX[i]
set minX = data.spawnX[i]
set maxY = data.spawnY[i]
set minY = data.spawnY[i]
loop
exitwhen(i == data.creepNum)
if maxX < data.spawnX[i] then
set maxX = data.spawnX[i]
endif
if minX > data.spawnX[i] then
set minX = data.spawnX[i]
endif
if maxY < data.spawnY[i] then
set maxY = data.spawnY[i]
endif
if minY > data.spawnY[i] then
set minY = data.spawnY[i]
endif
set i = i + 1
endloop
//and now create the rect!
set data.spawnPlace = Rect(minX, minY, maxX, maxY)
//now we start the timer and make everything run!
set data.t = NewTimer()
//start the timer!
call SetTimerData(data.t, integer(data))
call TimerStart(data.t, data.refresh, true, function CreepSpot.SpawnUnits)
return data
endmethod
static method createFromRect takes rect place, real rate, real range, string bornEff returns CreepSpot
local CreepSpot data = CreepSpot.allocate()
local integer i = 0
local unit f
//setting our members
set data.spawnPlace = place
set data.refresh = rate
set data.checkRange = range
set data.bornEffect = bornEff
set data.t = NewTimer()
//adding the creeps in the region to teh group
call GroupEnumUnitsInRect(initGroup, data.spawnPlace, null)
set data.creepNum = CountUnitsInGroup(initGroup)
if data.creepNum > MAX_UNITS_NUMBER then
call BJDebugMsg("Please update the MAX_UNITS_NUMBER variable, there is a creep spot with more units than it should.")
endif
//now we add the units to the array so we can keep track of their data
loop
set f = FirstOfGroup(initGroup)
exitwhen(i == data.creepNum)
call GroupRemoveUnit(initGroup, f)
set data.units[i] = f
set data.spawnX[i] = GetUnitX(f)
set data.spawnY[i] = GetUnitY(f)
set data.facing[i] = GetUnitFacing(f)
set i = i + 1
endloop
//start the timer!
call SetTimerData(data.t, integer(data))
call TimerStart(data.t, data.refresh, true, function CreepSpot.SpawnUnits)
return data
endmethod
method onDestroy takes nothing returns nothing
local integer i = 0
//killing the creeps
loop
exitwhen(i == .creepNum)
call KillUnit(.units[i])
set .units[i] = null
set i = i + 1
endloop
//fixing other stuff
call ReleaseTimer(.t)
endmethod
endstruct
//===========================================================================
private function Init takes nothing returns nothing
//setting our globals
set checkConds = Condition(function RangeConds)
set checkGroup = CreateGroup()
set initGroup = CreateGroup()
endfunction
endlibrary
Ok guys, I am posting this here for suggestions and bug reports. If you think there is something I should improve, go ahead and make a post.
Attachments
Last edited: