- Joined
- Mar 10, 2009
- Messages
- 5,016
What do you think about this system, any improvements are welcome...
progress: 50%
Picks a unit and loads to a ship/transport and transfer to another location
progress: 50%
Picks a unit and loads to a ship/transport and transfer to another location
JASS:
/**********************************************************************
* CargoSystem v0.5
* by mckill2009
***********************************************************************/
library CargoSystem uses GroupUtils, Table, TimerUtils, SpellEffectEvent
globals
private constant integer LOAD_ID = 'A000' //uses purge
private constant integer UNLOAD_ID = 'A001' //carrion swarm
private constant integer LOAD_ORDER_ID = 852111
private constant integer UNLOAD_ORDER_ID = 852218
private constant real SEARCH_AREA = 3000
//private constant integer ATTACK = 851983
private constant integer MOVE = 851986
//private constant integer SMART = 851971
private integer count = 0
private group TempG = CreateGroup()
private unit TempU = null
private sound loadS
private Table chk
private TableArray typeID
endglobals
/***************************************
* CONFIGURABLES:
****************************************/
private function FilterMore takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_FLYING)
endfunction
/***********************************************************
* NON-CONFIGURABLES
************************************************************/
private function UnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD) and u!=null
endfunction
private function GetDistance takes real x1, real y1, real x2, real y2 returns real
return (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)
endfunction
private function EnumUnits takes nothing returns nothing
set count = count+1
endfunction
private function GetRandomUnitInArea takes real x, real y, real aoe, boolexpr b returns unit
local integer ran
call GroupEnumUnitsInRange(TempG, x, y, aoe, b)
set count = 0
call ForGroup(TempG, function EnumUnits)
set ran = GetRandomInt(1, count)
set count = 0
loop
set TempU = FirstOfGroup(TempG)
set count = count + 1
exitwhen TempU==null or count==ran
call GroupRemoveUnit(TempG, TempU)
endloop
call GroupClear(TempG)
return TempU
endfunction
/***************************************
* LOADING UNITS
****************************************/
private struct LoadMovement
private unit u
private unit tra
private real x
private real y
private static method periodic takes nothing returns nothing
local timer t = GetExpiredTimer()
local LoadMovement this = GetTimerData(t)
if UnitAlive(.u) and chk.boolean[GetHandleId(.u)] then
if GetDistance(.x, .y, GetUnitX(.u), GetUnitY(.u)) > 60000 then
call IssuePointOrderById(.u, MOVE, .x, .y)
else
call IssueTargetOrderById(.tra, LOAD_ORDER_ID, .u)
endif
else
set .u = null
set .tra = null
call ReleaseTimer(t)
call .deallocate()
endif
set t = null
endmethod
static method load takes unit u, unit tra, real x, real y, real interval returns nothing
local LoadMovement this = allocate()
set .u = u
set .tra = tra
set .x = x
set .y = y
call TimerStart(NewTimerEx(this), interval, true, function LoadMovement.periodic)
endmethod
endstruct
/***************************************
* TRANSPORT MOVEMENT
****************************************/
struct CargoSystem
private unit transport
private player owner
private real xGather
private real yGather
private real xDock
private real yDock
private real xUnload
private real yUnload
private real interval
private integer maxLoad
private integer loadedUnitCount
private integer typeCount
private group loadGroup
private boolean isOn
private boolean isTransportLoading
private static integer loadCount = 0
private static integer DATA
private static method countUnitsInGroup takes nothing returns nothing
local thistype this = DATA
if UnitAlive(GetEnumUnit()) then
set loadCount = loadCount + 1
endif
endmethod
private static method unloadGroup takes nothing returns nothing
local thistype this = DATA
local unit u = GetEnumUnit()
if UnitAlive(u) then
call chk.remove(GetHandleId(u))
call GroupRemoveUnit(.loadGroup, u)
call SetUnitPosition(u, .xUnload, .yUnload)
call ShowUnit(u, true)
call SetUnitInvulnerable(u, false)
call UnitRemoveAbility(u, 'Abun')
endif
set u = null
endmethod
private static method filterTransported takes nothing returns boolean
local thistype this = DATA
return not IsUnitInGroup(GetFilterUnit(), .loadGroup) and UnitAlive(GetFilterUnit()) and .owner==GetOwningPlayer(GetFilterUnit()) /*
*/ and GetFilterUnit()!=.transport and FilterMore(GetFilterUnit()) and not chk.has(GetHandleId(GetFilterUnit())) /*
*/ and typeID[this][GetRandomInt(1, .typeCount)]==GetUnitTypeId(GetFilterUnit())
endmethod
private static method periodic takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = GetTimerData(t)
local unit target
local real x
local real y
if UnitAlive(.transport) and .isOn then
set x = GetUnitX(.transport)
set y = GetUnitY(.transport)
//if transporting
if .isTransportLoading then
if GetDistance(.xDock, .yDock, x, y) > 40000 then
call IssuePointOrderById(.transport, MOVE, .xDock, .yDock)
else
set DATA = this
set loadCount = 0
call ForGroup(.loadGroup, function thistype.countUnitsInGroup)
if .maxLoad > loadCount then
set target = GetRandomUnitInArea(.xDock, .yDock, SEARCH_AREA, Filter(function thistype.filterTransported))
if target!=null then
call RemoveGuardPosition(target)
set chk[GetHandleId(target)] = this
set chk.boolean[GetHandleId(target)] = true
call LoadMovement.load(target, .transport, .xGather, .yGather, .interval)
call GroupAddUnit(.loadGroup, target)
set target = null
endif
endif
endif
else //transport is unloading cargo here
call IssuePointOrderById(.transport, UNLOAD_ORDER_ID, .xUnload, .yUnload)
endif
else
set .transport = null
call ReleaseGroup(.loadGroup)
call ReleaseTimer(t)
call .deallocate()
endif
set t = null
endmethod
private static method death takes nothing returns nothing
if chk.has(GetHandleId(GetTriggerUnit())) then
call chk.remove(GetHandleId(GetTriggerUnit()))
endif
endmethod
private static method loadUnit takes nothing returns nothing
local thistype this
local unit u = GetSpellTargetUnit()
local integer id = GetHandleId(u)
local integer transportID
if chk.has(id) then
set this = chk[id]
set transportID = GetHandleId(.transport)
call ShowUnit(u, false)
call SetUnitInvulnerable(u, true)
call UnitAddAbility(u, 'Abun')
set .loadedUnitCount = .loadedUnitCount + 1
set chk.boolean[id] = false
if .loadedUnitCount==.maxLoad then
set .isTransportLoading = false
call UnitAddAbility(.transport, UNLOAD_ID)
endif
endif
set u = null
endmethod
private static method unloadUnit takes nothing returns nothing
local unit tra = GetTriggerUnit()
local thistype this = chk[GetHandleId(tra)]
if chk.has(GetHandleId(tra)) then
set DATA = this
call ForGroup(.loadGroup, function thistype.unloadGroup)
set .isTransportLoading = true
set .loadedUnitCount = 0
call UnitRemoveAbility(.transport, UNLOAD_ID)
endif
set tra = null
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(LOAD_ID, function thistype.loadUnit)
call RegisterSpellEffectEvent(UNLOAD_ID, function thistype.unloadUnit)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function thistype.death)
set chk = Table.create()
set typeID = TableArray[0x3000]
endmethod
/***************************************
* API:
****************************************/
static method register takes unit transport, integer maxLoad returns thistype
local thistype this
local integer id = GetHandleId(transport)
if chk.has(id) then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "thistype ERROR: "+ GetUnitName(transport) + " is already registered!")
else
set this = allocate()
set chk[id] = this
set .loadGroup = NewGroup()
set .transport = transport
set .maxLoad = maxLoad
set .owner = null
set .isOn = true
set .isTransportLoading = true
call RemoveGuardPosition(transport)
call UnitAddAbility(transport, LOAD_ID)
endif
return this
endmethod
method setRoute takes real xLoad, real yLoad, real xUnload, real yUnload returns nothing
set .xDock = xLoad
set .yDock = yLoad
set .xUnload = xUnload
set .yUnload = yUnload
endmethod
method setGatherPoint takes real x, real y returns nothing
set .xGather = x
set .yGather = y
endmethod
method setLoadedPlayer takes player p returns nothing
set .owner = p
endmethod
method setUnitLoadingIdType takes integer unitID returns nothing
set .typeCount = .typeCount + 1
set typeID[this][.typeCount] = unitID
endmethod
method setMaxLoad takes integer maxLoad returns nothing
set .maxLoad = maxLoad
set chk[GetHandleId(.transport)] = maxLoad
endmethod
method removeUnitType takes integer unitID returns nothing
local integer i = 0
endmethod
method launch takes real interval returns nothing
set .interval = interval
call TimerStart(NewTimerEx(this), interval, true, function thistype.periodic)
endmethod
method remove takes nothing returns nothing
call chk.remove(GetHandleId(.transport))
set .isOn = false
endmethod
endstruct
endlibrary