library DroneSystem requires Table, LinkedListModule /*
//==============================================================================
//========================== Drone System ==================================
//==============================================================================
This system allows you to add drones to a unit which follow/surround it.
Examples: Space maps: Use this system to add weapons to ships. The weapons will fire even if the ship moves!
Pokemon maps: Pikachu will always follow the trainer ;)
~~ Usage ~~
To create a new, static drone use
call droneList[yourUnit].add( DroneRawcode, DistanceToTarget, AngleToTarget, IsDroneAttackable) returns drone
integer real real boolean
To create a new rotating drone use
call droneList[yourUnit].addEx( DroneRawcode, DistanceToTarget, InitialAngleToTarget, AnglePerSecond, IsDroneAttackable) returns drone
integer real real real boolean
To clear all drones of a parent use
call droneList[yourUnit].destroy()
To remove a specific drone use
call drone[droneUnit].destroy()
You can modify the following values of a drone:
set drone[droneUnit].angle = newAngle <- the angle relative to the parents facing
set drone[droneUnit].distance = newDistance <- the distance to the parent
set drone[droneUnit].anglePerSecond = new <- the angle the rotating drone travels per second
*/
// Setup Part:
globals
private constant real TIMER_INTERVAL = 0.01
endglobals
/* How to implement this system in your map??
just copy and paste this trigger into your map
*/
//==============================================================================
//========================== System Code ====================================
//==============================================================================
globals
private Table table
endglobals
struct drone extends array
readonly unit unit
real distance
private real a
private real s
implement LinkedList
static method operator [] takes unit u returns drone
return table[GetHandleId(u)]
endmethod
method operator angle= takes real v returns nothing
set .a = angle * bj_DEGTORAD
endmethod
method operator angle takes nothing returns real
return .a
endmethod
method operator anglePerSecond= takes real v returns nothing
set .s = v * TIMER_INTERVAL * bj_DEGTORAD
endmethod
method operator anglePerSecond takes nothing returns real
return .s * bj_RADTODEG / TIMER_INTERVAL
endmethod
method destroy takes nothing returns nothing
call table.remove(GetHandleId(.unit))
call .removeNode()
call .deallocate()
endmethod
method update takes unit parent returns nothing
if IsUnitType(.unit, UNIT_TYPE_DEAD) or GetUnitTypeId(.unit) == 0 then
call .destroy()
else
set .a = .a + .s
call SetUnitX(.unit, GetUnitX(parent) + .distance * Cos(GetUnitFacing(parent) * bj_DEGTORAD + .a))
call SetUnitY(.unit, GetUnitY(parent) + .distance * Sin(GetUnitFacing(parent) * bj_DEGTORAD + .a))
if GetUnitCurrentOrder(.unit) == OrderId("move") then
call IssueImmediateOrder(.unit, "stop")
endif
endif
endmethod
method add takes unit u, real d, real a, real s returns drone
local thistype new = .allocate()
set new.unit = u
set new.distance = d
set new.a = a
set new.s = s
call SetUnitPathing(u, false)
set table[GetHandleId(u)] = new
call .insertNode(new)
return new
endmethod
endstruct
struct droneList extends array
private static timer tim
private drone list
readonly unit parent
implement LinkedList
static method operator [] takes unit u returns droneList
local droneList this
if table.has(GetHandleId(u)) then
set this = table[GetHandleId(u)]
else
set this = droneList.allocate()
set .list = drone.createNode()
set .parent = u
set table[GetHandleId(u)] = this
if .base.next.head then
call TimerStart(.tim, TIMER_INTERVAL, true, function thistype.periodic)
endif
call .base.insertNode(this)
endif
return this
endmethod
method destroy takes nothing returns nothing
local drone node = .list.next
loop
exitwhen node.head
call RemoveUnit(node.unit)
call node.destroy()
set node = node.next
endloop
call table.remove(GetHandleId(.parent))
call .list.removeNode()
call .list.deallocate()
call .removeNode()
call .deallocate()
endmethod
private static method periodic takes nothing returns nothing
local droneList this = .base.next
local drone node
local real x
local real y
local real f
local boolean dead
loop
exitwhen .head
set dead = IsUnitType(.parent, UNIT_TYPE_DEAD) or GetUnitTypeId(.parent) == 0
if not dead then
set node = .list.next
loop
exitwhen node.head
call node.update(.parent)
set node = node.next
endloop
endif
if dead or .list.next.head then
call .destroy()
endif
set this = .next
endloop
if .base.next.head then
call PauseTimer(.tim)
endif
endmethod
method addEx takes integer droneId, real distance, real angle, real anglePerSecond, boolean attackable returns drone
local real x = GetUnitX(parent) + distance * Cos((GetUnitFacing(parent) + angle) * bj_DEGTORAD)
local real y = GetUnitY(parent) + distance * Sin((GetUnitFacing(parent) + angle) * bj_DEGTORAD)
local drone new = .list.add(CreateUnit(GetOwningPlayer(parent), droneId, x, y, GetUnitFacing(parent)), distance, angle * bj_DEGTORAD, anglePerSecond * TIMER_INTERVAL * bj_DEGTORAD)
call SetUnitInvulnerable(new.unit, not attackable)
return new
endmethod
method add takes integer droneId, real distance, real angle, boolean attackable returns drone
return .addEx(droneId, distance, angle, 0, attackable)
endmethod
private static method onInit takes nothing returns nothing
set table = Table.create()
set .tim = CreateTimer()
endmethod
endstruct
endlibrary
//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com