Anachron
New Member
- Reaction score
- 53
(Yes, I am that Anachron from Hiveworkshop.com)
Anachrons Move System
Example
Anachrons Spawns System
Spawn System:
Example
Anachrons Move System
JASS:
//WayPoint:
public static method create takes real bX, real bY, real tX, real tY, real tR returns WayPoint
public method moveUnit takes unit u returns nothing
//Way:
public static method create takes nothing returns thistype
private static method addWay takes thistype wy returns nothing
private static method removeWay takes thistype wy returns nothing
public method addWayPoint takes WayPoint wp returns nothing
public method removeWayPoint takes WayPoint wp returns nothing
public method addUnit takes unit u, integer curPos returns nothing
public method removeUnit takes unit u returns nothing
public method moveUnit takes unit u, integer curPos returns nothing
public method moveNext takes unit u, integer curPos returns nothing
public method getNearestWP takes unit u returns integer
JASS:
//:******************************************************************************
//: Anachrons Move System
//: by dhk_undead_lord / aka Anachron
//: version 1.05
//:
//:
//: ABOUT:
//: This system has been thought to be able to easily
//: create and manage spawn ways of troops.
//: Top priority is the automatic movement control,
//: such as high customizeability for users.
//:
//: WHAT YOU NEED:
//: You need JassNewGenPack to use this vJASS system.
//: (Download it here: <a href="http://www.wc3c.net/showthread.php?goto=newpost&t=90999" target="_blank" class="link link--external" rel="nofollow ugc noopener">http://www.wc3c.net/showthread.php?goto=newpost&t=90999</a>)
//:
//: STEPS TO IMPORT:
//: I.) Copy this code.
//: II.) Paste it into the head of your map.
//: (Therefor go to the Trigger Editor, select the mapname and paste
//: into the area on the right)
//: III.) Save your map!
//: (With File - Save Map (S) or control + S. DO NOT SAVE WITH SAVE AS!)
//: IV.) You got it! You imported the system.
//:
//: To make sure this system works, you should try a few tests!
//:
//: METHODS
//:
//: >WayPoint.create takes real baseX, real baseY, real targX, real targY, real targRadius
//: Constructor of WayPoints.
//:
//: >WayPoint.moveUnit takes unit u
//: Move any unit to the target of this waypoint!
//:
//: >Way.create takes boolean scCon, boolean stCon, boolean hdCon returns Way
//: Create a new Way, say whether orders should recast attack/move or not.
//:
//: >Way.addWayPoint takes WayPoint wp returns nothing
//: Add a waypoint to the system! Horray, another patrol point.
//:
//: >Way.addUnit takes unit u returns nothing
//: Adds an unit to the way. Automaticly moves to the first waypoint.
//:
//: >Way.removeUnit takes unit u returns nothing
//: Remove a unit from the way system.
//:
//: >Way.moveUnit takes unit u, integer curPos returns nothing
//: Move the unit u to the waypoint curPos's position
//:
//: >Way.moveNext takes unit u, integer curPos returns nothing
//: Sets the new wayPoint for the unit u
//:
//: >Way.getNearestWP takes unit u returns integer
//: A very nice function to find the nearest waypoint of an unit.
//: Is perfect for Revive spells were you need to reregister,
//: because with this function its pretty easy to get the correct waypoint.
//:
//: Thanks for downloading and using my system!
//:
//: Please don't forget to give credits to me (dhk_undead_lord / Aka Anachron)
//:
//:******************************************************************************
library AnaMoveSys initializer init
//==========================================================================
// %CUSTOMIZATION AREA%: Feel free to change anything to what you need!
//==========================================================================
globals
//: %Default Values%
//: Basicly the radius the unit has to be to
//: get ordered to the next waypoint.
private constant real TARGET_TOLERANCE = 192.
//: Sets whether the unit should move again
//: after it casted a spell.
private constant boolean SPELLCAST_CONTINUE = true
//: Sets whether the unit should move again
//: after it used stop command.
private constant boolean STOP_CONTINUE = true
//: Sets whether the unit should move again
//: after it used the hold position command.
private constant boolean HOLDPOSITION_CONTINUE = false
//: Sets whether death units will automaticly
//: removed by the system.
//: WARNING: THIS IS HIGLY RECOMMENDED!
//: TO ADD UNITS (LIKE REVIVE) USE THE addUnit()
//: METHOD!
private constant boolean DEATH_REMOVES = true
//: %Hashtable Storage%
//: Sets which key is for the unit ID
private constant integer KEY_UNIT = 0
//: Sets which key is for the way ID
private constant integer KEY_WAY = 1
//: Sets which key is for the current
//: waypoint ID.
private constant integer KEY_CURPOS = 2
//: %Order Ids%
private constant string ORDER_STOP = "stop"
private constant string ORDER_HOLDPOSITION = "position"
private constant string ORDER_ATTACKMOVE = "attack"
//: %Timers%
private constant timer MOVE_TIMER = CreateTimer()
private constant real MOVE_INT = 0.75
//: %Saving%
private hashtable UNIT_DATA = InitHashtable()
private group MOVING_UNITS = CreateGroup()
endglobals
//: %Conditions of reordering the units
//: Here you can define the conditions,
//: such as owner controlling and other
//: useful filters.
public function globalCheck takes nothing returns boolean
return LoadWidgetHandle(UNIT_DATA, GetHandleId(GetTriggerUnit()), KEY_UNIT) != null
endfunction
public function checkSpellcast takes nothing returns boolean
return globalCheck()
endfunction
public function checkStopOrder takes nothing returns boolean
return globalCheck() and GetIssuedOrderId() == OrderId(ORDER_STOP)
endfunction
public function checkHoldOrder takes nothing returns boolean
return globalCheck() and GetIssuedOrderId() == OrderId(ORDER_HOLDPOSITION)
endfunction
//==========================================================================
//: %DO NOT CHANGE THIS UNLIKE YOU KNOW WHAT YOU ARE DOING%
//==========================================================================
public function reOrderUnit takes nothing returns nothing
local integer unitID = 0
local integer wayID = 0
local integer curPos = 0
if IsUnitInGroup(GetTriggerUnit(), MOVING_UNITS) then
set unitID = GetHandleId(GetTriggerUnit())
set wayID = LoadInteger(UNIT_DATA, unitID, KEY_WAY)
set curPos = LoadInteger(UNIT_DATA, unitID, KEY_CURPOS)
debug call BJDebugMsg("!AoSMoveSys] |NOTICE| <Way[" + I2S(wayID) + "]> <Reorder unit " + I2S(unitID) + ">")
call Way.instances[wayID].moveUnit(GetTriggerUnit(), curPos)
endif
endfunction
public function checkUnregister takes nothing returns boolean
return GetOwningPlayer(GetTriggerUnit()) == Player(0)
endfunction
public function unregisterUnit takes nothing returns nothing
local integer wayID = LoadInteger(UNIT_DATA, GetHandleId(GetTriggerUnit()), KEY_WAY)
call Way.instances[wayID].removeUnit(GetTriggerUnit())
endfunction
struct WayPoint
real baseX = 0.
real baseY = 0.
real targX = 0.
real targY = 0.
real targRadius = 0.
integer ID = 0
//: =================================
//: CREATE NEW INSTANCES
//: =================================
public static method create takes real bX, real bY, real tX, real tY, real tR returns WayPoint
local thistype wp = thistype.allocate()
set wp.baseX = bX
set wp.baseY = bY
set wp.targX = tX
set wp.targY = tY
set wp.targRadius = tR
return wp
endmethod
//: =================================
//: =================================
//: Move the unit to the target loc
//: =================================
public method moveUnit takes unit u returns nothing
call IssuePointOrder(u, ORDER_ATTACKMOVE, .targX, .targY)
endmethod
//: =================================
endstruct
struct Way
group units = CreateGroup()
integer ID = 0
static Way array instances[8191]
static integer index = 0
integer curwpID = 0
WayPoint array wayPoints[128]
//: Saves the triggers for the
//: auto remove functions.
//: -> spellcast?
static trigger scTrig = CreateTrigger()
//: -> stop?
static trigger stTrig = CreateTrigger()
//: -> hold position?
static trigger hpTrig = CreateTrigger()
//: This unregisters unit which die
static trigger deathTrig = CreateTrigger()
//: =================================
//: CREATE NEW INSTANCES
//: =================================
public static method create takes nothing returns thistype
local thistype wy = thistype.allocate()
call thistype.addWay(wy)
return wy
endmethod
//: =================================
//: =================================
//: Add and remove ways to the system
//: =================================
private static method addWay takes thistype wy returns nothing
set wy.ID = thistype.index
set thistype.instances[thistype.index] = wy
set thistype.index = thistype.index + 1
endmethod
private static method removeWay takes thistype wy returns nothing
set thistype.instances[wy.ID] = thistype.instances[thistype.index]
set thistype.index = thistype.index - 1
endmethod
//: =================================
//: ====================================
//: Add and remove Way Point to the way
//: ====================================
public method addWayPoint takes WayPoint wp returns nothing
set wp.ID = .curwpID
set .wayPoints[.curwpID] = wp
set .curwpID = .curwpID + 1
endmethod
public method removeWayPoint takes WayPoint wp returns nothing
set .wayPoints[wp.ID] = .wayPoints[.curwpID]
set .curwpID = .curwpID - 1
endmethod
//: ====================================
//: ====================================
//: Add and remove units to the way
//: ====================================
public method addUnit takes unit u, integer curPos returns nothing
if not(IsUnitInGroup(u, .units)) then
call SaveWidgetHandle(UNIT_DATA, GetHandleId(u), KEY_UNIT, u)
call SaveInteger(UNIT_DATA, GetHandleId(u), KEY_WAY, .ID)
call SaveInteger(UNIT_DATA, GetHandleId(u), KEY_CURPOS, curPos)
call GroupAddUnit(.units, u)
call GroupAddUnit(MOVING_UNITS, u)
call .moveUnit(u, curPos)
else
debug call BJDebugMsg("!AoSMoveSys] |ERROR| <Way[" + I2S(.ID) + "]> <addUnit: UNIT ALREADY REGISTERED!>")
endif
endmethod
public method removeUnit takes unit u returns nothing
call FlushChildHashtable(UNIT_DATA, GetHandleId(u))
call GroupRemoveUnit(.units, u)
call GroupRemoveUnit(MOVING_UNITS, u)
debug call BJDebugMsg("!AoSMoveSys] |NOTICE| <Way[" + I2S(.ID) + "]> <removeUnit: UNIT HAS BEEN REMOVED!>")
endmethod
//: ====================================
//: ====================================
//: Move an unit to the target
//: ====================================
public method moveUnit takes unit u, integer curPos returns nothing
call .wayPoints[curPos].moveUnit(u)
endmethod
public method moveNext takes unit u, integer curPos returns nothing
set curPos = curPos + 1
if curPos < .curwpID then
//: %Save data and move unit%
call SaveInteger(UNIT_DATA, GetHandleId(u), KEY_CURPOS, curPos)
call .moveUnit(u, curPos)
else
call .removeUnit(u)
endif
endmethod
//: ====================================
//: ====================================
//: Additional Methods for users
//: ====================================
public method getNearestWP takes unit u returns integer
local integer foundWP = -1
local WayPoint wp = 0
local integer i = 0
local real tmpDist = 0.
//: !Do NOT change this
local real dist = 100000000.
loop
exitwhen i >= .curwpID
// %Compare the distances%
set tmpDist = SquareRoot(GetUnitX(u) * wp.targX + GetUnitY(u) * wp.targY)
if tmpDist <= dist then
set foundWP = i
set dist = tmpDist
endif
set i = i + 1
endloop
return foundWP
endmethod
//: ====================================
//: ====================================
//: Desctrutor Method
//: ====================================
private method onDestroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= .curwpID
call .wayPoints<i>.destroy()
set i = i + 1
endloop
call thistype.removeWay(this)
endmethod
//: ====================================
endstruct
private struct MoveOrders
//: =================================
//: CHECK ALL WAYS FOR SPAWNING
//: =================================
static method checkWays takes nothing returns nothing
local Way wy = 0
local WayPoint wp = 0
local integer i = 0
local unit u = null
local group g = CreateGroup()
local integer unitID = 0
local integer wpID = 0
local real dx = 0.
local real dy = 0.
local real dist = 0.
loop
exitwhen i >= Way.index
//----------------
//: %Reset Data%
//----------------
set u = null
call GroupClear(g)
set wy = 0
set wp = 0
set unitID = 0
//----------------
set wy = Way.instances<i>
call GroupAddGroup(wy.units, g)
loop
set u = FirstOfGroup(g)
exitwhen u == null
//-----------------------
// %Get unit data%
//-----------------------
set unitID = GetHandleId(u)
set wpID = LoadInteger(UNIT_DATA, unitID, KEY_CURPOS)
set wp = wy.wayPoints[wpID]
//: Check whether the unit is in the range of
//: her checkpoint
set dx = GetUnitX(u) - wp.targX
set dy = GetUnitY(u) - wp.targY
set dist = SquareRoot(dx * dx + dy * dy)
if dist <= wp.targRadius then
call wy.moveNext(u, wpID)
debug call BJDebugMsg("!AoSMoveSys] |NOTICE| <Way[" + I2S(wy.ID) + "]> <Unit " + I2S(GetHandleId(u)) + " reached target>")
endif
call GroupRemoveUnit(g, u)
endloop
set i = i + 1
endloop
call GroupClear(g)
set u = null
set g = null
endmethod
//: =================================
endstruct
private function init takes nothing returns nothing
local integer i = 0
call TimerStart(MOVE_TIMER, MOVE_INT, true, function MoveOrders.checkWays)
if SPELLCAST_CONTINUE then
call TriggerAddAction(Way.scTrig, function reOrderUnit)
call TriggerAddCondition(Way.scTrig, Condition(function checkSpellcast))
set i = 0
loop
exitwhen i > 15
call TriggerRegisterPlayerUnitEvent(Way.scTrig, Player(i), EVENT_PLAYER_UNIT_SPELL_ENDCAST, null)
set i = i + 1
endloop
endif
if STOP_CONTINUE then
call TriggerAddAction(Way.stTrig, function reOrderUnit)
call TriggerAddCondition(Way.stTrig, Condition(function checkStopOrder))
set i = 0
loop
exitwhen i > 15
call TriggerRegisterPlayerUnitEvent(Way.scTrig, Player(i), EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
set i = i + 1
endloop
endif
if HOLDPOSITION_CONTINUE then
call TriggerAddAction(Way.hpTrig, function reOrderUnit)
call TriggerAddCondition(Way.hpTrig, Condition(function checkHoldOrder))
set i = 0
loop
exitwhen i > 15
call TriggerRegisterPlayerUnitEvent(Way.hpTrig, Player(i), EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
set i = i + 1
endloop
endif
if DEATH_REMOVES then
call TriggerAddAction(Way.deathTrig, function unregisterUnit)
call TriggerAddCondition(Way.deathTrig, Condition(function checkUnregister))
set i = 0
loop
exitwhen i > 15
call TriggerRegisterPlayerUnitEvent(Way.deathTrig, Player(i), EVENT_PLAYER_UNIT_DEATH, null)
set i = i + 1
endloop
endif
endfunction
endlibrary
</i></i>
Example
JASS:
scope example initializer init
private function init takes nothing returns nothing
local WayPoint wp = 0
local Way wy = 0
local unit u = CreateUnit(Player(0), 039;hmpr039;, 800., -1200., 270.)
call FogModifierStart(CreateFogModifierRect(Player(0), FOG_OF_WAR_VISIBLE, bj_mapInitialPlayableArea , false, false))
//: Instaciate a new way
set wy = Way.create()
//: Add a new waypoint
call wy.addWayPoint(WayPoint.create(800., -1200., -900., -1125., 192.))
call wy.addWayPoint(WayPoint.create(-900., -1125., -860., -110., 192.))
call wy.addWayPoint(WayPoint.create(-860., -110., 0., 0., 192.))
//: Add a unit to the way, starting at waypoint 0.
call wy.addUnit(u, 0)
endfunction
endscope
Anachrons Spawns System
Spawn System:
JASS:
//UnitSpawn:
public static method create takes integer unitId, integer amount, onUnitSpawn onUnitSp, string effPath returns UnitSpawn
public method spawn takes player p, real posX, real posY returns nothing
//GroupSpawn:
public static method create takes real baseX, real baseY, real d returns thistype
public method addUnitSpawn takes UnitSpawn us returns nothing
public method removeUnitSpawn takes UnitSpawn us returns nothing
public method spawnUnits takes player p returns nothing
//Wave:
public static method create takes real i, player own returns thistype
public method addGroupSpawn takes GroupSpawn gs returns nothing
public method removeGroupSpawn takes GroupSpawn gs returns nothing
public method spawnUnitGroup takes integer i returns nothing
//WaveCheck
public static method checkSpawn takes nothing returns nothing
public static method addWave takes Wave w, integer times returns nothing
public static method removeWave takes Wave w returns nothing
JASS:
//:******************************************************************************
//: Anachrons Spawn System
//: by dhk_undead_lord / aka Anachron
//: version 1.05
//: BETA
//:
//: ABOUT:
//: This system has been made for easily create
//: and manage grouped spawns such as in DotA or
//: AotZ. Could also be very useful in Tower Defenses,
//: TAG maps and/or all other map genres with interval
//: spawning, such as Enfo, Castle Defenses etc.
//:
//: WHAT YOU NEED:
//: You need JassNewGenPack to use this vJASS system.
//: (Download it here: <a href="http://www.wc3c.net/showthread.php?goto=newpost&t=90999" target="_blank" class="link link--external" rel="nofollow ugc noopener">http://www.wc3c.net/showthread.php?goto=newpost&t=90999</a>)
//:
//: STEPS TO IMPORT:
//: I.) Copy this code.
//: II.) Paste it into the head of your map.
//: (Therefor go to the Trigger Editor, select the mapname and paste
//: into the area on the right)
//: III.) Save your map!
//: (With File - Save Map (S) or control + S. DO NOT SAVE WITH SAVE AS!)
//: IV.) You got it! You imported the system.
//:
//: To make sure this system works, you should try a few tests!
//:
//: METHODS
//:
//: SharedObjects:
//: This is a small library for GroupSpawns and unitsspawns so
//: you can easily manage conditional spawning and function calls
//: at actual spawning.
//:
//:
//:
//:
//:
//:
//: Thanks for downloading and using my system!
//:
//: Please don't forget to give credits to me (dhk_undead_lord / Aka Anachron)
//:
//:******************************************************************************
library AnaSpawnSys initializer init
//==========================================================================
// %CUSTOMIZATION AREA%: Feel free to change anything to what you need!
//==========================================================================
globals
//: %Default Values%
//: Check whether wanting to create units in each other
//: on creation or not. This prevents the bug that units
//: spawn out of area when to much units are into, or
//: simple the pathing is off.
private constant boolean CREATION_ZEROCOLLISION = true
//: %Timers%
private constant timer WAVE_TIMER = CreateTimer()
private constant real WAVE_INT = 0.25
endglobals
//==========================================================================
//: %DO NOT CHANGE THIS UNLIKE YOU KNOW WHAT YOU ARE DOING%
//==========================================================================
//: =================================
//: Small Interface for Spawns
//: =================================
function interface onSpawn takes nothing returns nothing
function interface onCheck takes nothing returns boolean
function interface onUnitSpawn takes unit u returns nothing
private function returnTrue takes nothing returns boolean
return true
endfunction
struct SharedObjects
onSpawn spawnCall = 0
onCheck checkCall = 0
boolean isSetSpawn = false
boolean isSetCheck = false
public method setOnSpawnCall takes onSpawn onS returns nothing
set .spawnCall = onS
set .isSetSpawn = true
endmethod
public method runOnSpawnCall takes nothing returns nothing
if .isSetSpawn then
call .spawnCall.execute()
endif
endmethod
public method setOnSpawnCheck takes onCheck onC returns nothing
set .checkCall = onC
set .isSetCheck = true
endmethod
public method runOnSpawnCheck takes nothing returns boolean
if .isSetCheck then
return .checkCall.evaluate()
endif
return true
endmethod
endstruct
//: =================================
struct UnitSpawn extends SharedObjects
integer ID = 0
integer unitID = 039;0000039;
integer amount = 0
string sfxPath = ""
onUnitSpawn onUnitSpawnCall = 0
public static method create takes integer unitId, integer amount, onUnitSpawn onUnitSp, string effPath returns UnitSpawn
local thistype us = thistype.allocate()
set us.unitID = unitId
set us.amount = amount
set us.onUnitSpawnCall = onUnitSp
set us.sfxPath = effPath
return us
endmethod
public method spawn takes player p, real posX, real posY returns nothing
local integer i = 0
local integer i2 = .amount
local unit u = null
if .runOnSpawnCheck() then
call .runOnSpawnCall()
loop
exitwhen i >= i2
set u = CreateUnit(p, .unitID, posX, posY, 270)
if .sfxPath != "" then
call DestroyEffect(AddSpecialEffect(.sfxPath, GetUnitX(u), GetUnitY(u)))
endif
if CREATION_ZEROCOLLISION then
call SetUnitPathing(u, false)
call SetUnitX(u, posX)
call SetUnitY(u, posY)
call SetUnitPathing(u, true)
endif
if .onUnitSpawnCall != 0 then
call .onUnitSpawnCall.execute(u)
endif
set i = i + 1
endloop
endif
set u = null
endmethod
endstruct
struct GroupSpawn extends SharedObjects
integer ID = 0
real delay = 0
real baseX = 0.
real baseY = 0.
UnitSpawn array unitSpawns[64]
integer index = 0
//: =================================
//: CREATE NEW INSTANCES
//: =================================
public static method create takes real baseX, real baseY, real d returns thistype
local thistype usg = thistype.allocate()
set usg.baseX = baseX
set usg.baseY = baseY
set usg.delay = d
return usg
endmethod
//: =================================
//: =================================
//: Add and remove UnitSpawns
//: =================================
public method addUnitSpawn takes UnitSpawn us returns nothing
set us.ID = .index
set .unitSpawns[.index] = us
set .index = .index + 1
endmethod
public method removeUnitSpawn takes UnitSpawn us returns nothing
set .unitSpawns[us.ID] = .unitSpawns[.index]
set .index = .index - 1
endmethod
//: =================================
//: =================================
//: Spawn UnitSpawn-objects.
//: =================================
public method spawnUnits takes player p returns nothing
local integer i = 0
local UnitSpawn us = 0
if .runOnSpawnCheck() then
call .runOnSpawnCall()
loop
exitwhen i >= .index
set us = .unitSpawns<i>
call us.spawn(p, .baseX, .baseY)
set i = i + 1
endloop
endif
endmethod
//: =================================
//: ====================================
//: Desctrutor Method
//: ====================================
private method onDestroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= .index
call .unitSpawns<i>.destroy()
set i = i + 1
endloop
endmethod
//: ====================================
endstruct
struct Wave
GroupSpawn array groupSpawns[64]
integer groupIndex = 0
player owner = null
real interval = 0.
integer ID = 0
//: =================================
//: CREATE NEW INSTANCES
//: =================================
public static method create takes real i, player own returns thistype
local thistype usg = thistype.allocate()
set usg.interval = i
set usg.owner = own
return usg
endmethod
//: =================================
//: =================================
//: Add and remove GroupSpawns
//: =================================
public method addGroupSpawn takes GroupSpawn gs returns nothing
set gs.ID = .groupIndex
set .groupSpawns[.groupIndex] = gs
set .groupIndex = .groupIndex + 1
endmethod
public method removeGroupSpawn takes GroupSpawn gs returns nothing
set .groupSpawns[gs.ID] = .groupSpawns[.groupIndex]
set .groupIndex = .groupIndex - 1
endmethod
//: =================================
public method spawnUnitGroup takes integer i returns nothing
call .groupSpawns<i>.spawnUnits(.owner)
endmethod
//: ====================================
//: Desctrutor Method
//: ====================================
private method onDestroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= .groupIndex
call .groupSpawns<i>.destroy()
set i = i + 1
endloop
endmethod
//: ====================================
endstruct
struct WaveStack
static Wave array toSpawn[8191]
static integer index = 0
// %Data of the Waves%
static real array waitTime[8191]
static real array groupDelay[8191]
static integer array curGroup[8191]
static boolean array isPermanent[8191]
static integer array spawnTimes[8191]
//: =================================
//: CHECK ALL WAYS AND ALL UNITS
//: =================================
public static method checkSpawn takes nothing returns nothing
local integer i = 0
local Wave w = 0
loop
exitwhen i >= thistype.index
set w = thistype.toSpawn<i>
//: We don't have to wait so we
//: can check what should happen after the wave has to
//: be spammed.
if thistype.waitTime<i> <= 0. then
if thistype.groupDelay<i> > 0. then
set thistype.groupDelay<i> = thistype.groupDelay<i> - WAVE_INT
endif
debug call BJDebugMsg("!AoSSpawnSys] |NOTICE| <Wave[" + I2S(i) + "]> <CHECKING FOR SPAWNING!>")
//: If the group has no delay we can call the spawn
if thistype.groupDelay<i> <= 0. then
debug call BJDebugMsg("!AoSSpawnSys] |NOTICE| <Wave[" + I2S(i) + "]> <SPAWN GROUP " + I2S(thistype.curGroup<i>) + "!>")
call w.spawnUnitGroup(thistype.curGroup<i>)
if thistype.curGroup<i> < w.groupIndex - 1 then
set thistype.curGroup<i> = thistype.curGroup<i> + 1
else
set thistype.curGroup<i> = 0
set thistype.waitTime<i> = w.interval
debug call BJDebugMsg("!AoSSpawnSys] |NOTICE| <Wave[" + I2S(i) + "]> <RESET GROUPS!>")
endif
set thistype.groupDelay<i> = w.groupSpawns[thistype.curGroup<i>].delay
endif
//: If we have no permanent wave reduce its amount.
//: If required delete the wave from the stack.
if not thistype.isPermanent<i> then
debug call BJDebugMsg("!AoSSpawnSys] |NOTICE| <Wave[" + I2S(i) + "]> <DELETING THE WAVE!>")
set thistype.spawnTimes<i> = thistype.spawnTimes<i> - 1
if thistype.spawnTimes<i> <= 0 then
call thistype.removeWave(w)
set i = i - 1
endif
endif
else
//: If we have to wait decrease time
set thistype.waitTime<i> = thistype.waitTime<i> - WAVE_INT
endif
set i = i + 1
endloop
endmethod
//: =================================
//: =================================
//: Add and remove Waves
//: =================================
public static method addWave takes Wave w, integer times returns nothing
local integer i = thistype.index
set w.ID = i
set thistype.toSpawn<i> = w
// %Init Wave%
set thistype.waitTime<i> = w.interval
set thistype.curGroup<i> = 0
set thistype.groupDelay<i> = w.groupSpawns[0].delay
set thistype.spawnTimes<i> = times
if times == 0 then
set thistype.isPermanent<i> = true
else
set thistype.isPermanent<i> = false
endif
set thistype.index = thistype.index + 1
endmethod
public static method removeWave takes Wave w returns nothing
local integer i = w.ID
set thistype.toSpawn<i> = thistype.toSpawn[thistype.index]
set thistype.curGroup<i> = thistype.curGroup[thistype.index]
set thistype.groupDelay<i> = thistype.groupDelay[thistype.index]
set thistype.isPermanent<i> = thistype.isPermanent[thistype.index]
set thistype.spawnTimes<i> = thistype.spawnTimes[thistype.index]
set thistype.index = thistype.index - 1
endmethod
//: =================================
endstruct
public function init takes nothing returns nothing
call TimerStart(WAVE_TIMER, WAVE_INT, true, function WaveStack.checkSpawn)
endfunction
endlibrary</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>
Example
JASS:
scope example initializer init
globals
private Wave array NIGHTELF_WAVES
private unit array NIGHTELF_STRUCTURES[8191]
private constant integer ID_LEFTWAVE = 0
private constant integer ID_CENTERWAVE = 1
private constant integer ID_RIGHTWAVE = 2
endglobals
public function nightelfGroupSpawnCheckLeft takes nothing returns boolean
return GetUnitState(NIGHTELF_STRUCTURES[ID_LEFTWAVE], UNIT_STATE_LIFE) != 0.
endfunction
public function nightelfGroupSpawnCheckCenter takes nothing returns boolean
return GetUnitState(NIGHTELF_STRUCTURES[ID_CENTERWAVE], UNIT_STATE_LIFE) != 0.
endfunction
public function nightelfGroupSpawnCheckRight takes nothing returns boolean
return GetUnitState(NIGHTELF_STRUCTURES[ID_RIGHTWAVE], UNIT_STATE_LIFE) != 0.
endfunction
public function timedLife takes unit u returns nothing
call UnitApplyTimedLife(u, 039;0000039;, 25.)
endfunction
private function init takes nothing returns nothing
local Wave w = 0
local GroupSpawn gs = 0
local UnitSpawn us = 0
//:**********************************
//: %LEFT WAVE
//:**********************************
//: Instanciate a new wave
//: spawn every 30 seconds
//: owner is Player 0. (red)
set w = Wave.create(5, Player(0))
//: Instanciate a new GroupSpawn
//: based on Point(0., 0.)
//: delay to last group: 0.00
set gs = GroupSpawn.create(0., 0., 0.)
//: Add a condition to the group spawn
//: first parameter = condition
//: func that returns boolean
call gs.setOnSpawnCheck(nightelfGroupSpawnCheckLeft)
//: Create a new unitspawn
//: type: 'efon' (ent)
//: amount: 1
//: function to call on construction: nothing = 0
//: effect-path: "Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl"
set us = UnitSpawn.create(039;efon039;, 1, timedLife, "Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl")
//: Add the unit spawn to the group
call gs.addUnitSpawn(us)
//: Add the groupspawn to the wave
call w.addGroupSpawn(gs)
//: Add the wave to the current spawn system
//: 0 = endless spawning
call WaveStack.addWave(w, 0)
set NIGHTELF_WAVES[ID_LEFTWAVE] = w
set NIGHTELF_STRUCTURES[ID_LEFTWAVE] = CreateUnit(Player(0), 039;eaow039;, -64., -64., 270.)
//:**********************************
endfunction
endscope