mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge pull request #6 from svenvandevelde/Implement-cargo-initialization-upon-start-of-a-mission
Implement cargo initialization upon start of a mission
This commit is contained in:
commit
effc400a46
@ -1,42 +1,43 @@
|
||||
|
||||
local base = _G
|
||||
|
||||
env.info("Loading MOOSE " .. base.timer.getAbsTime() )
|
||||
|
||||
function script_path()
|
||||
local str = debug.getinfo(2, "S").source
|
||||
return str:match("(.*/)"):sub(1,-2)
|
||||
end
|
||||
|
||||
|
||||
Include = {}
|
||||
|
||||
Include.MissionPath = script_path() .. "Mission\\"
|
||||
Include.ProgramPath = "Scripts\\Moose\\Moose\\"
|
||||
|
||||
env.info( "Include.MissionPath = " .. Include.MissionPath)
|
||||
env.info( "Include.ProgramPath = " .. Include.ProgramPath)
|
||||
Include.Files = {}
|
||||
Include.Path = function()
|
||||
local str = debug.getinfo(2, "S").source
|
||||
return str:match("(.*/)"):sub(1,-2):gsub("\\","/")
|
||||
end
|
||||
|
||||
Include.File = function( IncludeFile )
|
||||
if not Include.Files[ IncludeFile ] then
|
||||
Include.Files[IncludeFile] = IncludeFile
|
||||
local f = base.loadfile( Include.ProgramPath .. IncludeFile .. ".lua" )
|
||||
env.info( "Include:" .. IncludeFile .. " from " .. Include.ProgramPath )
|
||||
local f = assert( base.loadfile( Include.ProgramPath .. IncludeFile .. ".lua" ) )
|
||||
if f == nil then
|
||||
local f = base.loadfile( Include.MissionPath .. IncludeFile .. ".lua" )
|
||||
env.info( "Include:" .. IncludeFile .. " from " .. Include.MissionPath )
|
||||
local f = assert( base.loadfile( Include.MissionPath .. IncludeFile .. ".lua" ) )
|
||||
if f == nil then
|
||||
error ("Could not load MOOSE file " .. IncludeFile .. ".lua" )
|
||||
else
|
||||
env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.ProgramPath )
|
||||
env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.MissionPath )
|
||||
return f()
|
||||
end
|
||||
else
|
||||
env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.MissionPath )
|
||||
env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.ProgramPath )
|
||||
return f()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Include.ProgramPath = "Scripts/Moose/Moose/"
|
||||
Include.MissionPath = Include.Path()
|
||||
|
||||
env.info( "Include.ProgramPath = " .. Include.ProgramPath)
|
||||
env.info( "Include.MissionPath = " .. Include.MissionPath)
|
||||
|
||||
Include.Files = {}
|
||||
|
||||
Include.File( "Database" )
|
||||
|
||||
env.info("Loaded MOOSE Include Engine")
|
||||
23
Loaders/Moose_Load_Embedded.lua
Normal file
23
Loaders/Moose_Load_Embedded.lua
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
local base = _G
|
||||
env.info("Loading MOOSE " .. base.timer.getAbsTime() )
|
||||
|
||||
Include = {}
|
||||
|
||||
Include.Path = function()
|
||||
local str = debug.getinfo(2, "S").source
|
||||
return str:match("(.*/)"):sub(1,-2):gsub("\\","/")
|
||||
end
|
||||
|
||||
Include.File = function( IncludeFile )
|
||||
end
|
||||
|
||||
Include.ProgramPath = "Scripts/Moose/Moose/"
|
||||
Include.MissionPath = Include.Path()
|
||||
|
||||
env.info( "Include.ProgramPath = " .. Include.ProgramPath)
|
||||
env.info( "Include.MissionPath = " .. Include.MissionPath)
|
||||
|
||||
Include.Files = {}
|
||||
|
||||
env.info("Loaded MOOSE Include Engine")
|
||||
159
Loaders/Moose_Test.lua
Normal file
159
Loaders/Moose_Test.lua
Normal file
@ -0,0 +1,159 @@
|
||||
|
||||
local base = _G
|
||||
|
||||
local MOOSE_Version = "0.1.1.1"
|
||||
|
||||
env.info("Loading MOOSE " .. base.timer.getAbsTime() )
|
||||
|
||||
function script_path()
|
||||
local str = debug.getinfo(2, "S").source
|
||||
return str:match("(.*/)"):sub(1,-2):gsub("\\","/")
|
||||
end
|
||||
|
||||
|
||||
Include = {}
|
||||
|
||||
Include.ProgramPath = "Scripts/Moose/Moose/"
|
||||
Include.MissionPath = script_path()
|
||||
|
||||
env.info( "Include.ProgramPath = " .. Include.ProgramPath)
|
||||
env.info( "Include.MissionPath = " .. Include.MissionPath)
|
||||
Include.Files = {}
|
||||
|
||||
Include.FileIn = function(fileName, table)
|
||||
-- env.info( fileName )
|
||||
local chunk, errMsg = base.loadfile(fileName)
|
||||
if chunk ~= nil then
|
||||
env.info( "chunk assigned " )
|
||||
env.info( Include.oneLineSerialize( chunk ) )
|
||||
base.setfenv(chunk, table)
|
||||
chunk()
|
||||
if table.MOOSE_Version then
|
||||
env.info( table.MOOSE_Version )
|
||||
end
|
||||
return chunk
|
||||
else
|
||||
return nil, errMsg
|
||||
end
|
||||
end
|
||||
|
||||
Include.MisFiles = {}
|
||||
|
||||
Include.FileName = function( num )
|
||||
local hexstr = '0123456789ABCDEF'
|
||||
local s = ''
|
||||
while num > 0 do
|
||||
local mod = math.fmod(num, 16)
|
||||
s = string.sub(hexstr, mod+1, mod+1) .. s
|
||||
num = math.floor(num / 16)
|
||||
end
|
||||
if s == '' then s = '0' end
|
||||
-- env.info( string.format( "~mis" .. "%8s", "00000000" .. s ) )
|
||||
return string.format( "~mis" .. "%s", string.sub( "00000000" .. s, -8 ) )
|
||||
end
|
||||
|
||||
Include.ScanFiles = function()
|
||||
|
||||
local i = 0
|
||||
while i <= 32767 do
|
||||
local FileName = Include.FileName( i )
|
||||
local FileChunk = {}
|
||||
local FileChunk = Include.FileIn( Include.MissionPath .. FileName, FileChunk )
|
||||
if FileChunk then
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Include.File = function( IncludeFile )
|
||||
if not Include.Files[ IncludeFile ] then
|
||||
Include.Files[IncludeFile] = IncludeFile
|
||||
env.info( "Include:" .. IncludeFile .. " from " .. Include.ProgramPath )
|
||||
local f = base.loadfile( Include.ProgramPath .. IncludeFile .. ".lua" )
|
||||
if f == nil then
|
||||
env.info( "Include:" .. IncludeFile .. " from " .. Include.MissionPath )
|
||||
local f = base.loadfile( Include.MissionPath .. IncludeFile .. ".lua" )
|
||||
if f == nil then
|
||||
error ("Could not load MOOSE file " .. IncludeFile .. ".lua" )
|
||||
else
|
||||
env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.MissionPath )
|
||||
return f()
|
||||
end
|
||||
else
|
||||
env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.ProgramPath )
|
||||
return f()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--porting in Slmod's "safestring" basic serialize
|
||||
Include.basicSerialize = function(s)
|
||||
if s == nil then
|
||||
return "\"\""
|
||||
else
|
||||
if ((type(s) == 'number') or (type(s) == 'boolean') or (type(s) == 'function') or (type(s) == 'table') or (type(s) == 'userdata') ) then
|
||||
return tostring(s)
|
||||
elseif type(s) == 'string' then
|
||||
s = string.format('%q', s)
|
||||
return s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- porting in Slmod's serialize_slmod2
|
||||
Include.oneLineSerialize = function(tbl) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
|
||||
if type(tbl) == 'table' then --function only works for tables!
|
||||
|
||||
local tbl_str = {}
|
||||
|
||||
tbl_str[#tbl_str + 1] = '{'
|
||||
|
||||
for ind,val in pairs(tbl) do -- serialize its fields
|
||||
if type(ind) == "number" then
|
||||
tbl_str[#tbl_str + 1] = '['
|
||||
tbl_str[#tbl_str + 1] = tostring(ind)
|
||||
tbl_str[#tbl_str + 1] = ']='
|
||||
else --must be a string
|
||||
tbl_str[#tbl_str + 1] = '['
|
||||
tbl_str[#tbl_str + 1] = Include.basicSerialize(ind)
|
||||
tbl_str[#tbl_str + 1] = ']='
|
||||
end
|
||||
|
||||
if ((type(val) == 'number') or (type(val) == 'boolean')) then
|
||||
tbl_str[#tbl_str + 1] = tostring(val)
|
||||
tbl_str[#tbl_str + 1] = ','
|
||||
elseif type(val) == 'string' then
|
||||
tbl_str[#tbl_str + 1] = Include.basicSerialize(val)
|
||||
tbl_str[#tbl_str + 1] = ','
|
||||
elseif type(val) == 'nil' then -- won't ever happen, right?
|
||||
tbl_str[#tbl_str + 1] = 'nil,'
|
||||
elseif type(val) == 'table' then
|
||||
if ind == "__index" then
|
||||
tbl_str[#tbl_str + 1] = "__index"
|
||||
tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
|
||||
else
|
||||
tbl_str[#tbl_str + 1] = Include.oneLineSerialize(val)
|
||||
tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
|
||||
end
|
||||
elseif type(val) == 'function' then
|
||||
tbl_str[#tbl_str + 1] = "function " .. tostring(ind)
|
||||
tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
|
||||
else
|
||||
env.info('unable to serialize value type ' .. Include.basicSerialize(type(val)) .. ' at index ' .. tostring(ind))
|
||||
env.info( debug.traceback() )
|
||||
end
|
||||
|
||||
end
|
||||
tbl_str[#tbl_str + 1] = '}'
|
||||
return table.concat(tbl_str)
|
||||
else
|
||||
return tostring(tbl)
|
||||
end
|
||||
end
|
||||
|
||||
Include.ScanFiles( )
|
||||
|
||||
Include.File( "Database" )
|
||||
|
||||
env.info("Loaded MOOSE Include Engine")
|
||||
@ -4,12 +4,22 @@
|
||||
|
||||
Include.File( "Routines" )
|
||||
|
||||
_TraceOn = true
|
||||
_TraceClass = {
|
||||
DATABASE = true,
|
||||
--SEAD = true,
|
||||
--DESTROYBASETASK = true,
|
||||
--MOVEMENT = true,
|
||||
--SPAWN = true,
|
||||
--GROUP = true,
|
||||
--UNIT = true,
|
||||
}
|
||||
|
||||
BASE = {
|
||||
|
||||
ClassName = "BASE",
|
||||
ClassID = 0,
|
||||
Events = {}
|
||||
|
||||
}
|
||||
|
||||
--- The base constructor. This is the top top class of all classed defined within the MOOSE.
|
||||
@ -53,7 +63,7 @@ function BASE:Inherit( Child, Parent )
|
||||
Child.__index = Child
|
||||
end
|
||||
--Child.ClassName = Child.ClassName .. '.' .. Child.ClassID
|
||||
trace.i( Child.ClassName, 'Inherited from ' .. Parent.ClassName )
|
||||
self:T( 'Inherited from ' .. Parent.ClassName )
|
||||
return Child
|
||||
end
|
||||
|
||||
@ -104,6 +114,7 @@ trace.f( self.ClassName )
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
BaseEventCodes = {
|
||||
"S_EVENT_SHOT",
|
||||
"S_EVENT_HIT",
|
||||
@ -129,7 +140,46 @@ BaseEventCodes = {
|
||||
"S_EVENT_SHOOTING_START",
|
||||
"S_EVENT_SHOOTING_END",
|
||||
"S_EVENT_MAX",
|
||||
}
|
||||
}
|
||||
|
||||
--onEvent( {[1]="S_EVENT_BIRTH",[2]={["subPlace"]=5,["time"]=0,["initiator"]={["id_"]=16884480,},["place"]={["id_"]=5000040,},["id"]=15,["IniUnitName"]="US F-15C@RAMP-Air Support Mountains#001-01",},}
|
||||
-- Event = {
|
||||
-- id = enum world.event,
|
||||
-- time = Time,
|
||||
-- initiator = Unit,
|
||||
-- target = Unit,
|
||||
-- place = Unit,
|
||||
-- subPlace = enum world.BirthPlace,
|
||||
-- weapon = Weapon
|
||||
-- }
|
||||
|
||||
|
||||
function BASE:CreateEventBirth( EventTime, Initiator, IniUnitName, place, subplace )
|
||||
trace.f( self.ClassName, { EventTime, Initiator, IniUnitName, place, subplace } )
|
||||
|
||||
local Event = {
|
||||
id = world.event.S_EVENT_BIRTH,
|
||||
time = EventTime,
|
||||
initiator = Initiator,
|
||||
IniUnitName = IniUnitName,
|
||||
place = place,
|
||||
subplace = subplace
|
||||
}
|
||||
|
||||
world.onEvent( Event )
|
||||
end
|
||||
|
||||
function BASE:CreateEventCrash( EventTime, Initiator )
|
||||
trace.f( self.ClassName, { EventTime, Initiator } )
|
||||
|
||||
local Event = {
|
||||
id = world.event.S_EVENT_CRASH,
|
||||
time = EventTime,
|
||||
initiator = Initiator,
|
||||
}
|
||||
|
||||
world.onEvent( Event )
|
||||
end
|
||||
|
||||
function BASE:onEvent(event)
|
||||
--trace.f(self.ClassName, event )
|
||||
@ -159,3 +209,22 @@ function BASE:onEvent(event)
|
||||
|
||||
end
|
||||
|
||||
-- Trace section
|
||||
|
||||
|
||||
function BASE:T( Arguments )
|
||||
|
||||
if _TraceOn and _TraceClass[self.ClassName] then
|
||||
|
||||
local DebugInfo = debug.getinfo( 2, "nl" )
|
||||
|
||||
local Function = "function"
|
||||
if DebugInfo.name then
|
||||
Function = DebugInfo.name
|
||||
end
|
||||
|
||||
local Line = DebugInfo.currentline
|
||||
|
||||
env.info( string.format( "%6d/%1s:%20s%05d.%s\(%s\)" , Line, "T", self.ClassName, self.ClassID, Function, routines.utils.oneLineSerialize( Arguments ) ) )
|
||||
end
|
||||
end
|
||||
|
||||
1015
Moose/Cargo.lua
1015
Moose/Cargo.lua
File diff suppressed because it is too large
Load Diff
280
Moose/Client.lua
280
Moose/Client.lua
@ -23,7 +23,6 @@ CLIENT = {
|
||||
ClientTransport = false,
|
||||
ClientBriefingShown = false,
|
||||
_Menus = {},
|
||||
_Cargos = {},
|
||||
_Tasks = {},
|
||||
Messages = {
|
||||
}
|
||||
@ -45,10 +44,9 @@ CLIENT = {
|
||||
-- Mission:AddClient( CLIENT:New( 'RU MI-8MTV2*RAMP-Deploy Troops 4' ):Transport() )
|
||||
|
||||
function CLIENT:New( ClientName, ClientBriefing )
|
||||
trace.f(self.ClassName)
|
||||
|
||||
-- Arrange meta tables
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:T()
|
||||
|
||||
self.ClientName = ClientName
|
||||
self:AddBriefing( ClientBriefing )
|
||||
self.MessageSwitch = true
|
||||
@ -59,29 +57,162 @@ end
|
||||
--- Resets a CLIENT.
|
||||
-- @tparam string ClientName Name of the Group as defined within the Mission Editor. The Group must have a Unit with the type Client.
|
||||
function CLIENT:Reset( ClientName )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
self._Menus = {}
|
||||
self._Cargos = {}
|
||||
end
|
||||
|
||||
--- ClientGroup returns the Group of a Client.
|
||||
-- This function is modified to deal with a couple of bugs in DCS 1.5.3
|
||||
-- @treturn Group
|
||||
function CLIENT:ClientGroup()
|
||||
--trace.f(self.ClassName)
|
||||
local ClientData = Group.getByName( self.ClientName )
|
||||
if ClientData and ClientData:isExist() then
|
||||
trace.i( self.ClassName, self.ClientName .. " : group found!" )
|
||||
return ClientData
|
||||
else
|
||||
-- trace.x( self.ClassName, self.ClientName .. " : no group found!" )
|
||||
return nil
|
||||
--self:T()
|
||||
|
||||
-- local ClientData = Group.getByName( self.ClientName )
|
||||
-- if ClientData and ClientData:isExist() then
|
||||
-- self:T( self.ClientName .. " : group found!" )
|
||||
-- return ClientData
|
||||
-- else
|
||||
-- return nil
|
||||
-- end
|
||||
|
||||
local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) }
|
||||
for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
|
||||
--self:T( { "CoalitionData:", CoalitionData } )
|
||||
for UnitId, UnitData in pairs( CoalitionData ) do
|
||||
--self:T( { "UnitData:", UnitData } )
|
||||
if UnitData and UnitData:isExist() then
|
||||
|
||||
local ClientGroup = Group.getByName( self.ClientName )
|
||||
if ClientGroup then
|
||||
self:T( "ClientGroup = " .. self.ClientName )
|
||||
if ClientGroup:isExist() then
|
||||
if ClientGroup:getID() == UnitData:getGroup():getID() then
|
||||
self:T( "Normal logic" )
|
||||
self:T( self.ClientName .. " : group found!" )
|
||||
return ClientGroup
|
||||
end
|
||||
else
|
||||
-- Now we need to resolve the bugs in DCS 1.5 ...
|
||||
-- Consult the database for the units of the Client Group. (ClientGroup:getUnits() returns nil)
|
||||
self:T( "Bug 1.5 logic" )
|
||||
local ClientUnits = _Database.Groups[self.ClientName].Units
|
||||
self:T( { ClientUnits[1].name, env.getValueDictByKey(ClientUnits[1].name) } )
|
||||
for ClientUnitID, ClientUnitData in pairs( ClientUnits ) do
|
||||
self:T( { tonumber(UnitData:getID()), ClientUnitData.unitId } )
|
||||
if tonumber(UnitData:getID()) == ClientUnitData.unitId then
|
||||
local ClientGroupTemplate = _Database.Groups[self.ClientName].Template
|
||||
self.ClientGroupID = ClientGroupTemplate.groupId
|
||||
self.ClientGroupUnit = UnitData
|
||||
self:T( self.ClientName .. " : group found in bug 1.5 resolvement logic!" )
|
||||
return ClientGroup
|
||||
end
|
||||
end
|
||||
end
|
||||
-- else
|
||||
-- error( "Client " .. self.ClientName .. " not found!" )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- For non player clients
|
||||
local ClientGroup = Group.getByName( self.ClientName )
|
||||
if ClientGroup then
|
||||
self:T( "ClientGroup = " .. self.ClientName )
|
||||
if ClientGroup:isExist() then
|
||||
self:T( "Normal logic" )
|
||||
self:T( self.ClientName .. " : group found!" )
|
||||
return ClientGroup
|
||||
end
|
||||
end
|
||||
|
||||
self.ClientGroupID = nil
|
||||
self.ClientGroupUnit = nil
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
function CLIENT:GetClientGroupID()
|
||||
self:T()
|
||||
|
||||
ClientGroup = self:ClientGroup()
|
||||
|
||||
if ClientGroup then
|
||||
if ClientGroup:isExist() then
|
||||
return ClientGroup:getID()
|
||||
else
|
||||
return self.ClientGroupID
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
function CLIENT:GetClientGroupName()
|
||||
self:T()
|
||||
|
||||
ClientGroup = self:ClientGroup()
|
||||
|
||||
if ClientGroup then
|
||||
if ClientGroup:isExist() then
|
||||
self:T( ClientGroup:getName() )
|
||||
return ClientGroup:getName()
|
||||
else
|
||||
self:T( self.ClientName )
|
||||
return self.ClientName
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns the Unit of the @{CLIENT}.
|
||||
-- @treturn Unit
|
||||
function CLIENT:GetClientGroupUnit()
|
||||
self:T()
|
||||
|
||||
local ClientGroup = self:ClientGroup()
|
||||
|
||||
if ClientGroup then
|
||||
if ClientGroup:isExist() then
|
||||
return ClientGroup:getUnits()[1]
|
||||
else
|
||||
return self.ClientGroupUnit
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function CLIENT:GetUnit()
|
||||
self:T()
|
||||
|
||||
return UNIT:New( self:GetClientGroupUnit() )
|
||||
end
|
||||
|
||||
|
||||
--- Returns the Position of the @{CLIENT}.
|
||||
-- @treturn Position
|
||||
function CLIENT:ClientPosition()
|
||||
--self:T()
|
||||
|
||||
ClientGroupUnit = self:GetClientGroupUnit()
|
||||
|
||||
if ClientGroupUnit then
|
||||
if ClientGroupUnit:isExist() then
|
||||
return ClientGroupUnit:getPosition()
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Transport defines that the Client is a Transport.
|
||||
-- @treturn CLIENT
|
||||
function CLIENT:Transport()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
self.ClientTransport = true
|
||||
return self
|
||||
@ -91,7 +222,7 @@ end
|
||||
-- @tparam string ClientBriefing is the text defining the Mission briefing.
|
||||
-- @treturn CLIENT
|
||||
function CLIENT:AddBriefing( ClientBriefing )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
self.ClientBriefing = ClientBriefing
|
||||
return self
|
||||
end
|
||||
@ -99,114 +230,29 @@ end
|
||||
--- IsTransport returns if a Client is a transport.
|
||||
-- @treturn bool
|
||||
function CLIENT:IsTransport()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
return self.ClientTransport
|
||||
end
|
||||
|
||||
--- FindCargo finds loaded Cargo within a CLIENT instance.
|
||||
-- Cargo is loaded when certain PICK-UP or DEPLOY Tasks are properly executed.
|
||||
-- @tparam string CargoName is the name of the cargo.
|
||||
-- @treturn CARGO_TYPE
|
||||
function CLIENT:FindCargo( CargoName )
|
||||
trace.f(self.ClassName)
|
||||
return self._Cargos[CargoName]
|
||||
end
|
||||
|
||||
--- ShowCargo shows the @{CARGO} within the CLIENT to the Player.
|
||||
-- The @{CARGO} is shown throught the MESSAGE system of DCS World.
|
||||
function CLIENT:ShowCargo()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
local CargoMsg = ""
|
||||
local CargoMsg = ""
|
||||
|
||||
for CargoName, Cargo in pairs( self._Cargos ) do
|
||||
if CargoMsg ~= "" then
|
||||
CargoMsg = CargoMsg .. "\n"
|
||||
end
|
||||
CargoMsg = CargoMsg .. Cargo.CargoName .. " Type:" .. Cargo.CargoType.TEXT .. " Weight: " .. Cargo.CargoWeight
|
||||
end
|
||||
|
||||
if CargoMsg == '' then
|
||||
CargoMsg = "empty"
|
||||
end
|
||||
|
||||
self:Message( CargoMsg, 15, self.ClientName .. "/Cargo", "Co-Pilot: Cargo Status", 30 )
|
||||
|
||||
end
|
||||
|
||||
--- InitCargo allows to initialize @{CARGO} on the CLIENT when the client initializes.
|
||||
-- @tparam string InitCargoNames is a string or a table containing the names of the @{CARGO}s initialized in the Mission.
|
||||
-- @treturn CLIENT
|
||||
function CLIENT:InitCargo( InitCargoNames )
|
||||
trace.f(self.ClassName, { InitCargoNames } )
|
||||
|
||||
local Valid = true
|
||||
|
||||
if Valid then
|
||||
if type( InitCargoNames ) == "table" then
|
||||
self.InitCargoNames = InitCargoNames
|
||||
else
|
||||
self.InitCargoNames = { InitCargoNames }
|
||||
for CargoName, Cargo in pairs( CARGOS ) do
|
||||
if self == Cargo:IsLoadedInClient() then
|
||||
CargoMsg = CargoMsg .. Cargo.CargoName .. " Type:" .. Cargo.CargoType .. " Weight: " .. Cargo.CargoWeight .. "\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
|
||||
--- AddCargo allows to add @{CARGO} on the CLIENT.
|
||||
-- @tparam string CargoName is the name of the @{CARGO}.
|
||||
-- @tparam string CargoGroupName is the name of an active Group defined within the Mission Editor or Dynamically Spawned. Note that this is only applicable for Unit @{CARGO} Types.
|
||||
-- @tparam CARGO_TYPE CargoType is the Type of the @{CARGO}.
|
||||
-- @tparam number CargoWeight is the weight of the cargo in Kg.
|
||||
-- @tparam string CargoGroupTemplate is the name of an active Group defined within the Mission Editor with "Late Activation".
|
||||
-- @treturn CLIENT
|
||||
function CLIENT:AddCargo( CargoName, CargoGroupName, CargoType, CargoWeight, CargoGroupTemplate )
|
||||
trace.f(self.ClassName, { CargoName, CargoGroupName, CargoType, CargoWeight, CargoGroupTemplate } )
|
||||
|
||||
local Valid = true
|
||||
|
||||
Valid = routines.ValidateString( CargoName, "CargoName", Valid )
|
||||
Valid = routines.ValidateEnumeration( CargoType, "CargoType", CARGO_TYPE, Valid )
|
||||
Valid = routines.ValidateNumber( CargoWeight, "CargoWeight", Valid )
|
||||
|
||||
if Valid then
|
||||
local Cargo = {}
|
||||
Cargo.CargoName = CargoName
|
||||
Cargo.CargoGroupName = CargoGroupName
|
||||
Cargo.CargoType = CargoType
|
||||
Cargo.CargoWeight = CargoWeight
|
||||
if CargoGroupTemplate then
|
||||
Cargo.CargoGroupTemplate = CargoGroupTemplate
|
||||
if CargoMsg == "" then
|
||||
CargoMsg = "empty"
|
||||
end
|
||||
self._Cargos[CargoName] = Cargo
|
||||
self:ShowCargo()
|
||||
end
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
self:Message( CargoMsg, 15, self.ClientName .. "/Cargo", "Co-Pilot: Cargo Status", 30 )
|
||||
|
||||
--- RemoveCargo removes @{CARGO} from the CLIENT.
|
||||
-- @tparam string CargoName is the name of the @{CARGO}.
|
||||
-- @treturn Cargo
|
||||
function CLIENT:RemoveCargo( CargoName )
|
||||
trace.f(self.ClassName, { CargoName } )
|
||||
|
||||
|
||||
local Valid = true
|
||||
local Cargo = nil
|
||||
|
||||
Valid = routines.ValidateString( CargoName, "CargoName", Valid )
|
||||
|
||||
if Valid then
|
||||
trace.i( "CLIENT", "RemoveCargo: CargoName = " .. CargoName )
|
||||
Cargo = routines.utils.deepCopy( self._Cargos[CargoName] )
|
||||
self._Cargos[CargoName] = nil
|
||||
end
|
||||
|
||||
return Cargo
|
||||
|
||||
end
|
||||
|
||||
--- SwitchMessages is a local function called by the DCS World Menu system to switch off messages.
|
||||
@ -222,13 +268,13 @@ end
|
||||
-- @tparam string MessageCategory is the category of the message (the title).
|
||||
-- @tparam number MessageInterval is the interval in seconds between the display of the Message when the CLIENT is in the air.
|
||||
function CLIENT:Message( Message, MessageDuration, MessageId, MessageCategory, MessageInterval )
|
||||
trace.f( self.ClassName, { Message, MessageDuration, MessageId, MessageCategory, MessageInterval } )
|
||||
self:T()
|
||||
|
||||
if not self.MenuMessages then
|
||||
if self:ClientGroup() and self:ClientGroup():getID() then
|
||||
self.MenuMessages = MENU_SUB_GROUP:New( self:ClientGroup():getID(), 'Messages' )
|
||||
self.MenuRouteMessageOn = MENU_COMMAND_GROUP:New( self:ClientGroup():getID(), 'Messages On', self.MenuMessages, CLIENT.SwitchMessages, { self, true } )
|
||||
self.MenuRouteMessageOff = MENU_COMMAND_GROUP:New( self:ClientGroup():getID(),'Messages Off', self.MenuMessages, CLIENT.SwitchMessages, { self, false } )
|
||||
if self:GetClientGroupID() then
|
||||
self.MenuMessages = MENU_SUB_GROUP:New( self:GetClientGroupID(), 'Messages' )
|
||||
self.MenuRouteMessageOn = MENU_COMMAND_GROUP:New( self:GetClientGroupID(), 'Messages On', self.MenuMessages, CLIENT.SwitchMessages, { self, true } )
|
||||
self.MenuRouteMessageOff = MENU_COMMAND_GROUP:New( self:GetClientGroupID(),'Messages Off', self.MenuMessages, CLIENT.SwitchMessages, { self, false } )
|
||||
end
|
||||
end
|
||||
|
||||
@ -248,7 +294,7 @@ trace.f( self.ClassName, { Message, MessageDuration, MessageId, MessageCategory,
|
||||
end
|
||||
MESSAGE:New( Message, MessageCategory, MessageDuration, MessageId ):ToClient( self )
|
||||
else
|
||||
if self:ClientGroup() and self:ClientGroup():getUnits() and self:ClientGroup():getUnits()[1] and not self:ClientGroup():getUnits()[1]:inAir() then
|
||||
if self:GetClientGroupUnit() and not self:GetClientGroupUnit():inAir() then
|
||||
if timer.getTime() - self.Messages[MessageId].MessageTime >= self.Messages[MessageId].MessageDuration + 10 then
|
||||
MESSAGE:New( Message, MessageCategory, MessageDuration, MessageId ):ToClient( self )
|
||||
self.Messages[MessageId].MessageTime = timer.getTime()
|
||||
|
||||
@ -13,6 +13,7 @@ DATABASE = {
|
||||
NavPoints = {},
|
||||
Statics = {},
|
||||
Players = {},
|
||||
ActivePlayers = {},
|
||||
ClientsByName = {},
|
||||
ClientsByID = {},
|
||||
}
|
||||
@ -27,7 +28,7 @@ DATABASECategory =
|
||||
{
|
||||
[Unit.Category.AIRPLANE] = "Plane",
|
||||
[Unit.Category.HELICOPTER] = "Helicopter",
|
||||
[Unit.Category.GROUND_UNIT] = "Ground",
|
||||
[Unit.Category.GROUND_UNIT] = "Vehicle",
|
||||
[Unit.Category.SHIP] = "Ship",
|
||||
[Unit.Category.STRUCTURE] = "Structure",
|
||||
}
|
||||
@ -39,7 +40,6 @@ DATABASECategory =
|
||||
-- -- Define a new DATABASE Object. This DBObject will contain a reference to all Group and Unit Templates defined within the ME and the DCSRTE.
|
||||
-- DBObject = DATABASE:New()
|
||||
function DATABASE:New()
|
||||
trace.f(self.ClassName )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
@ -120,14 +120,14 @@ trace.f(self.ClassName )
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Instantiate new Groups within the DCSRTE.
|
||||
-- This method expects EXACTLY the same structure as a structure within the ME, and needs 2 additional fields defined:
|
||||
-- SpawnCountryID, SpawnCategoryID
|
||||
-- This method is used by the SPAWN class.
|
||||
function DATABASE:Spawn( SpawnTemplate )
|
||||
trace.f( self.ClassName, SpawnTemplate )
|
||||
|
||||
trace.i( self.ClassName, { SpawnTemplate.SpawnCountryID, SpawnTemplate.SpawnCategoryID, SpawnTemplate.name } )
|
||||
self:T( { SpawnTemplate.SpawnCountryID, SpawnTemplate.SpawnCategoryID, SpawnTemplate.name } )
|
||||
|
||||
local SpawnCountryID = SpawnTemplate.SpawnCountryID
|
||||
local SpawnCategoryID = SpawnTemplate.SpawnCategoryID
|
||||
@ -140,16 +140,18 @@ trace.f( self.ClassName, SpawnTemplate )
|
||||
coalition.addGroup( SpawnCountryID, SpawnCategoryID, SpawnTemplate )
|
||||
end
|
||||
|
||||
|
||||
--- Set a status to a Group within the Database, this to check crossing events for example.
|
||||
function DATABASE:SetStatusGroup( GroupName, Status )
|
||||
trace.f( self.ClassName, Status )
|
||||
self:T( Status )
|
||||
|
||||
self.Groups[GroupName].Status = Status
|
||||
end
|
||||
|
||||
|
||||
--- Get a status to a Group within the Database, this to check crossing events for example.
|
||||
function DATABASE:GetStatusGroup( GroupName )
|
||||
trace.f( self.ClassName, Status )
|
||||
self:T( Status )
|
||||
|
||||
if self.Groups[GroupName] then
|
||||
return self.Groups[GroupName].Status
|
||||
@ -162,6 +164,7 @@ end
|
||||
--- Private
|
||||
-- @section Private
|
||||
|
||||
|
||||
--- Registers new Group Templates within the DATABASE Object.
|
||||
function DATABASE:_RegisterGroup( GroupTemplate )
|
||||
|
||||
@ -175,7 +178,9 @@ function DATABASE:_RegisterGroup( GroupTemplate )
|
||||
self.Groups[GroupTemplateName].Template = GroupTemplate
|
||||
self.Groups[GroupTemplateName].groupId = GroupTemplate.groupId
|
||||
self.Groups[GroupTemplateName].UnitCount = #GroupTemplate.units
|
||||
trace.i( self.ClassName, { "Group", self.Groups[GroupTemplateName].GroupName, self.Groups[GroupTemplateName].UnitCount } )
|
||||
self.Groups[GroupTemplateName].Units = GroupTemplate.units
|
||||
|
||||
self:T( { "Group", self.Groups[GroupTemplateName].GroupName, self.Groups[GroupTemplateName].UnitCount } )
|
||||
|
||||
for unit_num, UnitTemplate in pairs(GroupTemplate.units) do
|
||||
|
||||
@ -190,20 +195,24 @@ function DATABASE:_RegisterGroup( GroupTemplate )
|
||||
self.ClientsByName[UnitTemplateName] = UnitTemplate
|
||||
self.ClientsByID[UnitTemplate.unitId] = UnitTemplate
|
||||
end
|
||||
trace.i( self.ClassName, { "Unit", self.Units[UnitTemplateName].UnitName } )
|
||||
self:T( { "Unit", self.Units[UnitTemplateName].UnitName } )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Events
|
||||
-- @section Events
|
||||
|
||||
|
||||
--- Track DCSRTE DEAD or CRASH events for the internal scoring.
|
||||
function DATABASE:OnDeadOrCrash( event )
|
||||
trace.f( self.ClassName, { event } )
|
||||
self:T( { event } )
|
||||
|
||||
local TargetUnitName = nil
|
||||
local TargetGroupName = nil
|
||||
local TargetPlayerName = nil
|
||||
local TargetUnit = nil
|
||||
local TargetGroup = nil
|
||||
local TargetUnitName = ""
|
||||
local TargetGroupName = ""
|
||||
local TargetPlayerName = ""
|
||||
local TargetCoalition = nil
|
||||
local TargetCategory = nil
|
||||
local TargetType = nil
|
||||
@ -212,30 +221,42 @@ trace.f( self.ClassName, { event } )
|
||||
local TargetUnitType = nil
|
||||
|
||||
if event.initiator and Object.getCategory(event.initiator) == Object.Category.UNIT then
|
||||
TargetUnitName = event.initiator:getName()
|
||||
TargetGroupName = Unit.getGroup(event.initiator):getName()
|
||||
TargetPlayerName = event.initiator:getPlayerName()
|
||||
|
||||
TargetUnit = event.initiator
|
||||
TargetGroup = Unit.getGroup( TargetUnit )
|
||||
TargetUnitDesc = TargetUnit:getDesc()
|
||||
|
||||
TargetUnitName = TargetUnit:getName()
|
||||
if TargetGroup and TargetGroup:isExist() then
|
||||
TargetGroupName = TargetGroup:getName()
|
||||
end
|
||||
TargetPlayerName = TargetUnit:getPlayerName()
|
||||
|
||||
TargetCoalition = Unit.getGroup(event.initiator):getCoalition()
|
||||
TargetCategory = Unit.getGroup(event.initiator):getCategory()
|
||||
TargetType = event.initiator:getTypeName()
|
||||
TargetCoalition = TargetUnit:getCoalition()
|
||||
--TargetCategory = TargetUnit:getCategory()
|
||||
TargetCategory = TargetUnitDesc.category -- Workaround
|
||||
TargetType = TargetUnit:getTypeName()
|
||||
|
||||
TargetUnitCoalition = DATABASECoalition[TargetCoalition]
|
||||
TargetUnitCategory = DATABASECategory[TargetCategory]
|
||||
TargetUnitType = TargetType
|
||||
|
||||
trace.i( self.ClassName, { TargetUnitName, TargetGroupName, TargetPlayerName, TargetCoalition, TargetCategory, TargetType } )
|
||||
self:T( { TargetUnitName, TargetGroupName, TargetPlayerName, TargetCoalition, TargetCategory, TargetType } )
|
||||
end
|
||||
|
||||
for PlayerName, PlayerData in pairs( self.Players ) do
|
||||
if PlayerData then -- This should normally not happen, but i'll test it anyway.
|
||||
trace.i( self.ClassName, "Something got killed" )
|
||||
self:T( "Something got killed" )
|
||||
|
||||
-- Some variables
|
||||
local InitUnitCoalition = DATABASECoalition[PlayerData.UnitCoalition]
|
||||
local InitUnitCategory = DATABASECategory[PlayerData.UnitCategory]
|
||||
local InitUnitType = PlayerData.UnitType
|
||||
local InitUnitName = PlayerData.UnitName
|
||||
local InitUnitType = PlayerData.UnitType
|
||||
local InitCoalition = PlayerData.UnitCoalition
|
||||
local InitCategory = PlayerData.UnitCategory
|
||||
local InitUnitCoalition = DATABASECoalition[InitCoalition]
|
||||
local InitUnitCategory = DATABASECategory[InitCategory]
|
||||
|
||||
self:T( { InitUnitName, InitUnitType, InitUnitCoalition, InitCoalition, InitUnitCategory, InitCategory } )
|
||||
|
||||
-- What is he hitting?
|
||||
if TargetCategory then
|
||||
@ -251,17 +272,17 @@ trace.f( self.ClassName, { event } )
|
||||
PlayerData.Kill[TargetCategory][TargetType].PenaltyKill = 0
|
||||
end
|
||||
|
||||
if PlayerData.UnitCoalition == TargetCoalition then
|
||||
if InitCoalition == TargetCoalition then
|
||||
PlayerData.Kill[TargetCategory][TargetType].Penalty = PlayerData.Kill[TargetCategory][TargetType].Penalty + 25
|
||||
PlayerData.Kill[TargetCategory][TargetType].PenaltyKill = PlayerData.Kill[TargetCategory][TargetType].PenaltyKill + 1
|
||||
MESSAGE:New( "Player '" .. PlayerName .. "' killed a target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
PlayerData.Kill[TargetCategory][TargetType].PenaltyKill .. " times. Score: " .. PlayerData.Kill[TargetCategory][TargetType].Penalty,
|
||||
"Game Status: Score", 20, "/PENALTY" .. PlayerName .. "/" .. InitUnitName ):ToAll()
|
||||
MESSAGE:New( "Player '" .. PlayerName .. "' killed a friendly " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
PlayerData.Kill[TargetCategory][TargetType].PenaltyKill .. " times. Penalty: -" .. PlayerData.Kill[TargetCategory][TargetType].Penalty,
|
||||
"Game Status: Penalty", 20, "/PENALTY" .. PlayerName .. "/" .. InitUnitName ):ToAll()
|
||||
self:ScoreAdd( PlayerName, "KILL_PENALTY", 1, -125, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
else
|
||||
PlayerData.Kill[TargetCategory][TargetType].Score = PlayerData.Kill[TargetCategory][TargetType].Score + 10
|
||||
PlayerData.Kill[TargetCategory][TargetType].ScoreKill = PlayerData.Kill[TargetCategory][TargetType].ScoreKill + 1
|
||||
MESSAGE:New( "Player '" .. PlayerName .. "' killed a target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
MESSAGE:New( "Player '" .. PlayerName .. "' killed an enemy " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
PlayerData.Kill[TargetCategory][TargetType].ScoreKill .. " times. Score: " .. PlayerData.Kill[TargetCategory][TargetType].Score,
|
||||
"Game Status: Score", 20, "/SCORE" .. PlayerName .. "/" .. InitUnitName ):ToAll()
|
||||
self:ScoreAdd( PlayerName, "KILL_SCORE", 1, 10, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
@ -272,12 +293,14 @@ trace.f( self.ClassName, { event } )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Scheduled
|
||||
-- @section Scheduled
|
||||
|
||||
|
||||
--- Follows new players entering Clients within the DCSRTE.
|
||||
function DATABASE:_FollowPlayers()
|
||||
trace.scheduled( self.ClassName, "_FollowPlayers" )
|
||||
self:T( "_FollowPlayers" )
|
||||
|
||||
local ClientUnit = 0
|
||||
local CoalitionsData = { AlivePlayersRed = coalition.getPlayers(coalition.side.RED), AlivePlayersBlue = coalition.getPlayers(coalition.side.BLUE) }
|
||||
@ -286,73 +309,73 @@ trace.scheduled( self.ClassName, "_FollowPlayers" )
|
||||
local AlivePlayerUnits = {}
|
||||
|
||||
for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
|
||||
trace.l( self.ClassName, "_FollowPlayers", CoalitionData )
|
||||
self:T( { "_FollowPlayers", CoalitionData } )
|
||||
for UnitId, UnitData in pairs( CoalitionData ) do
|
||||
self:_AddPlayerFromUnit( UnitData )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Private
|
||||
-- @section Private
|
||||
|
||||
|
||||
--- Add a new player entering a Unit.
|
||||
function DATABASE:_AddPlayerFromUnit( UnitData )
|
||||
trace.f( self.ClassName, UnitData )
|
||||
self:T( UnitData )
|
||||
|
||||
if UnitData:isExist() then
|
||||
local UnitName = UnitData:getName()
|
||||
local GroupData = UnitData:getGroup()
|
||||
local PlayerName = UnitData:getPlayerName()
|
||||
local UnitDesc = UnitData:getDesc()
|
||||
local UnitCategory = UnitDesc.category
|
||||
local UnitCoalition = UnitData:getCoalition()
|
||||
local UnitTypeName = UnitData:getTypeName()
|
||||
|
||||
if GroupData and GroupData:isExist() then
|
||||
local GroupName = GroupData:getName()
|
||||
local PlayerName = UnitData:getPlayerName()
|
||||
self:T( { PlayerName, UnitName, UnitCategory, UnitCoalition, UnitTypeName } )
|
||||
|
||||
trace.i(self.ClassName, "Player : " .. PlayerName .. " Unit : " .. UnitName .. " Group : " .. GroupName )
|
||||
|
||||
if self.Players[PlayerName] == nil then -- I believe this is the place where a Player gets a life in a mission when he enters a unit ...
|
||||
self.Players[PlayerName] = {}
|
||||
self.Players[PlayerName].Hit = {}
|
||||
self.Players[PlayerName].Kill = {}
|
||||
self.Players[PlayerName].Mission = {}
|
||||
|
||||
-- for CategoryID, CategoryName in pairs( DATABASECategory ) do
|
||||
-- self.Players[PlayerName].Hit[CategoryID] = {}
|
||||
-- self.Players[PlayerName].Kill[CategoryID] = {}
|
||||
-- end
|
||||
self.Players[PlayerName].HitPlayers = {}
|
||||
self.Players[PlayerName].HitUnits = {}
|
||||
self.Players[PlayerName].Penalty = 0
|
||||
self.Players[PlayerName].PenaltyCoalition = 0
|
||||
end
|
||||
|
||||
if not self.Players[PlayerName].UnitCoalition then
|
||||
self.Players[PlayerName].UnitCoalition = Unit.getGroup(UnitData):getCoalition()
|
||||
else
|
||||
if self.Players[PlayerName].UnitCoalition ~= Unit.getGroup(UnitData):getCoalition() then
|
||||
self.Players[PlayerName].Penalty = self.Players[PlayerName].Penalty + 50
|
||||
self.Players[PlayerName].PenaltyCoalition = self.Players[PlayerName].PenaltyCoalition + 1
|
||||
MESSAGE:New( "Player '" .. PlayerName .. "' changed coalition from " .. DATABASECoalition[self.Players[PlayerName].UnitCoalition] .. " to " .. DATABASECoalition[Unit.getGroup(UnitData):getCoalition()] ..
|
||||
"(changed " .. self.Players[PlayerName].PenaltyCoalition .. " times the coalition). 50 Penalty points added.",
|
||||
"Game Status: Penalty", 20, "/PENALTYCOALITION" .. PlayerName ):ToAll()
|
||||
self:ScoreAdd( PlayerName, "COALITION_PENALTY", 1, -50, self.Players[PlayerName].UnitName, DATABASECoalition[self.Players[PlayerName].UnitCoalition], DATABASECategory[self.Players[PlayerName].UnitCategory], self.Players[PlayerName].UnitType,
|
||||
UnitName, DATABASECategory[Unit.getGroup(UnitData):getCoalition()], DATABASECategory[Unit.getGroup(UnitData):getCategory()], UnitData:getTypeName() )
|
||||
end
|
||||
end
|
||||
self.Players[PlayerName].UnitName = UnitName
|
||||
self.Players[PlayerName].GroupName = GroupName
|
||||
|
||||
self.Players[PlayerName].UnitCoalition = Unit.getGroup(UnitData):getCoalition()
|
||||
self.Players[PlayerName].UnitCategory = Unit.getGroup(UnitData):getCategory()
|
||||
self.Players[PlayerName].UnitType = UnitData:getTypeName()
|
||||
if self.Players[PlayerName] == nil then -- I believe this is the place where a Player gets a life in a mission when he enters a unit ...
|
||||
self.Players[PlayerName] = {}
|
||||
self.Players[PlayerName].Hit = {}
|
||||
self.Players[PlayerName].Kill = {}
|
||||
self.Players[PlayerName].Mission = {}
|
||||
|
||||
-- for CategoryID, CategoryName in pairs( DATABASECategory ) do
|
||||
-- self.Players[PlayerName].Hit[CategoryID] = {}
|
||||
-- self.Players[PlayerName].Kill[CategoryID] = {}
|
||||
-- end
|
||||
self.Players[PlayerName].HitPlayers = {}
|
||||
self.Players[PlayerName].HitUnits = {}
|
||||
self.Players[PlayerName].Penalty = 0
|
||||
self.Players[PlayerName].PenaltyCoalition = 0
|
||||
end
|
||||
|
||||
if not self.Players[PlayerName].UnitCoalition then
|
||||
self.Players[PlayerName].UnitCoalition = UnitCoalition
|
||||
else
|
||||
if self.Players[PlayerName].UnitCoalition ~= UnitCoalition then
|
||||
self.Players[PlayerName].Penalty = self.Players[PlayerName].Penalty + 50
|
||||
self.Players[PlayerName].PenaltyCoalition = self.Players[PlayerName].PenaltyCoalition + 1
|
||||
MESSAGE:New( "Player '" .. PlayerName .. "' changed coalition from " .. DATABASECoalition[self.Players[PlayerName].UnitCoalition] .. " to " .. DATABASECoalition[UnitCoalition] ..
|
||||
"(changed " .. self.Players[PlayerName].PenaltyCoalition .. " times the coalition). 50 Penalty points added.",
|
||||
"Game Status: Penalty", 20, "/PENALTYCOALITION" .. PlayerName ):ToAll()
|
||||
self:ScoreAdd( PlayerName, "COALITION_PENALTY", 1, -50, self.Players[PlayerName].UnitName, DATABASECoalition[self.Players[PlayerName].UnitCoalition], DATABASECategory[self.Players[PlayerName].UnitCategory], self.Players[PlayerName].UnitType,
|
||||
UnitName, DATABASECoalition[UnitCoalition], DATABASECategory[UnitCategory], UnitData:getTypeName() )
|
||||
end
|
||||
end
|
||||
self.Players[PlayerName].UnitName = UnitName
|
||||
self.Players[PlayerName].UnitCoalition = UnitCoalition
|
||||
self.Players[PlayerName].UnitCategory = UnitCategory
|
||||
self.Players[PlayerName].UnitType = UnitTypeName
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Registers Scores the players completing a Mission Task.
|
||||
function DATABASE:_AddMissionTaskScore( PlayerUnit, MissionName, Score )
|
||||
trace.f( self.ClassName, { PlayerUnit, MissionName, Score } )
|
||||
self:T( { PlayerUnit, MissionName, Score } )
|
||||
|
||||
local PlayerName = PlayerUnit:getPlayerName()
|
||||
|
||||
@ -361,6 +384,9 @@ trace.f( self.ClassName, { PlayerUnit, MissionName, Score } )
|
||||
self.Players[PlayerName].Mission[MissionName].ScoreTask = 0
|
||||
self.Players[PlayerName].Mission[MissionName].ScoreMission = 0
|
||||
end
|
||||
|
||||
self:T( PlayerName )
|
||||
self:T( self.Players[PlayerName].Mission[MissionName] )
|
||||
|
||||
self.Players[PlayerName].Mission[MissionName].ScoreTask = self.Players[PlayerName].Mission[MissionName].ScoreTask + Score
|
||||
|
||||
@ -374,7 +400,7 @@ end
|
||||
|
||||
--- Registers Mission Scores for possible multiple players that contributed in the Mission.
|
||||
function DATABASE:_AddMissionScore( MissionName, Score )
|
||||
trace.f( self.ClassName, { PlayerUnit, MissionName, Score } )
|
||||
self:T( { PlayerUnit, MissionName, Score } )
|
||||
|
||||
for PlayerName, PlayerData in pairs( self.Players ) do
|
||||
|
||||
@ -388,15 +414,18 @@ trace.f( self.ClassName, { PlayerUnit, MissionName, Score } )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Events
|
||||
-- @section Events
|
||||
|
||||
function DATABASE:OnHit( event )
|
||||
trace.f( self.ClassName, { event } )
|
||||
|
||||
local InitUnitName = nil
|
||||
local InitGroupName = nil
|
||||
local InitPlayerName = nil
|
||||
function DATABASE:OnHit( event )
|
||||
self:T( { event } )
|
||||
|
||||
local InitUnit = nil
|
||||
local InitUnitName = ""
|
||||
local InitGroupName = ""
|
||||
local InitPlayerName = "dummy"
|
||||
|
||||
local InitCoalition = nil
|
||||
local InitCategory = nil
|
||||
@ -405,9 +434,10 @@ trace.f( self.ClassName, { event } )
|
||||
local InitUnitCategory = nil
|
||||
local InitUnitType = nil
|
||||
|
||||
local TargetUnitName = nil
|
||||
local TargetGroupName = nil
|
||||
local TargetPlayerName = nil
|
||||
local TargetUnit = nil
|
||||
local TargetUnitName = ""
|
||||
local TargetGroupName = ""
|
||||
local TargetPlayerName = ""
|
||||
|
||||
local TargetCoalition = nil
|
||||
local TargetCategory = nil
|
||||
@ -419,49 +449,65 @@ trace.f( self.ClassName, { event } )
|
||||
if event.initiator and event.initiator:getName() then
|
||||
|
||||
if event.initiator and Object.getCategory(event.initiator) == Object.Category.UNIT then
|
||||
|
||||
InitUnit = event.initiator
|
||||
InitGroup = Unit.getGroup( InitUnit )
|
||||
InitUnitDesc = InitUnit:getDesc()
|
||||
|
||||
InitUnitName = event.initiator:getName()
|
||||
InitGroupName = Unit.getGroup(event.initiator):getName()
|
||||
InitPlayerName = event.initiator:getPlayerName()
|
||||
InitUnitName = InitUnit:getName()
|
||||
if InitGroup and InitGroup:isExist() then
|
||||
InitGroupName = InitGroup:getName()
|
||||
end
|
||||
InitPlayerName = InitUnit:getPlayerName()
|
||||
|
||||
InitCoalition = Unit.getGroup(event.initiator):getCoalition()
|
||||
InitCategory = Unit.getGroup(event.initiator):getCategory()
|
||||
InitType = event.initiator:getTypeName()
|
||||
InitCoalition = InitUnit:getCoalition()
|
||||
--InitCategory = InitUnit:getCategory()
|
||||
InitCategory = InitUnitDesc.category -- Workaround
|
||||
InitType = InitUnit:getTypeName()
|
||||
|
||||
InitUnitCoalition = DATABASECoalition[InitCoalition]
|
||||
InitUnitCategory = DATABASECategory[InitCategory]
|
||||
InitUnitType = InitType
|
||||
|
||||
trace.i( self.ClassName, { InitUnitName, InitGroupName, InitPlayerName, InitCoalition, InitCategory, InitType , InitUnitCoalition, InitUnitCategory, InitUnitType } )
|
||||
self:T( { InitUnitName, InitGroupName, InitPlayerName, InitCoalition, InitCategory, InitType , InitUnitCoalition, InitUnitCategory, InitUnitType } )
|
||||
self:T( { InitUnitDesc } )
|
||||
end
|
||||
|
||||
|
||||
if event.target and Object.getCategory(event.target) == Object.Category.UNIT then
|
||||
|
||||
TargetUnit = event.target
|
||||
TargetGroup = Unit.getGroup( TargetUnit )
|
||||
TargetUnitDesc = TargetUnit:getDesc()
|
||||
|
||||
TargetUnitName = event.target:getName()
|
||||
TargetGroupName = Unit.getGroup(event.target):getName()
|
||||
TargetPlayerName = event.target:getPlayerName()
|
||||
TargetUnitName = TargetUnit:getName()
|
||||
if TargetGroup and TargetGroup:isExist() then
|
||||
TargetGroupName = TargetGroup:getName()
|
||||
end
|
||||
TargetPlayerName = TargetUnit:getPlayerName()
|
||||
|
||||
TargetCoalition = Unit.getGroup(event.target):getCoalition()
|
||||
TargetCategory = Unit.getGroup(event.target):getCategory()
|
||||
TargetType = event.target:getTypeName()
|
||||
TargetCoalition = TargetUnit:getCoalition()
|
||||
--TargetCategory = TargetUnit:getCategory()
|
||||
TargetCategory = TargetUnitDesc.category -- Workaround
|
||||
TargetType = TargetUnit:getTypeName()
|
||||
|
||||
TargetUnitCoalition = DATABASECoalition[TargetCoalition]
|
||||
TargetUnitCategory = DATABASECategory[TargetCategory]
|
||||
TargetUnitType = TargetType
|
||||
|
||||
trace.i( self.ClassName, { TargetUnitName, TargetGroupName, TargetPlayerName, TargetCoalition, TargetCategory, TargetType, TargetUnitCoalition, TargetUnitCategory, TargetUnitType } )
|
||||
self:T( { TargetUnitName, TargetGroupName, TargetPlayerName, TargetCoalition, TargetCategory, TargetType, TargetUnitCoalition, TargetUnitCategory, TargetUnitType } )
|
||||
self:T( { TargetUnitDesc } )
|
||||
end
|
||||
|
||||
if InitPlayerName ~= nil then -- It is a player that is hitting something
|
||||
self:_AddPlayerFromUnit( event.initiator )
|
||||
self:_AddPlayerFromUnit( InitUnit )
|
||||
if self.Players[InitPlayerName] then -- This should normally not happen, but i'll test it anyway.
|
||||
if TargetPlayerName ~= nil then -- It is a player hitting another player ...
|
||||
self:_AddPlayerFromUnit( event.target )
|
||||
self:_AddPlayerFromUnit( TargetUnit )
|
||||
self.Players[InitPlayerName].HitPlayers = self.Players[InitPlayerName].HitPlayers + 1
|
||||
end
|
||||
|
||||
trace.i( self.ClassName, "Hitting Something" )
|
||||
self:T( "Hitting Something" )
|
||||
-- What is he hitting?
|
||||
if TargetCategory then
|
||||
if not self.Players[InitPlayerName].Hit[TargetCategory] then
|
||||
@ -479,7 +525,7 @@ trace.f( self.ClassName, { event } )
|
||||
self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].Penalty = self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].Penalty + 10
|
||||
self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].PenaltyHit = self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].PenaltyHit + 1
|
||||
MESSAGE:New( "Player '" .. InitPlayerName .. "' hit a friendly " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].PenaltyHit .. " times. Penalty: " .. self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].Penalty,
|
||||
self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].PenaltyHit .. " times. Penalty: -" .. self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].Penalty,
|
||||
"Game Status: Penalty", 20, "/PENALTY" .. InitPlayerName .. "/" .. InitUnitName ):ToAll()
|
||||
self:ScoreAdd( InitPlayerName, "HIT_PENALTY", 1, -25, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
else
|
||||
@ -498,14 +544,132 @@ trace.f( self.ClassName, { event } )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function DATABASE:ReportScoreAll()
|
||||
|
||||
env.info( "Hello World " )
|
||||
|
||||
local ScoreMessage = ""
|
||||
local PlayerMessage = ""
|
||||
|
||||
self:T( "Score Report" )
|
||||
|
||||
for PlayerName, PlayerData in pairs( self.Players ) do
|
||||
if PlayerData then -- This should normally not happen, but i'll test it anyway.
|
||||
trace.i( self.ClassName, "Score" )
|
||||
self:T( "Score Player: " .. PlayerName )
|
||||
|
||||
-- Some variables
|
||||
local InitUnitCoalition = DATABASECoalition[PlayerData.UnitCoalition]
|
||||
local InitUnitCategory = DATABASECategory[PlayerData.UnitCategory]
|
||||
local InitUnitType = PlayerData.UnitType
|
||||
local InitUnitName = PlayerData.UnitName
|
||||
|
||||
local PlayerScore = 0
|
||||
local PlayerPenalty = 0
|
||||
|
||||
ScoreMessage = ":\n"
|
||||
|
||||
local ScoreMessageHits = ""
|
||||
|
||||
for CategoryID, CategoryName in pairs( DATABASECategory ) do
|
||||
self:T( CategoryName )
|
||||
if PlayerData.Hit[CategoryID] then
|
||||
local Score = 0
|
||||
local ScoreHit = 0
|
||||
local Penalty = 0
|
||||
local PenaltyHit = 0
|
||||
self:T( "Hit scores exist for player " .. PlayerName )
|
||||
for UnitName, UnitData in pairs( PlayerData.Hit[CategoryID] ) do
|
||||
Score = Score + UnitData.Score
|
||||
ScoreHit = ScoreHit + UnitData.ScoreHit
|
||||
Penalty = Penalty + UnitData.Penalty
|
||||
PenaltyHit = UnitData.PenaltyHit
|
||||
end
|
||||
local ScoreMessageHit = string.format( "%s:%d ", CategoryName, Score - Penalty )
|
||||
self:T( ScoreMessageHit )
|
||||
ScoreMessageHits = ScoreMessageHits .. ScoreMessageHit
|
||||
PlayerScore = PlayerScore + Score
|
||||
PlayerPenalty = PlayerPenalty + Penalty
|
||||
else
|
||||
--ScoreMessageHits = ScoreMessageHits .. string.format( "%s:%d ", string.format(CategoryName, 1, 1), 0 )
|
||||
end
|
||||
end
|
||||
if ScoreMessageHits ~= "" then
|
||||
ScoreMessage = ScoreMessage .. " Hits: " .. ScoreMessageHits .. "\n"
|
||||
end
|
||||
|
||||
local ScoreMessageKills = ""
|
||||
for CategoryID, CategoryName in pairs( DATABASECategory ) do
|
||||
self:T( "Kill scores exist for player " .. PlayerName )
|
||||
if PlayerData.Kill[CategoryID] then
|
||||
local Score = 0
|
||||
local ScoreKill = 0
|
||||
local Penalty = 0
|
||||
local PenaltyKill = 0
|
||||
|
||||
for UnitName, UnitData in pairs( PlayerData.Kill[CategoryID] ) do
|
||||
Score = Score + UnitData.Score
|
||||
ScoreKill = ScoreKill + UnitData.ScoreKill
|
||||
Penalty = Penalty + UnitData.Penalty
|
||||
PenaltyKill = PenaltyKill + UnitData.PenaltyKill
|
||||
end
|
||||
|
||||
local ScoreMessageKill = string.format( " %s:%d ", CategoryName, Score - Penalty )
|
||||
self:T( ScoreMessageKill )
|
||||
ScoreMessageKills = ScoreMessageKills .. ScoreMessageKill
|
||||
|
||||
PlayerScore = PlayerScore + Score
|
||||
PlayerPenalty = PlayerPenalty + Penalty
|
||||
else
|
||||
--ScoreMessageKills = ScoreMessageKills .. string.format( "%s:%d ", string.format(CategoryName, 1, 1), 0 )
|
||||
end
|
||||
end
|
||||
if ScoreMessageKills ~= "" then
|
||||
ScoreMessage = ScoreMessage .. " Kills: " .. ScoreMessageKills .. "\n"
|
||||
end
|
||||
|
||||
local ScoreMessageCoalitionChangePenalties = ""
|
||||
if PlayerData.PenaltyCoalition ~= 0 then
|
||||
ScoreMessageCoalitionChangePenalties = ScoreMessageCoalitionChangePenalties .. string.format( " -%d (%d changed)", PlayerData.Penalty, PlayerData.PenaltyCoalition )
|
||||
PlayerPenalty = PlayerPenalty + PlayerData.Penalty
|
||||
end
|
||||
if ScoreMessageCoalitionChangePenalties ~= "" then
|
||||
ScoreMessage = ScoreMessage .. " Coalition Penalties: " .. ScoreMessageCoalitionChangePenalties .. "\n"
|
||||
end
|
||||
|
||||
local ScoreMessageMission = ""
|
||||
local ScoreMission = 0
|
||||
local ScoreTask = 0
|
||||
for MissionName, MissionData in pairs( PlayerData.Mission ) do
|
||||
ScoreMission = ScoreMission + MissionData.ScoreMission
|
||||
ScoreTask = ScoreTask + MissionData.ScoreTask
|
||||
ScoreMessageMission = ScoreMessageMission .. "'" .. MissionName .. "'; "
|
||||
end
|
||||
PlayerScore = PlayerScore + ScoreMission + ScoreTask
|
||||
|
||||
if ScoreMessageMission ~= "" then
|
||||
ScoreMessage = ScoreMessage .. " Tasks: " .. ScoreTask .. " Mission: " .. ScoreMission .. " ( " .. ScoreMessageMission .. ")\n"
|
||||
end
|
||||
|
||||
PlayerMessage = PlayerMessage .. string.format( "Player '%s' Score:%d (%d Score -%d Penalties)%s", PlayerName, PlayerScore - PlayerPenalty, PlayerScore, PlayerPenalty, ScoreMessage )
|
||||
end
|
||||
end
|
||||
MESSAGE:New( PlayerMessage, "Player Scores", 30, "AllPlayerScores"):ToAll()
|
||||
end
|
||||
|
||||
|
||||
function DATABASE:ReportScorePlayer()
|
||||
|
||||
env.info( "Hello World " )
|
||||
|
||||
local ScoreMessage = ""
|
||||
local PlayerMessage = ""
|
||||
|
||||
self:T( "Score Report" )
|
||||
|
||||
for PlayerName, PlayerData in pairs( self.Players ) do
|
||||
if PlayerData then -- This should normally not happen, but i'll test it anyway.
|
||||
self:T( "Score Player: " .. PlayerName )
|
||||
|
||||
-- Some variables
|
||||
local InitUnitCoalition = DATABASECoalition[PlayerData.UnitCoalition]
|
||||
@ -521,18 +685,22 @@ function DATABASE:ReportScoreAll()
|
||||
local ScoreMessageHits = ""
|
||||
|
||||
for CategoryID, CategoryName in pairs( DATABASECategory ) do
|
||||
self:T( CategoryName )
|
||||
if PlayerData.Hit[CategoryID] then
|
||||
local Score = 0
|
||||
local ScoreHit = 0
|
||||
local Penalty = 0
|
||||
local PenaltyHit = 0
|
||||
self:T( "Hit scores exist for player " .. PlayerName )
|
||||
for UnitName, UnitData in pairs( PlayerData.Hit[CategoryID] ) do
|
||||
Score = Score + UnitData.Score
|
||||
ScoreHit = ScoreHit + UnitData.ScoreHit
|
||||
Penalty = Penalty + UnitData.Penalty
|
||||
PenaltyHit = UnitData.PenaltyHit
|
||||
end
|
||||
ScoreMessageHits = ScoreMessageHits .. string.format( " %s = %d score(%d;-%d) hits(#%d;#-%d)", CategoryName, Score - Penalty, Score, Penalty, ScoreHit, PenaltyHit )
|
||||
local ScoreMessageHit = string.format( "\n %s = %d score(%d;-%d) hits(#%d;#-%d)", CategoryName, Score - Penalty, Score, Penalty, ScoreHit, PenaltyHit )
|
||||
self:T( ScoreMessageHit )
|
||||
ScoreMessageHits = ScoreMessageHits .. ScoreMessageHit
|
||||
PlayerScore = PlayerScore + Score
|
||||
PlayerPenalty = PlayerPenalty + Penalty
|
||||
else
|
||||
@ -540,11 +708,12 @@ function DATABASE:ReportScoreAll()
|
||||
end
|
||||
end
|
||||
if ScoreMessageHits ~= "" then
|
||||
ScoreMessage = ScoreMessage .. " Hits: " .. ScoreMessageHits .. " "
|
||||
ScoreMessage = ScoreMessage .. "\n Hits: " .. ScoreMessageHits .. " "
|
||||
end
|
||||
|
||||
local ScoreMessageKills = ""
|
||||
for CategoryID, CategoryName in pairs( DATABASECategory ) do
|
||||
self:T( "Kill scores exist for player " .. PlayerName )
|
||||
if PlayerData.Kill[CategoryID] then
|
||||
local Score = 0
|
||||
local ScoreKill = 0
|
||||
@ -557,8 +726,10 @@ function DATABASE:ReportScoreAll()
|
||||
Penalty = Penalty + UnitData.Penalty
|
||||
PenaltyKill = PenaltyKill + UnitData.PenaltyKill
|
||||
end
|
||||
|
||||
ScoreMessageKills = ScoreMessageKills .. string.format( " %s = %d score(%d;-%d) hits(#%d;#-%d)", CategoryName, Score - Penalty, Score, Penalty, ScoreKill, PenaltyKill )
|
||||
|
||||
local ScoreMessageKill = string.format( "\n %s = %d score(%d;-%d) hits(#%d;#-%d)", CategoryName, Score - Penalty, Score, Penalty, ScoreKill, PenaltyKill )
|
||||
self:T( ScoreMessageKill )
|
||||
ScoreMessageKills = ScoreMessageKills .. ScoreMessageKill
|
||||
|
||||
PlayerScore = PlayerScore + Score
|
||||
PlayerPenalty = PlayerPenalty + Penalty
|
||||
@ -567,16 +738,16 @@ function DATABASE:ReportScoreAll()
|
||||
end
|
||||
end
|
||||
if ScoreMessageKills ~= "" then
|
||||
ScoreMessage = ScoreMessage .. " Kills: " .. ScoreMessageKills .. " "
|
||||
ScoreMessage = ScoreMessage .. "\n Kills: " .. ScoreMessageKills .. " "
|
||||
end
|
||||
|
||||
local ScoreMessageCoalitionChangePenalties = ""
|
||||
if PlayerData.PenaltyCoalition ~= 0 then
|
||||
ScoreMessageCoalitionChangePenalties = ScoreMessageCoalitionChangePenalties .. string.format( "-%d (%d changed)", PlayerData.Penalty, PlayerData.PenaltyCoalition )
|
||||
ScoreMessageCoalitionChangePenalties = ScoreMessageCoalitionChangePenalties .. string.format( " -%d (%d changed)", PlayerData.Penalty, PlayerData.PenaltyCoalition )
|
||||
PlayerPenalty = PlayerPenalty + PlayerData.Penalty
|
||||
end
|
||||
if ScoreMessageCoalitionChangePenalties ~= "" then
|
||||
ScoreMessage = ScoreMessage .. " Coalition: " .. ScoreMessageCoalitionChangePenalties .. " "
|
||||
ScoreMessage = ScoreMessage .. "\n Coalition: " .. ScoreMessageCoalitionChangePenalties .. " "
|
||||
end
|
||||
|
||||
local ScoreMessageMission = ""
|
||||
@ -590,26 +761,26 @@ function DATABASE:ReportScoreAll()
|
||||
PlayerScore = PlayerScore + ScoreMission + ScoreTask
|
||||
|
||||
if ScoreMessageMission ~= "" then
|
||||
ScoreMessage = ScoreMessage .. " Tasks: " .. ScoreTask .. " Mission: " .. ScoreMission .. " ( " .. ScoreMessageMission .. ") "
|
||||
ScoreMessage = ScoreMessage .. "\n Tasks: " .. ScoreTask .. " Mission: " .. ScoreMission .. " ( " .. ScoreMessageMission .. ") "
|
||||
end
|
||||
|
||||
PlayerMessage = string.format( " Player '%s' Score = %d ( %d Score, -%d Penalties ):", PlayerName, PlayerScore - PlayerPenalty, PlayerScore, PlayerPenalty )
|
||||
MESSAGE:New( PlayerMessage .. ScoreMessage, "Player Scores", 30, "/SCORE/" .. PlayerName ):ToAll()
|
||||
PlayerMessage = PlayerMessage .. string.format( "Player '%s' Score = %d ( %d Score, -%d Penalties ):%s", PlayerName, PlayerScore - PlayerPenalty, PlayerScore, PlayerPenalty, ScoreMessage )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DATABASE:ReportScorePlayer()
|
||||
|
||||
MESSAGE:New( PlayerMessage, "Player Scores", 30, "AllPlayerScores"):ToAll()
|
||||
|
||||
end
|
||||
|
||||
|
||||
function DATABASE:ScoreMenu()
|
||||
local ReportScore = SUBMENU:New( 'Scoring' )
|
||||
local ReportAllScores = COMMANDMENU:New( 'Score All Active Players', ReportScore, DATABASE.ReportScoreAll, self )
|
||||
local ReportPlayerScores = COMMANDMENU:New('Your Current Score', ReportScore, DATABASE.ReportScorePlayer, self )
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
-- File Logic for tracking the scores
|
||||
|
||||
function DATABASE:SecondsToClock(sSeconds)
|
||||
@ -625,6 +796,7 @@ local nSeconds = sSeconds
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function DATABASE:ScoreOpen()
|
||||
if lfs then
|
||||
local fdir = lfs.writedir() .. [[Logs\]] .. "Player_Scores_" .. os.date( "%Y-%m-%d_%H-%M-%S" ) .. ".csv"
|
||||
@ -632,12 +804,13 @@ function DATABASE:ScoreOpen()
|
||||
if not self.StatFile then
|
||||
error( "Error: Cannot open 'Player Scores.csv' file in " .. lfs.writedir() )
|
||||
end
|
||||
self.StatFile:write( '"Run-ID";Time;"PlayerName";"ScoreType";"PlayerUnitCoaltion";"PlayerUnitCategory";"PlayerUnitType"; "PlayerUnitName";"TargetUnitCoalition";"TargetUnitCategory";"TargetUnitType";"TargetUnitName";Times;Score\n' )
|
||||
self.StatFile:write( '"RunID";"Time";"PlayerName";"ScoreType";"PlayerUnitCoaltion";"PlayerUnitCategory";"PlayerUnitType";"PlayerUnitName";"TargetUnitCoalition";"TargetUnitCategory";"TargetUnitType";"TargetUnitName";"Times";"Score"\n' )
|
||||
|
||||
self.RunID = os.date("%y-%m-%d_%H-%M-%S")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function DATABASE:ScoreAdd( PlayerName, ScoreType, ScoreTimes, ScoreAmount, PlayerUnitName, PlayerUnitCoalition, PlayerUnitCategory, PlayerUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
--write statistic information to file
|
||||
local ScoreTime = self:SecondsToClock(timer.getTime())
|
||||
@ -648,11 +821,12 @@ function DATABASE:ScoreAdd( PlayerName, ScoreType, ScoreTimes, ScoreAmount, Play
|
||||
|
||||
if PlayerUnit then
|
||||
if not PlayerUnitCategory then
|
||||
PlayerUnitCategory = DATABASECategory[Unit.getGroup(PlayerUnit):getCategory()]
|
||||
--PlayerUnitCategory = DATABASECategory[PlayerUnit:getCategory()]
|
||||
PlayerUnitCategory = DATABASECategory[PlayerUnit:getDesc().category]
|
||||
end
|
||||
|
||||
if not PlayerUnitCoalition then
|
||||
PlayerUnitCoalition = DATABASECoalition[Unit.getGroup(PlayerUnit):getCoalition()]
|
||||
PlayerUnitCoalition = DATABASECoalition[PlayerUnit:getCoalition()]
|
||||
end
|
||||
|
||||
if not PlayerUnitType then
|
||||
@ -695,6 +869,7 @@ function DATABASE:ScoreAdd( PlayerName, ScoreType, ScoreTimes, ScoreAmount, Play
|
||||
self.StatFile:write( "\n" )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function LogClose()
|
||||
if lfs then
|
||||
|
||||
@ -13,39 +13,64 @@ DEPLOYTASK = {
|
||||
--- Creates a new DEPLOYTASK object, which models the sequence of STAGEs to unload a cargo.
|
||||
-- @tparam table{string,...}|string LandingZones Table or name of the zone(s) where Cargo is to be unloaded.
|
||||
-- @tparam CARGO_TYPE CargoType Type of the Cargo.
|
||||
function DEPLOYTASK:New( LandingZones, CargoType )
|
||||
trace.f(self.ClassName)
|
||||
function DEPLOYTASK:New( CargoType )
|
||||
local self = BASE:Inherit( self, TASK:New() )
|
||||
self:T()
|
||||
|
||||
-- Child holds the inherited instance of the DEPLOYTASK Class to the BASE class.
|
||||
local Child = BASE:Inherit( self, TASK:New() )
|
||||
|
||||
local Valid = true
|
||||
|
||||
Valid = routines.ValidateZone( LandingZones, "LandingZones", Valid )
|
||||
Valid = routines.ValidateEnumeration( CargoType, "CargoType", CARGO_TYPE, Valid )
|
||||
|
||||
if Valid then
|
||||
Child.Name = 'Deploy Cargo'
|
||||
Child.TaskBriefing = "Fly to one of the indicated landing zones and deploy " .. CargoType.TEXT .. ". Your co-pilot will provide you with the directions (required flight angle in degrees) and the distance (in km) to the deployment zone."
|
||||
if type( LandingZones ) == "table" then
|
||||
Child.LandingZones = LandingZones
|
||||
else
|
||||
Child.LandingZones = { LandingZones }
|
||||
end
|
||||
Child.CargoType = CargoType
|
||||
Child.GoalVerb = CargoType.TEXT .. " " .. self.GoalVerb
|
||||
Child.Stages = { STAGEBRIEF:New(), STAGESTART:New(), STAGEROUTE:New(), STAGELANDING:New(), STAGELANDED:New(), STAGEUNLOAD:New(), STAGEDONE:New() }
|
||||
Child.SetStage( Child, 1 )
|
||||
self.Name = 'Deploy Cargo'
|
||||
self.TaskBriefing = "Fly to one of the indicated landing zones and deploy " .. CargoType .. ". Your co-pilot will provide you with the directions (required flight angle in degrees) and the distance (in km) to the deployment zone."
|
||||
self.CargoType = CargoType
|
||||
self.GoalVerb = CargoType .. " " .. self.GoalVerb
|
||||
self.Stages = { STAGE_CARGO_INIT:New(), STAGE_CARGO_LOAD:New(), STAGEBRIEF:New(), STAGESTART:New(), STAGEROUTE:New(), STAGELANDING:New(), STAGELANDED:New(), STAGEUNLOAD:New(), STAGEDONE:New() }
|
||||
self.SetStage( self, 1 )
|
||||
end
|
||||
|
||||
return Child
|
||||
return self
|
||||
end
|
||||
|
||||
function DEPLOYTASK:ToZone( LandingZone )
|
||||
self:T()
|
||||
|
||||
self.LandingZones.LandingZoneNames[LandingZone.CargoZoneName] = LandingZone.CargoZoneName
|
||||
self.LandingZones.LandingZones[LandingZone.CargoZoneName] = LandingZone
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function DEPLOYTASK:InitCargo( InitCargos )
|
||||
self:T( { InitCargos } )
|
||||
|
||||
if type( InitCargos ) == "table" then
|
||||
self.Cargos.InitCargos = InitCargos
|
||||
else
|
||||
self.Cargos.InitCargos = { InitCargos }
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function DEPLOYTASK:LoadCargo( LoadCargos )
|
||||
self:T( { LoadCargos } )
|
||||
|
||||
if type( LoadCargos ) == "table" then
|
||||
self.Cargos.LoadCargos = LoadCargos
|
||||
else
|
||||
self.Cargos.LoadCargos = { LoadCargos }
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- When the cargo is unloaded, it will move to the target zone name.
|
||||
-- @tparam string TargetZoneName Name of the Zone to where the Cargo should move after unloading.
|
||||
function DEPLOYTASK:SetCargoTargetZoneName( TargetZoneName )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
local Valid = true
|
||||
|
||||
@ -60,57 +85,68 @@ trace.f(self.ClassName)
|
||||
end
|
||||
|
||||
function DEPLOYTASK:AddCargoMenus( Client, Cargos, TransportRadius )
|
||||
trace.f(self.ClassName, {Client, Cargos, TransportRadius})
|
||||
self:T()
|
||||
|
||||
for CargoID, CargoData in pairs( Client._Cargos ) do
|
||||
local ClientGroupID = Client:GetClientGroupID()
|
||||
|
||||
trace.i( self.ClassName, ClientGroupID )
|
||||
|
||||
for CargoID, Cargo in pairs( Cargos ) do
|
||||
|
||||
trace.i( self.ClassName, { CargoData.CargoName } )
|
||||
if Client._Menus[CargoData.CargoType] == nil then
|
||||
Client._Menus[CargoData.CargoType] = {}
|
||||
end
|
||||
trace.i( self.ClassName, { Cargo.ClassName, Cargo.CargoName, Cargo.CargoType, Cargo.CargoWeight } )
|
||||
|
||||
if not Client._Menus[CargoData.CargoType].DeployMenu then
|
||||
Client._Menus[CargoData.CargoType].DeployMenu = missionCommands.addSubMenuForGroup(
|
||||
Client:ClientGroup():getID(),
|
||||
self.TEXT[1],
|
||||
nil
|
||||
if Cargo:IsStatusLoaded() and Client == Cargo:IsLoadedInClient() then
|
||||
|
||||
if Client._Menus[Cargo.CargoType] == nil then
|
||||
Client._Menus[Cargo.CargoType] = {}
|
||||
end
|
||||
|
||||
if not Client._Menus[Cargo.CargoType].DeployMenu then
|
||||
Client._Menus[Cargo.CargoType].DeployMenu = missionCommands.addSubMenuForGroup(
|
||||
ClientGroupID,
|
||||
self.TEXT[1] .. " " .. Cargo.CargoType,
|
||||
nil
|
||||
)
|
||||
trace.i( self.ClassName, 'Added DeployMenu ' .. self.TEXT[1] )
|
||||
end
|
||||
|
||||
if Client._Menus[Cargo.CargoType].DeploySubMenus == nil then
|
||||
Client._Menus[Cargo.CargoType].DeploySubMenus = {}
|
||||
end
|
||||
|
||||
if Client._Menus[Cargo.CargoType].DeployMenu == nil then
|
||||
trace.i( self.ClassName, 'deploymenu is nil' )
|
||||
end
|
||||
|
||||
Client._Menus[Cargo.CargoType].DeploySubMenus[ #Client._Menus[Cargo.CargoType].DeploySubMenus + 1 ] = missionCommands.addCommandForGroup(
|
||||
ClientGroupID,
|
||||
Cargo.CargoName .. " ( " .. Cargo.CargoWeight .. "kg )",
|
||||
Client._Menus[Cargo.CargoType].DeployMenu,
|
||||
self.MenuAction,
|
||||
{ ReferenceTask = self, CargoTask = Cargo }
|
||||
)
|
||||
trace.i( self.ClassName, 'Added DeployMenu ' .. self.TEXT[1] )
|
||||
trace.i( self.ClassName, 'Added DeploySubMenu ' .. Cargo.CargoType .. ":" .. Cargo.CargoName .. " ( " .. Cargo.CargoWeight .. "kg )" )
|
||||
end
|
||||
|
||||
if Client._Menus[CargoData.CargoType].DeploySubMenus == nil then
|
||||
Client._Menus[CargoData.CargoType].DeploySubMenus = {}
|
||||
end
|
||||
|
||||
if Client._Menus[CargoData.CargoType].DeployMenu == nil then
|
||||
trace.i( self.ClassName, 'deploymenu is nil' )
|
||||
end
|
||||
|
||||
Client._Menus[CargoData.CargoType].DeploySubMenus[ #Client._Menus[CargoData.CargoType].DeploySubMenus + 1 ].MenuPath = missionCommands.addCommandForGroup(
|
||||
Client:ClientGroup():getID(),
|
||||
CargoData.CargoName .. " ( " .. CargoData.CargoWeight .. "kg )",
|
||||
Client._Menus[CargoData.CargoType].DeployMenu,
|
||||
self.MenuAction,
|
||||
{ ReferenceTask = self, CargoName = CargoData.CargoName }
|
||||
)
|
||||
trace.i( self.ClassName, 'Added DeploySubMenu ' .. CargoData.CargoType.TEXT .. ":" .. CargoData.CargoName .. " ( " .. CargoData.CargoWeight .. "kg )" )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function DEPLOYTASK:RemoveCargoMenus( Client )
|
||||
trace.f(self.ClassName, { Client } )
|
||||
self:T()
|
||||
|
||||
local ClientGroupID = Client:GetClientGroupID()
|
||||
trace.i( self.ClassName, ClientGroupID )
|
||||
|
||||
for MenuID, MenuData in pairs( Client._Menus ) do
|
||||
if MenuData.DeploySubMenus ~= nil then
|
||||
for SubMenuID, SubMenuData in pairs( MenuData.DeploySubMenus ) do
|
||||
missionCommands.removeItemForGroup( Client:ClientGroup():getID(), SubMenuData )
|
||||
missionCommands.removeItemForGroup( ClientGroupID, SubMenuData )
|
||||
trace.i( self.ClassName, "Removed DeploySubMenu " )
|
||||
SubMenuData = nil
|
||||
end
|
||||
end
|
||||
if MenuData.DeployMenu then
|
||||
missionCommands.removeItemForGroup( Client:ClientGroup():getID(), MenuData.DeployMenu )
|
||||
missionCommands.removeItemForGroup( ClientGroupID, MenuData.DeployMenu )
|
||||
trace.i( self.ClassName, "Removed DeployMenu " )
|
||||
MenuData.DeployMenu = nil
|
||||
end
|
||||
|
||||
@ -20,51 +20,52 @@ DESTROYBASETASK = {
|
||||
-- @tparam ?number DestroyPercentage defines the %-tage that needs to be destroyed to achieve mission success. eg. If in the Group there are 10 units, then a value of 75 would require 8 units to be destroyed from the Group to complete the @{TASK}.
|
||||
-- @treturn DESTROYBASETASK
|
||||
function DESTROYBASETASK:New( DestroyGroupType, DestroyUnitType, DestroyGroupPrefixes, DestroyPercentage )
|
||||
trace.f(self.ClassName)
|
||||
|
||||
-- Inheritance
|
||||
local Child = BASE:Inherit( self, TASK:New() )
|
||||
local self = BASE:Inherit( self, TASK:New() )
|
||||
self:T()
|
||||
|
||||
Child.Name = 'Destroy'
|
||||
Child.Destroyed = 0
|
||||
Child.DestroyGroupPrefixes = DestroyGroupPrefixes
|
||||
Child.DestroyGroupType = DestroyGroupType
|
||||
Child.DestroyUnitType = DestroyUnitType
|
||||
Child.TaskBriefing = "Task: Destroy " .. DestroyGroupType .. "."
|
||||
Child.Stages = { STAGEBRIEF:New(), STAGESTART:New(), STAGEGROUPSDESTROYED:New(), STAGEDONE:New() }
|
||||
Child.SetStage( Child, 1 )
|
||||
self.Name = 'Destroy'
|
||||
self.Destroyed = 0
|
||||
self.DestroyGroupPrefixes = DestroyGroupPrefixes
|
||||
self.DestroyGroupType = DestroyGroupType
|
||||
self.DestroyUnitType = DestroyUnitType
|
||||
self.TaskBriefing = "Task: Destroy " .. DestroyGroupType .. "."
|
||||
self.Stages = { STAGEBRIEF:New(), STAGESTART:New(), STAGEGROUPSDESTROYED:New(), STAGEDONE:New() }
|
||||
self.SetStage( self, 1 )
|
||||
|
||||
--Child.AddEvent( Child, world.event.S_EVENT_DEAD, Child.EventDead )
|
||||
--self.AddEvent( self, world.event.S_EVENT_DEAD, self.EventDead )
|
||||
|
||||
--env.info( 'New Table Child = ' .. tostring(Child) )
|
||||
--env.info( 'New Table self = ' .. tostring(self) )
|
||||
--env.info( 'New Table self = ' .. tostring(self) )
|
||||
|
||||
return Child
|
||||
return self
|
||||
end
|
||||
|
||||
--- Handle the S_EVENT_DEAD events to validate the destruction of units for the task monitoring.
|
||||
-- @param event Event structure of DCS world.
|
||||
function DESTROYBASETASK:EventDead( event )
|
||||
trace.f( self.ClassName, { 'EventDead', event } )
|
||||
self:T( { 'EventDead', event } )
|
||||
|
||||
if event.initiator then
|
||||
local DestroyGroup = Unit.getGroup( event.initiator )
|
||||
local DestroyGroupName = DestroyGroup:getName()
|
||||
if event.initiator and Object.getCategory(event.initiator) == Object.Category.UNIT then
|
||||
local DestroyUnit = event.initiator
|
||||
local DestroyUnitName = DestroyUnit:getName()
|
||||
local DestroyGroup = Unit.getGroup( DestroyUnit )
|
||||
local DestroyGroupName = ""
|
||||
if DestroyGroup and DestroyGroup:isExist() then
|
||||
local DestroyGroupName = DestroyGroup:getName()
|
||||
end
|
||||
local UnitsDestroyed = 0
|
||||
trace.i( self.ClassName, DestroyGroupName )
|
||||
trace.i( self.ClassName, DestroyUnitName )
|
||||
self:T( DestroyGroupName )
|
||||
self:T( DestroyUnitName )
|
||||
for DestroyGroupPrefixID, DestroyGroupPrefix in pairs( self.DestroyGroupPrefixes ) do
|
||||
trace.i( self.ClassName, DestroyGroupPrefix )
|
||||
self:T( DestroyGroupPrefix )
|
||||
if string.find( DestroyGroupName, DestroyGroupPrefix, 1, true ) then
|
||||
trace.i( self.ClassName, BASE:Inherited(self).ClassName )
|
||||
self:T( BASE:Inherited(self).ClassName )
|
||||
UnitsDestroyed = self:ReportGoalProgress( DestroyGroup, DestroyUnit )
|
||||
trace.i( self.ClassName, UnitsDestroyed )
|
||||
self:T( UnitsDestroyed )
|
||||
end
|
||||
end
|
||||
|
||||
trace.i( self.ClassName, { UnitsDestroyed } )
|
||||
self:T( { UnitsDestroyed } )
|
||||
self:IncreaseGoalCount( UnitsDestroyed, self.GoalVerb )
|
||||
end
|
||||
end
|
||||
@ -73,7 +74,7 @@ end
|
||||
-- @param DestroyGroup Group structure describing the group to be evaluated.
|
||||
-- @param DestroyUnit Unit structure describing the Unit to be evaluated.
|
||||
function DESTROYBASETASK:ReportGoalProgress( DestroyGroup, DestroyUnit )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
177
Moose/Group.lua
Normal file
177
Moose/Group.lua
Normal file
@ -0,0 +1,177 @@
|
||||
--- GROUP Classes
|
||||
-- @classmod GROUP
|
||||
|
||||
Include.File( "Routines" )
|
||||
Include.File( "Base" )
|
||||
Include.File( "Message" )
|
||||
Include.File( "Unit" )
|
||||
|
||||
GROUPS = {}
|
||||
|
||||
|
||||
GROUP = {
|
||||
ClassName="GROUP",
|
||||
}
|
||||
|
||||
function GROUP:New( _Group )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:T( _Group:getName() )
|
||||
|
||||
self._Group = _Group
|
||||
self.GroupName = _Group:getName()
|
||||
self.GroupID = _Group:getID()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function GROUP:NewFromName( GroupName )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:T( GroupName )
|
||||
|
||||
self._Group = Group.getByName( GroupName )
|
||||
self.GroupName = self._Group:getName()
|
||||
self.GroupID = self._Group:getID()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function GROUP:GetName()
|
||||
self:T( self.GroupName )
|
||||
|
||||
return self.GroupName
|
||||
end
|
||||
|
||||
|
||||
function GROUP:Destroy()
|
||||
self:T( self.GroupName )
|
||||
|
||||
for Index, UnitData in pairs( self._Group:getUnits() ) do
|
||||
self:CreateEventCrash( timer.getTime(), UnitData )
|
||||
end
|
||||
|
||||
self._Group:destroy()
|
||||
end
|
||||
|
||||
|
||||
function GROUP:GetUnit( UnitNumber )
|
||||
self:T( self.GroupName )
|
||||
return UNIT:New( self._Group:getUnit( UnitNumber ) )
|
||||
end
|
||||
|
||||
|
||||
function GROUP:IsAir()
|
||||
self:T()
|
||||
|
||||
local IsAirResult = self._Group:getCategory() == Group.Category.AIRPLANE or self._Group:getCategory() == Group.Category.HELICOPTER
|
||||
|
||||
self:T( IsAirResult )
|
||||
return IsAirResult
|
||||
end
|
||||
|
||||
|
||||
function GROUP:AllOnGround()
|
||||
self:T()
|
||||
|
||||
local AllOnGroundResult = true
|
||||
|
||||
for Index, UnitData in pairs( self._Group:getUnits() ) do
|
||||
if UnitData:inAir() then
|
||||
AllOnGroundResult = false
|
||||
end
|
||||
end
|
||||
|
||||
self:T( AllOnGroundResult )
|
||||
return AllOnGroundResult
|
||||
end
|
||||
|
||||
|
||||
function GROUP:GetMaxVelocity()
|
||||
self:T()
|
||||
|
||||
local MaxVelocity = 0
|
||||
|
||||
for Index, UnitData in pairs( self._Group:getUnits() ) do
|
||||
|
||||
local Velocity = UnitData:getVelocity()
|
||||
local VelocityTotal = math.abs( Velocity.x ) + math.abs( Velocity.y ) + math.abs( Velocity.z )
|
||||
|
||||
if VelocityTotal < MaxVelocity then
|
||||
MaxVelocity = VelocityTotal
|
||||
end
|
||||
end
|
||||
|
||||
return MaxVelocity
|
||||
end
|
||||
|
||||
|
||||
function GROUP:GetHeight()
|
||||
self:T()
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
function GROUP:Land( Point, Duration )
|
||||
trace.f( self.ClassName, { self.GroupName, Point, Duration } )
|
||||
|
||||
local Controller = self:_GetController()
|
||||
|
||||
if Duration and Duration > 0 then
|
||||
Controller:pushTask( { id = 'Land', params = { point = Point, durationFlag = true, duration = Duration } } )
|
||||
else
|
||||
Controller:pushTask( { id = 'Land', params = { point = Point, durationFlag = false } } )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function GROUP:Embarking( Point, Duration, EmbarkingGroup )
|
||||
trace.f( self.ClassName, { self.GroupName, Point, Duration, EmbarkingGroup._Group } )
|
||||
|
||||
local Controller = self:_GetController()
|
||||
|
||||
trace.i( self.ClassName, EmbarkingGroup.GroupID )
|
||||
trace.i( self.ClassName, EmbarkingGroup._Group:getID() )
|
||||
trace.i( self.ClassName, EmbarkingGroup._Group.id )
|
||||
|
||||
Controller:pushTask( { id = 'Embarking',
|
||||
params = { x = Point.x,
|
||||
y = Point.y,
|
||||
duration = Duration,
|
||||
groupsForEmbarking = { EmbarkingGroup.GroupID },
|
||||
durationFlag = true,
|
||||
distributionFlag = false,
|
||||
distribution = {},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function GROUP:EmbarkToTransport( Point, Radius )
|
||||
trace.f( self.ClassName, { self.GroupName, Point, Radius } )
|
||||
|
||||
local Controller = self:_GetController()
|
||||
|
||||
Controller:pushTask( { id = 'EmbarkToTransport',
|
||||
params = { x = Point.x,
|
||||
y = Point.y,
|
||||
zoneRadius = Radius,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function GROUP:_GetController()
|
||||
|
||||
return self._Group:getController()
|
||||
|
||||
end
|
||||
@ -74,16 +74,52 @@ end
|
||||
function MESSAGE:ToClient( Client )
|
||||
trace.f(self.ClassName )
|
||||
|
||||
if Client and Client:ClientGroup() then
|
||||
if Client and Client:GetClientGroupID() then
|
||||
|
||||
local ClientGroup = Client:ClientGroup()
|
||||
local ClientGroupID = Client:GetClientGroupID()
|
||||
trace.i( self.ClassName, self.MessageCategory .. '\n' .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
|
||||
trigger.action.outTextForGroup( ClientGroup:getID(), self.MessageCategory .. '\n' .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration )
|
||||
trigger.action.outTextForGroup( ClientGroupID, self.MessageCategory .. '\n' .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sends a MESSAGE to the Blue coalition.
|
||||
-- @treturn MESSAGE
|
||||
-- @usage
|
||||
-- -- Send a message created with the @{New} method to the BLUE coalition.
|
||||
-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToBlue()
|
||||
-- or
|
||||
-- MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToBlue()
|
||||
-- or
|
||||
-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" )
|
||||
-- MessageBLUE:ToBlue()
|
||||
function MESSAGE:ToBlue()
|
||||
trace.f(self.ClassName )
|
||||
|
||||
self:ToCoalition( coalition.side.BLUE )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sends a MESSAGE to the Red Coalition.
|
||||
-- @treturn MESSAGE
|
||||
-- @usage
|
||||
-- -- Send a message created with the @{New} method to the RED coalition.
|
||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToRed()
|
||||
-- or
|
||||
-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToRed()
|
||||
-- or
|
||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" )
|
||||
-- MessageRED:ToRed()
|
||||
function MESSAGE:ToRed( )
|
||||
trace.f(self.ClassName )
|
||||
|
||||
self:ToCoalition( coalition.side.RED )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sends a MESSAGE to a Coalition.
|
||||
-- @param CoalitionSide needs to be filled out by the defined structure of the standard scripting engine @{coalition.side}.
|
||||
-- @treturn MESSAGE
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
Include.File( "Routines" )
|
||||
Include.File( "Base" )
|
||||
Include.File( "Mission" )
|
||||
Include.File( "Client" )
|
||||
Include.File( "Task" )
|
||||
|
||||
@ -16,7 +15,6 @@ MISSION = {
|
||||
_Clients = {},
|
||||
_Tasks = {},
|
||||
_ActiveTasks = {},
|
||||
_Cargos = {},
|
||||
GoalFunction = nil,
|
||||
MissionReportTrigger = 0,
|
||||
MissionProgressTrigger = 0,
|
||||
@ -30,23 +28,13 @@ MISSION = {
|
||||
_GoalTasks = {}
|
||||
}
|
||||
|
||||
CARGOSTATUS = {
|
||||
NONE = 0,
|
||||
LOADED = 1,
|
||||
UNLOADED = 2,
|
||||
LOADING = 3,
|
||||
LoadCount= 0,
|
||||
UnloadCount = 0
|
||||
}
|
||||
|
||||
|
||||
function MISSION:Meta()
|
||||
trace.f(self.ClassName)
|
||||
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, BASE:New() )
|
||||
trace.r( self.ClassName, "", { Child } )
|
||||
return Child
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:T()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
|
||||
@ -66,8 +54,9 @@ end
|
||||
-- local Mission = MISSIONSCHEDULER.AddMission( 'NATO Sling Load', 'Operational', 'Fly to the cargo pickup zone at Dzegvi or Kaspi, and sling the cargo to Soganlug airbase.', 'NATO' )
|
||||
-- local Mission = MISSIONSCHEDULER.AddMission( 'Rescue secret agent', 'Tactical', 'In order to be in full control of the situation, we need you to rescue a secret agent from the woods behind enemy lines. Avoid the Russian defenses and rescue the agent. Keep south until Khasuri, and keep your eyes open for any SAM presence. The agent is located at waypoint 4 on your kneeboard.', 'NATO' )
|
||||
function MISSION:New( MissionName, MissionPriority, MissionBriefing, MissionCoalition )
|
||||
trace.f(self.ClassName, { MissionName, MissionPriority, MissionBriefing, MissionCoalition } )
|
||||
|
||||
self = MISSION:Meta()
|
||||
self:T({ MissionName, MissionPriority, MissionBriefing, MissionCoalition })
|
||||
|
||||
local Valid = true
|
||||
|
||||
@ -83,20 +72,19 @@ trace.f(self.ClassName, { MissionName, MissionPriority, MissionBriefing, Mission
|
||||
self.MissionCoalition = MissionCoalition
|
||||
end
|
||||
|
||||
trace.r( self.ClassName, "" )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns if a Mission has completed.
|
||||
-- @treturn bool
|
||||
function MISSION:IsCompleted()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
return self.MissionStatus == "ACCOMPLISHED"
|
||||
end
|
||||
|
||||
--- Set a Mission to completed.
|
||||
function MISSION:Completed()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
self.MissionStatus = "ACCOMPLISHED"
|
||||
self:StatusToClients()
|
||||
end
|
||||
@ -104,27 +92,27 @@ end
|
||||
--- Returns if a Mission is ongoing.
|
||||
-- treturn bool
|
||||
function MISSION:IsOngoing()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
return self.MissionStatus == "ONGOING"
|
||||
end
|
||||
|
||||
--- Set a Mission to ongoing.
|
||||
function MISSION:Ongoing()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
self.MissionStatus = "ONGOING"
|
||||
self:StatusToClients()
|
||||
--self:StatusToClients()
|
||||
end
|
||||
|
||||
--- Returns if a Mission is pending.
|
||||
-- treturn bool
|
||||
function MISSION:IsPending()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
return self.MissionStatus == "PENDING"
|
||||
end
|
||||
|
||||
--- Set a Mission to pending.
|
||||
function MISSION:Pending()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
self.MissionStatus = "PENDING"
|
||||
self:StatusToClients()
|
||||
end
|
||||
@ -132,31 +120,31 @@ end
|
||||
--- Returns if a Mission has failed.
|
||||
-- treturn bool
|
||||
function MISSION:IsFailed()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
return self.MissionStatus == "FAILED"
|
||||
end
|
||||
|
||||
--- Set a Mission to failed.
|
||||
function MISSION:Failed()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
self.MissionStatus = "FAILED"
|
||||
self:StatusToClients()
|
||||
end
|
||||
|
||||
--- Send the status of the MISSION to all Clients.
|
||||
function MISSION:StatusToClients()
|
||||
trace.f(self.ClassName)
|
||||
if timer.getTime() >= self.MissionReportTrigger then
|
||||
self:T()
|
||||
if self.MissionReportFlash then
|
||||
for ClientID, Client in pairs( self._Clients ) do
|
||||
Client:Message( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. '! ( ' .. self.MissionPriority .. ' mission ) ', 10, self.Name .. '/Status', "Mission Command: Mission Status")
|
||||
end
|
||||
end
|
||||
trace.e()
|
||||
end
|
||||
|
||||
--- Handles the reporting. After certain time intervals, a MISSION report MESSAGE will be shown to All Players.
|
||||
function MISSION:ReportTrigger()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
if self.MissionReportShow == true then
|
||||
self.MissionReportShow = false
|
||||
trace.r( "MISSION", "1", { true } )
|
||||
@ -181,16 +169,17 @@ end
|
||||
|
||||
--- Report the status of all MISSIONs to all active Clients.
|
||||
function MISSION:ReportToAll()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
local AlivePlayers = ''
|
||||
for ClientID, Client in pairs( self._Clients ) do
|
||||
if Client:ClientGroup() then
|
||||
if Client:ClientGroup():getUnit(1) then
|
||||
if Client:ClientGroup():getUnit(1):getLife() > 0.0 then
|
||||
if Client:GetClientGroupUnit() then
|
||||
if Client:GetClientGroupUnit():getLife() > 0.0 then
|
||||
if AlivePlayers == '' then
|
||||
AlivePlayers = ' Players: ' .. Client:ClientGroup():getUnit(1):getPlayerName()
|
||||
AlivePlayers = ' Players: ' .. Client:GetClientGroupUnit():getPlayerName()
|
||||
else
|
||||
AlivePlayers = AlivePlayers .. ' / ' .. Client:ClientGroup():getUnit(1):getPlayerName()
|
||||
AlivePlayers = AlivePlayers .. ' / ' .. Client:GetClientGroupUnit():getPlayerName()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -202,7 +191,6 @@ trace.f(self.ClassName)
|
||||
TaskText = TaskText .. " - Task " .. TaskID .. ": " .. TaskData.Name .. ": " .. TaskData:GetGoalProgress() .. "\n"
|
||||
end
|
||||
MESSAGE:New( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. ' ( ' .. self.MissionPriority .. ' mission )' .. AlivePlayers .. "\n" .. TaskText:gsub("\n$",""), "Mission Command: Mission Report", 10, self.Name .. '/Status'):ToAll()
|
||||
trace.e()
|
||||
end
|
||||
|
||||
|
||||
@ -243,27 +231,26 @@ end
|
||||
-- local Mission = MISSIONSCHEDULER.AddMission( 'NATO Transport Troops', 'Operational', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.', 'NATO' )
|
||||
-- Mission:AddGoalFunction( DeployPatriotTroopsGoal )
|
||||
function MISSION:AddGoalFunction( GoalFunction )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
self.GoalFunction = GoalFunction
|
||||
trace.e()
|
||||
end
|
||||
|
||||
--- Show the briefing of the MISSION to the CLIENT.
|
||||
-- @tparam CLIENT Client to show briefing to.
|
||||
-- @treturn CLIENT
|
||||
function MISSION:ShowBriefing( Client )
|
||||
trace.f(self.ClassName, { Client } )
|
||||
self:T( { Client.ClientName } )
|
||||
|
||||
if not Client.ClientBriefingShown then
|
||||
Client.ClientBriefingShown = true
|
||||
Client:Message( '(Press the keys [LEFT ALT]+[B] to view the briefing pages. Browse through the graphical briefing.)\n' ..
|
||||
self.MissionBriefing, 40, self.Name .. '/MissionBriefing', "Mission Command: Mission Briefing" )
|
||||
local Briefing = self.MissionBriefing
|
||||
if Client.ClientBriefing then
|
||||
Client:Message( Client.ClientBriefing, 40, self.Name .. '/ClientBriefing', "Mission Command: Mission Briefing" )
|
||||
Briefing = Briefing .. "\n" .. Client.ClientBriefing
|
||||
end
|
||||
Briefing = Briefing .. "\n (Press [LEFT ALT]+[B] to view the graphical documentation.)"
|
||||
Client:Message( Briefing, 30, self.Name .. '/MissionBriefing', "Command: Mission Briefing" )
|
||||
end
|
||||
|
||||
trace.r( "", "", { Client } )
|
||||
return Client
|
||||
end
|
||||
|
||||
@ -277,7 +264,7 @@ end
|
||||
-- Mission:AddClient( CLIENT:New( 'US UH-1H*HOT-Deploy Troops 2', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
|
||||
-- Mission:AddClient( CLIENT:New( 'US UH-1H*RAMP-Deploy Troops 4', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
|
||||
function MISSION:AddClient( Client )
|
||||
trace.f(self.ClassName, { Client } )
|
||||
self:T( { Client } )
|
||||
|
||||
local Valid = true
|
||||
|
||||
@ -296,8 +283,7 @@ end
|
||||
-- -- Seach for Client "Bomber" within the Mission.
|
||||
-- local BomberClient = Mission:FindClient( "Bomber" )
|
||||
function MISSION:FindClient( ClientName )
|
||||
trace.f(self.ClassName)
|
||||
trace.r( "", "", { self._Clients[ClientName] } )
|
||||
self:T( { self._Clients[ClientName] } )
|
||||
return self._Clients[ClientName]
|
||||
end
|
||||
|
||||
@ -328,13 +314,12 @@ end
|
||||
-- Mission:AddTask( DeployTask, 2 )
|
||||
|
||||
function MISSION:AddTask( Task, TaskNumber )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
self._Tasks[TaskNumber] = Task
|
||||
self._Tasks[TaskNumber]:EnableEvents()
|
||||
self._Tasks[TaskNumber].ID = TaskNumber
|
||||
|
||||
trace.r( self.ClassName, "" )
|
||||
return Task
|
||||
end
|
||||
|
||||
@ -346,7 +331,7 @@ trace.r( self.ClassName, "" )
|
||||
-- Task2 = Mission:GetTask( 2 )
|
||||
|
||||
function MISSION:GetTask( TaskNumber )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
local Valid = true
|
||||
|
||||
@ -370,51 +355,11 @@ end
|
||||
-- Tasks = Mission:GetTasks()
|
||||
-- env.info( "Task 2 Completion = " .. Tasks[2]:GetGoalPercentage() .. "%" )
|
||||
function MISSION:GetTasks()
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
return self._Tasks
|
||||
end
|
||||
|
||||
--- Add Cargo to the mission... Cargo functionality needs to be reworked a bit, so this is still under construction. I need to make a CARGO Class...
|
||||
SpawnCargo = {}
|
||||
function MISSION:AddCargo( CargoName, CargoType, CargoWeight, CargoGroupControlCenter, CargoGroupTemplate, CargoZone )
|
||||
trace.f(self.ClassName, { CargoName, CargoType, CargoWeight, CargoGroupControlCenter, CargoGroupTemplate, CargoZone } )
|
||||
|
||||
local Cargo = {}
|
||||
Cargo.CargoName = CargoName
|
||||
if CargoType.TRANSPORT == CARGO_TRANSPORT.UNIT then
|
||||
if not SpawnCargo[CargoGroupTemplate] then
|
||||
SpawnCargo[CargoGroupTemplate] = SPAWN:New( CargoGroupTemplate )
|
||||
end
|
||||
if CargoGroupControlCenter == nil then
|
||||
--- @todo check this
|
||||
Cargo.CargoGroupName = SpawnCargo[CargoGroupTemplate]:InZone( CargoZone ).name
|
||||
else
|
||||
--- @todo check this
|
||||
env.info( "SpawnFromCarrier")
|
||||
Cargo.CargoGroupName = SpawnCargo[CargoGroupTemplate]:FromCarrier( Group.getByName( CargoGroupControlCenter ), CargoZone, nil, true ).name
|
||||
--trigger.action.activateGroup( Group.getByName( Cargo.CargoGroupName ) )
|
||||
--trigger.action.setGroupAIOff( Cargo.CargoGroupName )
|
||||
trace.i( self.ClassName, Cargo.CargoGroupName )
|
||||
|
||||
end
|
||||
else
|
||||
Cargo.CargoGroupName = CargoGroupControlCenter
|
||||
end
|
||||
Cargo.CargoType = CargoType
|
||||
Cargo.CargoWeight = CargoWeight
|
||||
Cargo.CargoGroupControlCenter = CargoGroupControlCenter
|
||||
Cargo.CargoGroupTemplate = CargoGroupTemplate
|
||||
Cargo.CargoZone = CargoZone
|
||||
Cargo.Status = CARGOSTATUS.NONE
|
||||
self._Cargos[CargoName] = Cargo
|
||||
|
||||
trace.r( self.ClassName, "AddCargo", { Cargo.CargoGroupName } )
|
||||
return Cargo.CargoGroupName
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--[[
|
||||
_TransportExecuteStage: Defines the different stages of Transport unload/load execution. This table is internal and is used to control the validity of Transport load/unload timing.
|
||||
@ -450,6 +395,8 @@ trace.scheduled("MISSIONSCHEDULER","Scheduler")
|
||||
|
||||
-- loop through the missions in the TransportTasks
|
||||
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
|
||||
|
||||
trace.i( "MISSIONSCHEDULER", MissionName )
|
||||
|
||||
if not Mission:IsCompleted() then
|
||||
|
||||
@ -457,8 +404,10 @@ trace.scheduled("MISSIONSCHEDULER","Scheduler")
|
||||
local ClientsAlive = false
|
||||
|
||||
for ClientID, Client in pairs( Mission._Clients ) do
|
||||
|
||||
trace.i( "MISSIONSCHEDULER", "Client: " .. Client.ClientName )
|
||||
|
||||
if Client:ClientGroup() and Client:ClientGroup():getUnits() and Client:ClientGroup():getUnits()[1] and Client:ClientGroup():getUnits()[1]:getLife() > 0.0 then
|
||||
if Client:ClientGroup() then
|
||||
|
||||
-- There is at least one Client that is alive... So the Mission status is set to Ongoing.
|
||||
ClientsAlive = true
|
||||
@ -476,13 +425,10 @@ trace.scheduled("MISSIONSCHEDULER","Scheduler")
|
||||
Client._Tasks[TaskNumber] = routines.utils.deepCopy( Mission._Tasks[TaskNumber] )
|
||||
-- Each MissionTask must point to the original Mission.
|
||||
Client._Tasks[TaskNumber].MissionTask = Mission._Tasks[TaskNumber]
|
||||
Client._Tasks[TaskNumber].Cargos = Mission._Tasks[TaskNumber].Cargos
|
||||
Client._Tasks[TaskNumber].LandingZones = Mission._Tasks[TaskNumber].LandingZones
|
||||
end
|
||||
Client._Cargos = {}
|
||||
if Client.InitCargoNames then
|
||||
for InitCargoID, InitCargoName in pairs( Client.InitCargoNames ) do
|
||||
Client._Cargos[InitCargoName] = Mission._Cargos[InitCargoName]
|
||||
end
|
||||
end
|
||||
|
||||
Mission:Ongoing()
|
||||
end
|
||||
|
||||
@ -524,6 +470,7 @@ trace.scheduled("MISSIONSCHEDULER","Scheduler")
|
||||
end
|
||||
|
||||
if Task:IsDone() then
|
||||
trace.i( "MISSIONSCHEDULER", "Task " .. Task.Name .. " is Done." )
|
||||
--env.info( 'Scheduler: Mission '.. Mission.Name .. ' Task ' .. Task.Name .. ' Stage ' .. Task.Stage.Name .. ' done. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
|
||||
TaskComplete = true -- when a task is not yet completed, a mission cannot be completed
|
||||
|
||||
@ -539,7 +486,7 @@ trace.scheduled("MISSIONSCHEDULER","Scheduler")
|
||||
if Mission.GoalFunction ~= nil then
|
||||
Mission.GoalFunction( Mission, Client )
|
||||
end
|
||||
_Database:_AddMissionTaskScore( Client:ClientGroup():getUnit(1), Mission.Name, 25 )
|
||||
_Database:_AddMissionTaskScore( Client:GetClientGroupUnit(), Mission.Name, 25 )
|
||||
|
||||
-- if not Mission:IsCompleted() then
|
||||
-- end
|
||||
@ -580,9 +527,6 @@ trace.scheduled("MISSIONSCHEDULER","Scheduler")
|
||||
-- So first sanitize Client._Tasks[TaskNumber].MissionTask, after that, sanitize only the whole _Tasks structure...
|
||||
--Client._Tasks[TaskNumber].MissionTask = nil
|
||||
--Client._Tasks = nil
|
||||
|
||||
-- Sanitize the Client._Cargos. Any cargo within the Client will be lost when the client crashes. This is an important statement.
|
||||
Client._Cargos = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -20,61 +20,61 @@ MOVEMENT = {
|
||||
-- Movement_US_Platoons = MOVEMENT:New( { 'US Tank Platoon Left', 'US Tank Platoon Middle', 'US Tank Platoon Right', 'US CH-47D Troops' }, 15 )
|
||||
|
||||
function MOVEMENT:New( MovePrefixes, MoveMaximum )
|
||||
trace.f(self.ClassName, { MovePrefixes, MoveMaximum } )
|
||||
|
||||
-- Inherits from BASE
|
||||
local Child = BASE:Inherit( self, BASE:New() )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:T( { MovePrefixes, MoveMaximum } )
|
||||
|
||||
if type( MovePrefixes ) == 'table' then
|
||||
Child.MovePrefixes = MovePrefixes
|
||||
self.MovePrefixes = MovePrefixes
|
||||
else
|
||||
Child.MovePrefixes = { MovePrefixes }
|
||||
self.MovePrefixes = { MovePrefixes }
|
||||
end
|
||||
Child.MoveCount = 0 -- The internal counter of the amount of Moveing the has happened since MoveStart.
|
||||
Child.MoveMaximum = MoveMaximum -- Contains the Maximum amount of units that are allowed to move...
|
||||
Child.AliveUnits = 0 -- Contains the counter how many units are currently alive
|
||||
Child.MoveGroups = {} -- Reflects if the Moveing for this MovePrefixes is going to be scheduled or not.
|
||||
self.MoveCount = 0 -- The internal counter of the amount of Moveing the has happened since MoveStart.
|
||||
self.MoveMaximum = MoveMaximum -- Contains the Maximum amount of units that are allowed to move...
|
||||
self.AliveUnits = 0 -- Contains the counter how many units are currently alive
|
||||
self.MoveUnits = {} -- Reflects if the Moving for this MovePrefixes is going to be scheduled or not.
|
||||
|
||||
Child.AddEvent( Child, world.event.S_EVENT_BIRTH, Child.OnBirth )
|
||||
Child.AddEvent( Child, world.event.S_EVENT_DEAD, Child.OnDeadOrCrash )
|
||||
Child.AddEvent( Child, world.event.S_EVENT_CRASH, Child.OnDeadOrCrash )
|
||||
self.AddEvent( self, world.event.S_EVENT_BIRTH, self.OnBirth )
|
||||
self.AddEvent( self, world.event.S_EVENT_DEAD, self.OnDeadOrCrash )
|
||||
self.AddEvent( self, world.event.S_EVENT_CRASH, self.OnDeadOrCrash )
|
||||
|
||||
Child.EnableEvents( Child )
|
||||
self.EnableEvents( self )
|
||||
|
||||
Child.ScheduleStart( Child )
|
||||
self.ScheduleStart( self )
|
||||
|
||||
return Child
|
||||
return self
|
||||
end
|
||||
|
||||
--- Call this function to start the MOVEMENT scheduling.
|
||||
function MOVEMENT:ScheduleStart()
|
||||
trace.f( self.ClassName )
|
||||
self:T()
|
||||
self.MoveFunction = routines.scheduleFunction( self._Scheduler, { self }, timer.getTime() + 1, 120 )
|
||||
end
|
||||
|
||||
--- Call this function to stop the MOVEMENT scheduling.
|
||||
-- @todo need to implement it ... Forgot.
|
||||
function MOVEMENT:ScheduleStop()
|
||||
trace.f( self.ClassName )
|
||||
self:T()
|
||||
|
||||
end
|
||||
|
||||
--- Captures the birth events when new Units were spawned.
|
||||
-- @todo This method should become obsolete. The new @{DATABASE} class will handle the collection administration.
|
||||
function MOVEMENT:OnBirth( event )
|
||||
trace.f( self.ClassName, { event } )
|
||||
self:T( { event } )
|
||||
|
||||
if timer.getTime0() < timer.getAbsTime() then -- dont need to add units spawned in at the start of the mission if mist is loaded in init line
|
||||
if event.initiator and event.initiator:getName() then
|
||||
trace.l(self.ClassName, "OnBirth", "Birth object : " .. event.initiator:getName() )
|
||||
local GroupData = Unit.getGroup(event.initiator)
|
||||
if GroupData and GroupData:isExist() then
|
||||
local EventGroupName = GroupData:getName()
|
||||
if event.initiator and Object.getCategory(event.initiator) == Object.Category.UNIT then
|
||||
local MovementUnit = event.initiator
|
||||
local MovementUnitName = MovementUnit:getName()
|
||||
self:T( "Birth object : " .. MovementUnitName )
|
||||
local MovementGroup = MovementUnit:getGroup()
|
||||
if MovementGroup and MovementGroup:isExist() then
|
||||
local MovementGroupName = MovementGroup:getName()
|
||||
for MovePrefixID, MovePrefix in pairs( self.MovePrefixes ) do
|
||||
if string.find( EventGroupName, MovePrefix, 1, true ) then
|
||||
if string.find( MovementUnitName, MovePrefix, 1, true ) then
|
||||
self.AliveUnits = self.AliveUnits + 1
|
||||
self.MoveGroups[EventGroupName] = EventGroupName
|
||||
trace.l(self.ClassName, "OnBirth", self.AliveUnits )
|
||||
self.MoveUnits[MovementUnitName] = MovementGroupName
|
||||
self:T( self.AliveUnits )
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -86,16 +86,17 @@ end
|
||||
--- Captures the Dead or Crash events when Units crash or are destroyed.
|
||||
-- @todo This method should become obsolete. The new @{DATABASE} class will handle the collection administration.
|
||||
function MOVEMENT:OnDeadOrCrash( event )
|
||||
trace.f( self.ClassName, { event } )
|
||||
self:T( { event } )
|
||||
|
||||
if event.initiator and event.initiator:getName() then
|
||||
trace.l( self.ClassName, "OnDeadOrCrash", "Dead object : " .. event.initiator:getName() )
|
||||
local EventGroupName = Unit.getGroup(event.initiator):getName()
|
||||
if event.initiator and Object.getCategory(event.initiator) == Object.Category.UNIT then
|
||||
local MovementUnit = event.initiator
|
||||
local MovementUnitName = MovementUnit:getName()
|
||||
self:T( "Dead object : " .. MovementUnitName )
|
||||
for MovePrefixID, MovePrefix in pairs( self.MovePrefixes ) do
|
||||
if string.find( EventGroupName, MovePrefix, 1, true ) then
|
||||
if string.find( MovementUnitName, MovePrefix, 1, true ) then
|
||||
self.AliveUnits = self.AliveUnits - 1
|
||||
self.MoveGroups[EventGroupName] = nil
|
||||
trace.l( self.ClassName, "OnDeadOrCrash", self.AliveUnits )
|
||||
self.MoveUnits[MovementUnitName] = nil
|
||||
self:T( self.AliveUnits )
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -103,24 +104,26 @@ end
|
||||
|
||||
--- This function is called automatically by the MOVEMENT scheduler. A new function is scheduled when MoveScheduled is true.
|
||||
function MOVEMENT:_Scheduler()
|
||||
trace.l( self.ClassName, '_Scheduler', { self.MovePrefixes, self.MoveMaximum, self.AliveUnits, self.MoveGroups } )
|
||||
self:T( { self.MovePrefixes, self.MoveMaximum, self.AliveUnits, self.MovementGroups } )
|
||||
|
||||
if self.AliveUnits > 0 then
|
||||
local MoveProbability = ( self.MoveMaximum * 100 ) / self.AliveUnits
|
||||
trace.l( self.ClassName, '_Scheduler', 'Move Probability = ' .. MoveProbability )
|
||||
self:T( 'Move Probability = ' .. MoveProbability )
|
||||
|
||||
for MoveGroupID, MoveGroupName in pairs( self.MoveGroups ) do
|
||||
local MoveGroup = Group.getByName( MoveGroupName )
|
||||
if MoveGroup then
|
||||
for MovementUnitName, MovementGroupName in pairs( self.MoveUnits ) do
|
||||
local MovementGroup = Group.getByName( MovementGroupName )
|
||||
if MovementGroup and MovementGroup:isExist() then
|
||||
local MoveOrStop = math.random( 1, 100 )
|
||||
trace.l( self.ClassName, '_Scheduler', 'MoveOrStop = ' .. MoveOrStop )
|
||||
self:T( 'MoveOrStop = ' .. MoveOrStop )
|
||||
if MoveOrStop <= MoveProbability then
|
||||
trace.l( self.ClassName, '_Scheduler', 'Group continues moving = ' .. MoveGroupName )
|
||||
trigger.action.groupContinueMoving( MoveGroup )
|
||||
self:T( 'Group continues moving = ' .. MovementGroupName )
|
||||
trigger.action.groupContinueMoving( MovementGroup )
|
||||
else
|
||||
trace.l( self.ClassName, '_Scheduler', 'Group stops moving = ' .. MoveGroupName )
|
||||
trigger.action.groupStopMoving( MoveGroup )
|
||||
self:T( 'Group stops moving = ' .. MovementGroupName )
|
||||
trigger.action.groupStopMoving( MovementGroup )
|
||||
end
|
||||
else
|
||||
self.MoveUnits[MovementUnitName] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
-- @parent TASK
|
||||
|
||||
Include.File("Task")
|
||||
Include.File("Cargo")
|
||||
|
||||
PICKUPTASK = {
|
||||
ClassName = "PICKUPTASK",
|
||||
@ -14,87 +15,103 @@ PICKUPTASK = {
|
||||
-- @tparam table{string,...}|string LandingZones Table of Zone names where Cargo is to be loaded.
|
||||
-- @tparam CARGO_TYPE CargoType Type of the Cargo. The type must be of the following Enumeration:..
|
||||
-- @tparam number OnBoardSide Reflects from which side the cargo Group will be on-boarded on the Carrier.
|
||||
function PICKUPTASK:New( LandingZones, CargoType, OnBoardSide )
|
||||
trace.f(self.ClassName)
|
||||
function PICKUPTASK:New( CargoType, OnBoardSide )
|
||||
local self = BASE:Inherit( self, TASK:New() )
|
||||
self:T()
|
||||
|
||||
-- Child holds the inherited instance of the PICKUPTASK Class to the BASE class.
|
||||
local Child = BASE:Inherit( self, TASK:New() )
|
||||
-- self holds the inherited instance of the PICKUPTASK Class to the BASE class.
|
||||
|
||||
local Valid = true
|
||||
|
||||
Valid = routines.ValidateZone( LandingZones, "LandingZones", Valid )
|
||||
Valid = routines.ValidateEnumeration( CargoType, "CargoType", CARGO_TYPE, Valid )
|
||||
Valid = routines.ValidateEnumeration( CargoType, "CargoType", CARGO_TYPE, Valid )
|
||||
--Valid = routines.ValidateEnumeration( OnBoardSide, "OnBoardSide", CLIENT.ONBOARDSIDE, Valid )
|
||||
|
||||
if Valid then
|
||||
Child.Name = 'Pickup Cargo'
|
||||
Child.TaskBriefing = "Task: Fly to the indicated landing zones and pickup " .. CargoType.TEXT .. ". Your co-pilot will provide you with the directions (required flight angle in degrees) and the distance (in km) to the pickup zone."
|
||||
if type( LandingZones ) == "table" then
|
||||
Child.LandingZones = LandingZones
|
||||
else
|
||||
Child.LandingZones = { LandingZones }
|
||||
end
|
||||
Child.CargoType = CargoType
|
||||
Child.GoalVerb = CargoType.TEXT .. " " .. Child.GoalVerb
|
||||
Child.OnBoardSide = OnBoardSide
|
||||
Child.Stages = { STAGEBRIEF:New(), STAGESTART:New(), STAGEROUTE:New(), STAGELANDING:New(), STAGELANDED:New(), STAGELOAD:New(), STAGEDONE:New() }
|
||||
Child.SetStage( Child, 1 )
|
||||
|
||||
self.Name = 'Pickup Cargo'
|
||||
self.TaskBriefing = "Task: Fly to the indicated landing zones and pickup " .. CargoType .. ". Your co-pilot will provide you with the directions (required flight angle in degrees) and the distance (in km) to the pickup zone."
|
||||
self.CargoType = CargoType
|
||||
self.GoalVerb = CargoType .. " " .. self.GoalVerb
|
||||
self.OnBoardSide = OnBoardSide
|
||||
self.IsLandingRequired = false -- required to decide whether the client needs to land or not
|
||||
self.IsSlingLoad = false -- Indicates whether the cargo is a sling load cargo
|
||||
self.Stages = { STAGE_CARGO_INIT:New(), STAGE_CARGO_LOAD:New(), STAGEBRIEF:New(), STAGESTART:New(), STAGEROUTE:New(), STAGELANDING:New(), STAGELANDED:New(), STAGELOAD:New(), STAGEDONE:New() }
|
||||
self.SetStage( self, 1 )
|
||||
end
|
||||
|
||||
return Child
|
||||
return self
|
||||
end
|
||||
|
||||
function PICKUPTASK:FromZone( LandingZone )
|
||||
self:T()
|
||||
|
||||
self.LandingZones.LandingZoneNames[LandingZone.CargoZoneName] = LandingZone.CargoZoneName
|
||||
self.LandingZones.LandingZones[LandingZone.CargoZoneName] = LandingZone
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function PICKUPTASK:InitCargo( InitCargos )
|
||||
self:T( { InitCargos } )
|
||||
|
||||
if type( InitCargos ) == "table" then
|
||||
self.Cargos.InitCargos = InitCargos
|
||||
else
|
||||
self.Cargos.InitCargos = { InitCargos }
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function PICKUPTASK:LoadCargo( LoadCargos )
|
||||
self:T( { LoadCargos } )
|
||||
|
||||
if type( LoadCargos ) == "table" then
|
||||
self.Cargos.LoadCargos = LoadCargos
|
||||
else
|
||||
self.Cargos.LoadCargos = { LoadCargos }
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function PICKUPTASK:AddCargoMenus( Client, Cargos, TransportRadius )
|
||||
trace.f(self.ClassName, { Client, Cargos, TransportRadius } )
|
||||
self:T()
|
||||
|
||||
for CargoID, CargoData in pairs( Cargos ) do
|
||||
for CargoID, Cargo in pairs( Cargos ) do
|
||||
|
||||
if CargoData.Status ~= CARGOSTATUS.LOADED and CargoData.Status ~= CARGOSTATUS.LOADING then
|
||||
self:T( { Cargo.ClassName, Cargo.CargoName, Cargo.CargoType, Cargo:IsStatusNone(), Cargo:IsStatusLoaded(), Cargo:IsStatusLoading(), Cargo:IsStatusUnLoaded() } )
|
||||
|
||||
if Group.getByName( CargoData.CargoGroupName ) then
|
||||
-- If the Cargo has no status, allow the menu option.
|
||||
if Cargo:IsStatusNone() or ( Cargo:IsStatusLoading() and Client == Cargo:IsLoadingToClient() ) then
|
||||
|
||||
local MenuAdd = false
|
||||
if Cargo:IsNear( Client, self.CurrentCargoZone ) then
|
||||
MenuAdd = true
|
||||
end
|
||||
|
||||
if Group.getByName( CargoData.CargoGroupName ):getSize() >= 1 then
|
||||
|
||||
if Client._Menus[CargoData.CargoType] == nil then
|
||||
Client._Menus[CargoData.CargoType] = {}
|
||||
end
|
||||
|
||||
if not Client._Menus[CargoData.CargoType].PickupMenu then
|
||||
Client._Menus[CargoData.CargoType].PickupMenu = missionCommands.addSubMenuForGroup(
|
||||
Client:ClientGroup():getID(),
|
||||
self.TEXT[1],
|
||||
nil
|
||||
)
|
||||
trace.i( self.ClassName, 'Added PickupMenu' .. self.TEXT[1] )
|
||||
end
|
||||
|
||||
if Client._Menus[CargoData.CargoType].PickupSubMenus == nil then
|
||||
Client._Menus[CargoData.CargoType].PickupSubMenus = {}
|
||||
end
|
||||
|
||||
local MenuAdd = false
|
||||
if CargoData.CargoType.TRANSPORT == CARGO_TRANSPORT.UNIT then
|
||||
CargoGroup = Group.getByName( CargoData.CargoGroupName )
|
||||
if routines.IsPartOfGroupInRadius( CargoGroup, Client:ClientGroup(), TransportRadius ) then
|
||||
MenuAdd = true
|
||||
end
|
||||
else
|
||||
MenuAdd = true
|
||||
end
|
||||
|
||||
if MenuAdd then
|
||||
Client._Menus[CargoData.CargoType].PickupSubMenus[ #Client._Menus[CargoData.CargoType].PickupSubMenus + 1 ] = missionCommands.addCommandForGroup(
|
||||
Client:ClientGroup():getID(),
|
||||
CargoData.CargoName .. " ( " .. CargoData.CargoWeight .. "kg )",
|
||||
Client._Menus[CargoData.CargoType].PickupMenu,
|
||||
self.MenuAction,
|
||||
{ ReferenceTask = self, CargoName = CargoData.CargoName }
|
||||
)
|
||||
trace.i( self.ClassName, 'Added PickupSubMenu' .. CargoData.CargoType.TEXT .. ":" .. CargoData.CargoName .. " ( " .. CargoData.CargoWeight .. "kg )" )
|
||||
end
|
||||
if MenuAdd then
|
||||
if Client._Menus[Cargo.CargoType] == nil then
|
||||
Client._Menus[Cargo.CargoType] = {}
|
||||
end
|
||||
|
||||
if not Client._Menus[Cargo.CargoType].PickupMenu then
|
||||
Client._Menus[Cargo.CargoType].PickupMenu = missionCommands.addSubMenuForGroup(
|
||||
Client:GetClientGroupID(),
|
||||
self.TEXT[1] .. " " .. Cargo.CargoType,
|
||||
nil
|
||||
)
|
||||
self:T( 'Added PickupMenu: ' .. self.TEXT[1] .. " " .. Cargo.CargoType )
|
||||
end
|
||||
|
||||
if Client._Menus[Cargo.CargoType].PickupSubMenus == nil then
|
||||
Client._Menus[Cargo.CargoType].PickupSubMenus = {}
|
||||
end
|
||||
|
||||
Client._Menus[Cargo.CargoType].PickupSubMenus[ #Client._Menus[Cargo.CargoType].PickupSubMenus + 1 ] = missionCommands.addCommandForGroup(
|
||||
Client:GetClientGroupID(),
|
||||
Cargo.CargoName .. " ( " .. Cargo.CargoWeight .. "kg )",
|
||||
Client._Menus[Cargo.CargoType].PickupMenu,
|
||||
self.MenuAction,
|
||||
{ ReferenceTask = self, CargoTask = Cargo }
|
||||
)
|
||||
self:T( 'Added PickupSubMenu' .. Cargo.CargoType .. ":" .. Cargo.CargoName .. " ( " .. Cargo.CargoWeight .. "kg )" )
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -102,103 +119,36 @@ trace.f(self.ClassName, { Client, Cargos, TransportRadius } )
|
||||
end
|
||||
|
||||
function PICKUPTASK:RemoveCargoMenus( Client )
|
||||
trace.f(self.ClassName, { Client } )
|
||||
self:T()
|
||||
|
||||
for MenuID, MenuData in pairs( Client._Menus ) do
|
||||
for SubMenuID, SubMenuData in pairs( MenuData.PickupSubMenus ) do
|
||||
missionCommands.removeItemForGroup( Client:ClientGroup():getID(), SubMenuData )
|
||||
trace.i( self.ClassName, "Removed PickupSubMenu " )
|
||||
missionCommands.removeItemForGroup( Client:GetClientGroupID(), SubMenuData )
|
||||
self:T( "Removed PickupSubMenu " )
|
||||
SubMenuData = nil
|
||||
end
|
||||
if MenuData.PickupMenu then
|
||||
missionCommands.removeItemForGroup( Client:ClientGroup():getID(), MenuData.PickupMenu )
|
||||
trace.i( self.ClassName, "Removed PickupMenu " )
|
||||
missionCommands.removeItemForGroup( Client:GetClientGroupID(), MenuData.PickupMenu )
|
||||
self:T( "Removed PickupMenu " )
|
||||
MenuData.PickupMenu = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
for CargoID, Cargo in pairs( CARGOS ) do
|
||||
self:T( { Cargo.ClassName, Cargo.CargoName, Cargo.CargoType, Cargo:IsStatusNone(), Cargo:IsStatusLoaded(), Cargo:IsStatusLoading(), Cargo:IsStatusUnLoaded() } )
|
||||
if Cargo:IsStatusLoading() and Client == Cargo:IsLoadingToClient() then
|
||||
Cargo:StatusNone()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
function PICKUPTASK:HasFailed( ClientDead )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
local TaskHasFailed = self.TaskFailed
|
||||
return TaskHasFailed
|
||||
end
|
||||
|
||||
function PICKUPTASK:OnBoardCargo( ClientGroup, Cargos )
|
||||
trace.f(self.ClassName, { ClientGroup, Cargos } )
|
||||
|
||||
local Valid = true
|
||||
|
||||
Valid = routines.ValidateGroup( ClientGroup, "ClientGroup", Valid )
|
||||
|
||||
if Valid then
|
||||
|
||||
local CarrierPos = ClientGroup:getUnits()[1]:getPoint()
|
||||
local CarrierPosMove = ClientGroup:getUnits()[1]:getPoint()
|
||||
local CarrierPosOnBoard = ClientGroup:getUnits()[1]:getPoint()
|
||||
|
||||
local CargoGroup = Group.getByName( Cargos[ self.CargoName ].CargoGroupName )
|
||||
trigger.action.activateGroup( CargoGroup )
|
||||
trigger.action.setGroupAIOn( CargoGroup )
|
||||
|
||||
local CargoUnits = CargoGroup:getUnits()
|
||||
local CargoPos = CargoUnits[1]:getPoint()
|
||||
|
||||
|
||||
local Points = {}
|
||||
|
||||
trace.i( self.ClassName, 'CargoPos x = ' .. CargoPos.x .. " z = " .. CargoPos.z )
|
||||
trace.i( self.ClassName, 'CarrierPosMove x = ' .. CarrierPosMove.x .. " z = " .. CarrierPosMove.z )
|
||||
|
||||
Points[#Points+1] = routines.ground.buildWP( CargoPos, "off road", 6 )
|
||||
|
||||
trace.i( self.ClassName, 'Points[1] x = ' .. Points[1].x .. " y = " .. Points[1].y )
|
||||
|
||||
if self.OnBoardSide == nil then
|
||||
self.OnBoardSide = CLIENT.ONBOARDSIDE.NONE
|
||||
end
|
||||
|
||||
if self.OnBoardSide == CLIENT.ONBOARDSIDE.LEFT then
|
||||
trace.i( self.ClassName, "TransportCargoOnBoard: Onboarding LEFT" )
|
||||
CarrierPosMove.z = CarrierPosMove.z - 50
|
||||
CarrierPosOnBoard.z = CarrierPosOnBoard.z - 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "diamond", 6 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "diamond", 6 )
|
||||
elseif self.OnBoardSide == CLIENT.ONBOARDSIDE.RIGHT then
|
||||
trace.i( self.ClassName, "TransportCargoOnBoard: Onboarding RIGHT" )
|
||||
CarrierPosMove.z = CarrierPosMove.z + 50
|
||||
CarrierPosOnBoard.z = CarrierPosOnBoard.z + 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "diamond", 6 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "diamond", 6 )
|
||||
elseif self.OnBoardSide == CLIENT.ONBOARDSIDE.BACK then
|
||||
trace.i( self.ClassName, "TransportCargoOnBoard: Onboarding BACK" )
|
||||
CarrierPosMove.x = CarrierPosMove.x - 50
|
||||
CarrierPosOnBoard.x = CarrierPosOnBoard.x - 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "diamond", 6 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "diamond", 6 )
|
||||
elseif self.OnBoardSide == CLIENT.ONBOARDSIDE.FRONT then
|
||||
trace.i( self.ClassName, "TransportCargoOnBoard: Onboarding FRONT" )
|
||||
CarrierPosMove.x = CarrierPosMove.x + 50
|
||||
CarrierPosOnBoard.x = CarrierPosOnBoard.x + 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "diamond", 6 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "diamond", 6 )
|
||||
elseif self.OnBoardSide == CLIENT.ONBOARDSIDE.NONE then
|
||||
trace.i( self.ClassName, "TransportCargoOnBoard: Onboarding CENTRAL" )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPos, "diamond", 6 )
|
||||
end
|
||||
trace.i( self.ClassName, "TransportCargoOnBoard: Routing " .. Cargos[ self.CargoName ].CargoGroupName )
|
||||
|
||||
trace.i( self.ClassName, 'Points[2] x = ' .. Points[2].x .. " y = " .. Points[2].y )
|
||||
trace.i( self.ClassName, 'Points[3] x = ' .. Points[3].x .. " y = " .. Points[3].y )
|
||||
|
||||
routines.scheduleFunction(routines.goRoute, {Cargos[ self.CargoName ].CargoGroupName, Points}, timer.getTime() + 8)
|
||||
--routines.goRoute( Cargos[ self.CargoName ].CargoGroupName, Points )
|
||||
end
|
||||
|
||||
return Valid
|
||||
|
||||
end
|
||||
|
||||
@ -25,6 +25,107 @@ routines.build = 22
|
||||
-- Utils- conversion, Lua utils, etc.
|
||||
routines.utils = {}
|
||||
|
||||
--from http://lua-users.org/wiki/CopyTable
|
||||
routines.utils.deepCopy = function(object)
|
||||
local lookup_table = {}
|
||||
local function _copy(object)
|
||||
if type(object) ~= "table" then
|
||||
return object
|
||||
elseif lookup_table[object] then
|
||||
return lookup_table[object]
|
||||
end
|
||||
local new_table = {}
|
||||
lookup_table[object] = new_table
|
||||
for index, value in pairs(object) do
|
||||
new_table[_copy(index)] = _copy(value)
|
||||
end
|
||||
return setmetatable(new_table, getmetatable(object))
|
||||
end
|
||||
local objectreturn = _copy(object)
|
||||
return objectreturn
|
||||
end
|
||||
|
||||
|
||||
-- porting in Slmod's serialize_slmod2
|
||||
routines.utils.oneLineSerialize = function(tbl) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
|
||||
|
||||
lookup_table = {}
|
||||
|
||||
local function _Serialize( tbl )
|
||||
|
||||
if type(tbl) == 'table' then --function only works for tables!
|
||||
|
||||
if lookup_table[tbl] then
|
||||
return lookup_table[object]
|
||||
end
|
||||
|
||||
local tbl_str = {}
|
||||
|
||||
lookup_table[tbl] = tbl_str
|
||||
|
||||
tbl_str[#tbl_str + 1] = '{'
|
||||
|
||||
for ind,val in pairs(tbl) do -- serialize its fields
|
||||
if type(ind) == "number" then
|
||||
tbl_str[#tbl_str + 1] = '['
|
||||
tbl_str[#tbl_str + 1] = tostring(ind)
|
||||
tbl_str[#tbl_str + 1] = ']='
|
||||
else --must be a string
|
||||
tbl_str[#tbl_str + 1] = '['
|
||||
tbl_str[#tbl_str + 1] = routines.utils.basicSerialize(ind)
|
||||
tbl_str[#tbl_str + 1] = ']='
|
||||
end
|
||||
|
||||
if ((type(val) == 'number') or (type(val) == 'boolean')) then
|
||||
tbl_str[#tbl_str + 1] = tostring(val)
|
||||
tbl_str[#tbl_str + 1] = ','
|
||||
elseif type(val) == 'string' then
|
||||
tbl_str[#tbl_str + 1] = routines.utils.basicSerialize(val)
|
||||
tbl_str[#tbl_str + 1] = ','
|
||||
elseif type(val) == 'nil' then -- won't ever happen, right?
|
||||
tbl_str[#tbl_str + 1] = 'nil,'
|
||||
elseif type(val) == 'table' then
|
||||
if ind == "__index" then
|
||||
tbl_str[#tbl_str + 1] = "__index"
|
||||
tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
|
||||
else
|
||||
|
||||
tbl_str[#tbl_str + 1] = _Serialize(val)
|
||||
tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
|
||||
end
|
||||
elseif type(val) == 'function' then
|
||||
tbl_str[#tbl_str + 1] = "function " .. tostring(ind)
|
||||
tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
|
||||
else
|
||||
env.info('unable to serialize value type ' .. routines.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind))
|
||||
env.info( debug.traceback() )
|
||||
end
|
||||
|
||||
end
|
||||
tbl_str[#tbl_str + 1] = '}'
|
||||
return table.concat(tbl_str)
|
||||
else
|
||||
return tostring(tbl)
|
||||
end
|
||||
end
|
||||
|
||||
local objectreturn = _Serialize(tbl)
|
||||
return objectreturn
|
||||
end
|
||||
|
||||
--porting in Slmod's "safestring" basic serialize
|
||||
routines.utils.basicSerialize = function(s)
|
||||
if s == nil then
|
||||
return "\"\""
|
||||
else
|
||||
if ((type(s) == 'number') or (type(s) == 'boolean') or (type(s) == 'function') or (type(s) == 'table') or (type(s) == 'userdata') ) then
|
||||
return tostring(s)
|
||||
elseif type(s) == 'string' then
|
||||
s = string.format('%q', s)
|
||||
return s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
routines.utils.toDegree = function(angle)
|
||||
@ -137,91 +238,6 @@ function routines.utils.get3DDist(point1, point2)
|
||||
end
|
||||
|
||||
|
||||
--from http://lua-users.org/wiki/CopyTable
|
||||
routines.utils.deepCopy = function(object)
|
||||
local lookup_table = {}
|
||||
local function _copy(object)
|
||||
if type(object) ~= "table" then
|
||||
return object
|
||||
elseif lookup_table[object] then
|
||||
return lookup_table[object]
|
||||
end
|
||||
local new_table = {}
|
||||
lookup_table[object] = new_table
|
||||
for index, value in pairs(object) do
|
||||
new_table[_copy(index)] = _copy(value)
|
||||
end
|
||||
return setmetatable(new_table, getmetatable(object))
|
||||
end
|
||||
local objectreturn = _copy(object)
|
||||
return objectreturn
|
||||
end
|
||||
|
||||
|
||||
-- porting in Slmod's serialize_slmod2
|
||||
routines.utils.oneLineSerialize = function(tbl) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
|
||||
if type(tbl) == 'table' then --function only works for tables!
|
||||
|
||||
local tbl_str = {}
|
||||
|
||||
tbl_str[#tbl_str + 1] = '{'
|
||||
|
||||
for ind,val in pairs(tbl) do -- serialize its fields
|
||||
if type(ind) == "number" then
|
||||
tbl_str[#tbl_str + 1] = '['
|
||||
tbl_str[#tbl_str + 1] = tostring(ind)
|
||||
tbl_str[#tbl_str + 1] = ']='
|
||||
else --must be a string
|
||||
tbl_str[#tbl_str + 1] = '['
|
||||
tbl_str[#tbl_str + 1] = routines.utils.basicSerialize(ind)
|
||||
tbl_str[#tbl_str + 1] = ']='
|
||||
end
|
||||
|
||||
if ((type(val) == 'number') or (type(val) == 'boolean')) then
|
||||
tbl_str[#tbl_str + 1] = tostring(val)
|
||||
tbl_str[#tbl_str + 1] = ','
|
||||
elseif type(val) == 'string' then
|
||||
tbl_str[#tbl_str + 1] = routines.utils.basicSerialize(val)
|
||||
tbl_str[#tbl_str + 1] = ','
|
||||
elseif type(val) == 'nil' then -- won't ever happen, right?
|
||||
tbl_str[#tbl_str + 1] = 'nil,'
|
||||
elseif type(val) == 'table' then
|
||||
if ind == "__index" then
|
||||
tbl_str[#tbl_str + 1] = "__index"
|
||||
tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
|
||||
else
|
||||
tbl_str[#tbl_str + 1] = routines.utils.oneLineSerialize(val)
|
||||
tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
|
||||
end
|
||||
elseif type(val) == 'function' then
|
||||
tbl_str[#tbl_str + 1] = "function " .. tostring(ind)
|
||||
tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
|
||||
else
|
||||
env.info('unable to serialize value type ' .. routines.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind))
|
||||
env.info( debug.traceback() )
|
||||
end
|
||||
|
||||
end
|
||||
tbl_str[#tbl_str + 1] = '}'
|
||||
return table.concat(tbl_str)
|
||||
else
|
||||
return tostring(tbl)
|
||||
end
|
||||
end
|
||||
|
||||
--porting in Slmod's "safestring" basic serialize
|
||||
routines.utils.basicSerialize = function(s)
|
||||
if s == nil then
|
||||
return "\"\""
|
||||
else
|
||||
if ((type(s) == 'number') or (type(s) == 'boolean') or (type(s) == 'function') or (type(s) == 'table') or (type(s) == 'userdata') ) then
|
||||
return tostring(s)
|
||||
elseif type(s) == 'string' then
|
||||
s = string.format('%q', s)
|
||||
return s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- From http://lua-users.org/wiki/SimpleRound
|
||||
-- use negative idp for rounding ahead of decimal place, positive for rounding after decimal place
|
||||
@ -280,6 +296,9 @@ routines.vec.rotateVec2 = function(vec2, theta)
|
||||
end
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
-- acc- the accuracy of each easting/northing. 0, 1, 2, 3, 4, or 5.
|
||||
routines.tostringMGRS = function(MGRS, acc)
|
||||
if acc == 0 then
|
||||
@ -1521,85 +1540,48 @@ trace.r( "", "", { TransportZoneResult } )
|
||||
end
|
||||
|
||||
|
||||
function routines.IsUnitInRadius( CargoUnit, ReferenceGroup, Radius )
|
||||
function routines.IsUnitInRadius( CargoUnit, ReferencePosition, Radius )
|
||||
trace.f()
|
||||
|
||||
local Valid = true
|
||||
|
||||
-- fill-up some local variables to support further calculations to determine location of units within the zone.
|
||||
local CargoPos = CargoUnit:getPosition().p
|
||||
local ReferenceGroupPos = ReferenceGroup:getUnits()[1]:getPosition().p
|
||||
local ReferenceP = ReferencePosition.p
|
||||
|
||||
if (((CargoPos.x - ReferenceGroupPos.x)^2 + (CargoPos.z - ReferenceGroupPos.z)^2)^0.5 <= Radius) then
|
||||
if (((CargoPos.x - ReferenceP.x)^2 + (CargoPos.z - ReferenceP.z)^2)^0.5 <= Radius) then
|
||||
else
|
||||
Valid = false
|
||||
end
|
||||
|
||||
trace.r( "", "", { Valid } )
|
||||
return Valid
|
||||
end
|
||||
|
||||
function routines.IsPartOfGroupInRadius( CargoGroup, ReferenceGroup, Radius )
|
||||
function routines.IsPartOfGroupInRadius( CargoGroup, ReferencePosition, Radius )
|
||||
trace.f()
|
||||
|
||||
local Valid = true
|
||||
|
||||
Valid = routines.ValidateGroup( CargoGroup, "CargoGroup", Valid )
|
||||
Valid = routines.ValidateGroup( ReferenceGroup, "ReferenceGroup", Valid )
|
||||
|
||||
-- fill-up some local variables to support further calculations to determine location of units within the zone
|
||||
local CargoUnits = CargoGroup:getUnits()
|
||||
for CargoUnitId, CargoUnit in pairs( CargoUnits ) do
|
||||
local CargoUnitPos = CargoUnit:getPosition().p
|
||||
-- env.info( 'routines.IsPartOfGroupInRadius: CargoUnitPos.x = ' .. CargoUnitPos.x .. ' CargoUnitPos.z = ' .. CargoUnitPos.z )
|
||||
local ReferenceGroupPos = ReferenceGroup:getUnits()[1]:getPosition().p
|
||||
local ReferenceP = ReferencePosition.p
|
||||
-- env.info( 'routines.IsPartOfGroupInRadius: ReferenceGroupPos.x = ' .. ReferenceGroupPos.x .. ' ReferenceGroupPos.z = ' .. ReferenceGroupPos.z )
|
||||
|
||||
if ((( CargoUnitPos.x - ReferenceGroupPos.x)^2 + (CargoUnitPos.z - ReferenceGroupPos.z)^2)^0.5 <= Radius) then
|
||||
if ((( CargoUnitPos.x - ReferenceP.x)^2 + (CargoUnitPos.z - ReferenceP.z)^2)^0.5 <= Radius) then
|
||||
else
|
||||
Valid = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
trace.r( "", "", { Valid } )
|
||||
return Valid
|
||||
end
|
||||
|
||||
function routines.DestroyGroupInRadiusFromGroup( CargoGroup, ReferenceGroup, Radius )
|
||||
trace.f()
|
||||
|
||||
local Valid = true
|
||||
|
||||
Valid = routines.ValidateGroup( CargoGroup, "CargoGroup", Valid )
|
||||
Valid = routines.ValidateGroup( ReferenceGroup, "ReferenceGroup", Valid )
|
||||
|
||||
if Valid then
|
||||
-- fill-up some local variables to support further calculations to determine location of units within the zone
|
||||
local CargoUnits = CargoGroup:getUnits()
|
||||
local AliveCargoUnits = #CargoUnits
|
||||
for CargoUnitId, CargoUnit in pairs( CargoUnits ) do
|
||||
local CargoUnitPos = CargoUnit:getPosition().p
|
||||
-- env.info( 'routines.DestroyGroupInRadiusFromGroup: CargoUnitPos.x = ' .. CargoUnitPos.x .. ' CargoUnitPos.z = ' .. CargoUnitPos.z )
|
||||
local ReferenceGroupPos = ReferenceGroup:getUnits()[1]:getPosition().p
|
||||
-- env.info( 'routines.DestroyGroupInRadiusFromGroup: ReferenceGroupPos.x = ' .. ReferenceGroupPos.x .. ' ReferenceGroupPos.z = ' .. ReferenceGroupPos.z )
|
||||
|
||||
if ((( CargoUnitPos.x - ReferenceGroupPos.x)^2 + (CargoUnitPos.z - ReferenceGroupPos.z)^2)^0.5 <= Radius) then
|
||||
CargoUnit:destroy()
|
||||
AliveCargoUnits = AliveCargoUnits - 1
|
||||
else
|
||||
Valid = false
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
AliveCargoUnits = -1
|
||||
end
|
||||
|
||||
trace.r( "", "", { AliveCargoUnits } )
|
||||
return AliveCargoUnits
|
||||
end
|
||||
|
||||
|
||||
function routines.ValidateString( Variable, VariableName, Valid )
|
||||
trace.f()
|
||||
@ -1866,6 +1848,23 @@ routines.ground.patrol = function(gpData, pType, form, speed)
|
||||
return
|
||||
end
|
||||
|
||||
function routines.GetUnitHeight( CheckUnit )
|
||||
trace.f( "routines" )
|
||||
|
||||
local UnitPoint = CheckUnit:getPoint()
|
||||
local UnitPosition = { x = UnitPoint.x, y = UnitPoint.z }
|
||||
local UnitHeight = UnitPoint.y
|
||||
|
||||
local LandHeight = land.getHeight( UnitPosition )
|
||||
|
||||
--env.info(( 'CarrierHeight: LandHeight = ' .. LandHeight .. ' CarrierHeight = ' .. CarrierHeight ))
|
||||
|
||||
trace.f( "routines", "Unit Height = " .. UnitHeight - LandHeight )
|
||||
|
||||
return UnitHeight - LandHeight
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
Su34Status = { status = {} }
|
||||
@ -2399,7 +2398,7 @@ trace.f()
|
||||
|
||||
--env.info(( 'CarrierHeight: LandHeight = ' .. LandHeight .. ' CarrierHeight = ' .. CarrierHeight ))
|
||||
|
||||
return CarrierHeight - LandHeight
|
||||
return UnitHeight - LandHeight
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -30,51 +30,48 @@ SEAD = {
|
||||
-- -- Defends the Russian SA installations from SEAD attacks.
|
||||
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
|
||||
function SEAD:New( SEADGroupPrefixes )
|
||||
trace.f(self.ClassName, SEADGroupPrefixes )
|
||||
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, BASE:New() )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:T( SEADGroupPrefixes )
|
||||
if type( SEADGroupPrefixes ) == 'table' then
|
||||
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
||||
Child.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
|
||||
self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
|
||||
end
|
||||
else
|
||||
Child.SEADGroupNames[SEADGroupPrefixes] = SEADGroupPrefixes
|
||||
self.SEADGroupNames[SEADGroupPrefixes] = SEADGroupPrefixes
|
||||
end
|
||||
Child.AddEvent( Child, world.event.S_EVENT_SHOT, Child.EventShot )
|
||||
Child.EnableEvents( Child )
|
||||
self.AddEvent( self, world.event.S_EVENT_SHOT, self.EventShot )
|
||||
self.EnableEvents( self )
|
||||
|
||||
return Child
|
||||
return self
|
||||
end
|
||||
|
||||
--- Detects if an SA site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
|
||||
-- @see SEAD
|
||||
function SEAD:EventShot( event )
|
||||
trace.f( self.ClassName, { event } )
|
||||
self:T( { event } )
|
||||
|
||||
local _grp = Unit.getGroup(event.initiator)-- Identify the group that fired
|
||||
local _groupname = _grp:getName() -- return the name of the group
|
||||
local _unittable = {event.initiator:getName()} -- return the name of the units in the group
|
||||
local _SEADmissile = event.weapon -- Identify the weapon fired
|
||||
local _SEADmissileName = _SEADmissile:getTypeName() -- return weapon type
|
||||
--trigger.action.outText( string.format("Alerte, depart missile " ..string.format(_SEADmissileName)), 20) --debug message
|
||||
local SEADUnit = event.initiator
|
||||
local SEADUnitName = SEADUnit:getName()
|
||||
local SEADWeapon = event.weapon -- Identify the weapon fired
|
||||
local SEADWeaponName = SEADWeapon:getTypeName() -- return weapon type
|
||||
--trigger.action.outText( string.format("Alerte, depart missile " ..string.format(SEADWeaponName)), 20) --debug message
|
||||
-- Start of the 2nd loop
|
||||
trace.i( self.ClassName, "Missile Launched = " .. _SEADmissileName )
|
||||
if _SEADmissileName == "KH-58" or _SEADmissileName == "KH-25MPU" or _SEADmissileName == "AGM-88" or _SEADmissileName == "KH-31A" or _SEADmissileName == "KH-31P" then -- Check if the missile is a SEAD
|
||||
self:T( "Missile Launched = " .. SEADWeaponName )
|
||||
if SEADWeaponName == "KH-58" or SEADWeaponName == "KH-25MPU" or SEADWeaponName == "AGM-88" or SEADWeaponName == "KH-31A" or SEADWeaponName == "KH-31P" then -- Check if the missile is a SEAD
|
||||
local _evade = math.random (1,100) -- random number for chance of evading action
|
||||
local _targetMim = Weapon.getTarget(_SEADmissile) -- Identify target
|
||||
local _targetMim = Weapon.getTarget(SEADWeapon) -- Identify target
|
||||
local _targetMimname = Unit.getName(_targetMim)
|
||||
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(_SEADmissile))
|
||||
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon))
|
||||
local _targetMimgroupName = _targetMimgroup:getName()
|
||||
local _targetMimcont= _targetMimgroup:getController()
|
||||
local _targetskill = _Database.Units[_targetMimname].Template.skill
|
||||
trace.i( self.ClassName, self.SEADGroupPrefixes )
|
||||
trace.i( self.ClassName, _targetMimgroupName )
|
||||
self:T( self.SEADGroupPrefixes )
|
||||
self:T( _targetMimgroupName )
|
||||
local SEADGroupFound = false
|
||||
for SEADGroupPrefixID, SEADGroupPrefix in pairs( self.SEADGroupPrefixes ) do
|
||||
if string.find( _targetMimgroupName, SEADGroupPrefix, 1, true ) then
|
||||
SEADGroupFound = true
|
||||
trace.i( self.ClassName, 'Group Found' )
|
||||
self:T( 'Group Found' )
|
||||
break
|
||||
end
|
||||
end
|
||||
@ -83,15 +80,15 @@ trace.f( self.ClassName, { event } )
|
||||
local Skills = { "Average", "Good", "High", "Excellent" }
|
||||
_targetskill = Skills[ math.random(1,4) ]
|
||||
end
|
||||
trace.i( self.ClassName, _targetskill ) -- debug message for skill check
|
||||
self:T( _targetskill ) -- debug message for skill check
|
||||
if self.TargetSkill[_targetskill] then
|
||||
if (_evade > self.TargetSkill[_targetskill].Evade) then
|
||||
trace.i( self.ClassName, string.format("Evading, target skill " ..string.format(_targetskill)) ) --debug message
|
||||
local _targetMim = Weapon.getTarget(_SEADmissile)
|
||||
self:T( string.format("Evading, target skill " ..string.format(_targetskill)) ) --debug message
|
||||
local _targetMim = Weapon.getTarget(SEADWeapon)
|
||||
local _targetMimname = Unit.getName(_targetMim)
|
||||
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(_SEADmissile))
|
||||
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon))
|
||||
local _targetMimcont= _targetMimgroup:getController()
|
||||
routines.groupRandomDistSelf(_targetMimgroup,300,'Rank',250,20) -- move randomly
|
||||
routines.groupRandomDistSelf(_targetMimgroup,300,'Diamond',250,20) -- move randomly
|
||||
local SuppressedGroups1 = {} -- unit suppressed radar off for a random time
|
||||
local function SuppressionEnd1(id)
|
||||
id.ctrl:setOption(AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.GREEN)
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
--- A SLINGLOADHOOKTASK will orchestrate the sling-load hook activity to slingload a CARGO from a specific landing zone(s).
|
||||
-- @classmod SLINGLOADHOOKTASK
|
||||
|
||||
Include.File("Task")
|
||||
|
||||
SLINGLOADHOOKTASK = {
|
||||
ClassName = "SLINGLOADHOOKTASK",
|
||||
GoalVerb = "Hook and Sling Cargo"
|
||||
}
|
||||
|
||||
--- Creates a new SLINGLOADHOOKTASK.
|
||||
-- @tparam table{string,...}|string LandingZones Table or name of the zone(s) where Cargo is to be loaded.
|
||||
-- @tparam table{string,...)|string CargoPrefixes is the name or prefix of the name of the Cargo objects defined within the DCS ME.
|
||||
-- @treturn SLINGLOADHOOKTASK
|
||||
function SLINGLOADHOOKTASK:New( LandingZones, CargoPrefixes )
|
||||
trace.f(self.ClassName)
|
||||
|
||||
local self = BASE:Inherit( self, TASK:New() )
|
||||
|
||||
self.Name = 'Hook and Sling Cargo'
|
||||
self.TaskBriefing = "Task: Hook"
|
||||
|
||||
if type( LandingZones ) == "table" then
|
||||
self.LandingZones = LandingZones
|
||||
else
|
||||
self.LandingZones = { LandingZones }
|
||||
end
|
||||
|
||||
if type( CargoPrefixes ) == "table" then
|
||||
self.CargoPrefixes = CargoPrefixes
|
||||
else
|
||||
self.CargoPrefixes = { CargoPrefixes }
|
||||
end
|
||||
|
||||
self.Stages = { STAGEBRIEF:New(), STAGESTART:New(), STAGEROUTE:New(), STAGE_SLINGLOAD_HOOK:New(), STAGEDONE:New() }
|
||||
self:SetStage( 1 )
|
||||
|
||||
return self
|
||||
end
|
||||
@ -1,38 +0,0 @@
|
||||
--- A SLINGLOADUNHOOKTASK will orchestrate the sling-load unhook activity to (sling)load a CARGO and deploy it in a specific landing zone(s).
|
||||
-- @classmod SLINGLOADUNHOOKTASK
|
||||
|
||||
Include.File("Task")
|
||||
|
||||
SLINGLOADUNHOOKTASK = {
|
||||
ClassName = "SLINGLOADUNHOOKTASK",
|
||||
GoalVerb = "Sling and UnHook Cargo"
|
||||
}
|
||||
|
||||
--- Creates a new SLINGLOADUNHOOKTASK.
|
||||
-- @tparam table{string,...}|string LandingZones Table or name of the zone(s) where Cargo is to be loaded.
|
||||
-- @tparam table{string,...}|string CargoPrefixes is the name or prefix of the name of the Cargo objects defined within the DCS ME.
|
||||
function SLINGLOADUNHOOKTASK:New( LandingZones, CargoPrefixes )
|
||||
trace.f(self.ClassName)
|
||||
|
||||
local self = BASE:Inherit( self, TASK:New() )
|
||||
|
||||
self.Name = 'Sling and Unhook Cargo'
|
||||
self.TaskBriefing = "Task: UnHook"
|
||||
|
||||
if type( LandingZones ) == "table" then
|
||||
self.LandingZones = LandingZones
|
||||
else
|
||||
self.LandingZones = { LandingZones }
|
||||
end
|
||||
|
||||
if type( CargoPrefixes ) == "table" then
|
||||
self.CargoPrefixes = CargoPrefixes
|
||||
else
|
||||
self.CargoPrefixes = { CargoPrefixes }
|
||||
end
|
||||
|
||||
self.Stages = { STAGEBRIEF:New(), STAGESTART:New(), STAGEROUTE:New(), STAGE_SLINGLOAD_UNHOOK:New(), STAGEDONE:New() }
|
||||
self:SetStage( 1 )
|
||||
|
||||
return self
|
||||
end
|
||||
419
Moose/Spawn.lua
419
Moose/Spawn.lua
@ -2,9 +2,13 @@
|
||||
-- @classmod SPAWN
|
||||
-- @author Flightcontrol
|
||||
|
||||
MOOSE_Version = "0.1.1.1"
|
||||
|
||||
Include.File( "Routines" )
|
||||
Include.File( "Base" )
|
||||
Include.File( "Database" )
|
||||
Include.File( "Group" )
|
||||
|
||||
|
||||
SPAWN = {
|
||||
ClassName = "SPAWN",
|
||||
@ -23,10 +27,8 @@ SPAWN = {
|
||||
-- -- NATO helicopters engaging in the battle field.
|
||||
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' )
|
||||
function SPAWN:New( SpawnPrefix )
|
||||
trace.f(self.ClassName, SpawnPrefix)
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:T( SpawnPrefix)
|
||||
|
||||
local TemplateGroup = Group.getByName( SpawnPrefix )
|
||||
if TemplateGroup then
|
||||
@ -39,6 +41,7 @@ trace.f(self.ClassName, SpawnPrefix)
|
||||
self.UnControlled = false -- When working in UnControlled mode, all planes are Spawned in UnControlled mode before the scheduler starts.
|
||||
self.SpawnMaxGroupsAlive = 0 -- The maximum amount of groups that can be alive of SpawnPrefix at the same time.
|
||||
self.SpawnMaxGroups = 0 -- The maximum amount of groups that can be spawned.
|
||||
self.SpawnRandomize = false
|
||||
else
|
||||
error( "SPAWN:New: There is no group declared in the mission editor with SpawnPrefix = '" .. SpawnPrefix .. "'" )
|
||||
end
|
||||
@ -65,11 +68,12 @@ end
|
||||
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):RandomizeRoute( 2, 2, 2000 )
|
||||
|
||||
function SPAWN:RandomizeRoute( SpawnStartPoint, SpawnEndPoint, SpawnRadius )
|
||||
trace.f( self.ClassName, { SpawnStartPoint, SpawnEndPoint, SpawnRadius } )
|
||||
self:T( { SpawnStartPoint, SpawnEndPoint, SpawnRadius } )
|
||||
|
||||
self.SpawnStartPoint = SpawnStartPoint -- When the spawning occurs, randomize the route points from SpawnStartPoint.
|
||||
self.SpawnEndPoint = SpawnEndPoint -- When the spawning occurs, randomize the route points till SpawnEndPoint.
|
||||
self.SpawnRadius = SpawnRadius -- The Radius of randomization of the route points from SpawnStartPoint till SpawnEndPoint.
|
||||
self.SpawnRandomize = true
|
||||
|
||||
return self
|
||||
end
|
||||
@ -89,7 +93,7 @@ end
|
||||
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):Schedule( 600, 0.5 )
|
||||
|
||||
function SPAWN:Schedule( SpawnTime, SpawnTimeVariation )
|
||||
trace.f( self.ClassName, { SpawnTime, SpawnTimeVariation } )
|
||||
self:T( { SpawnTime, SpawnTimeVariation } )
|
||||
|
||||
self.SpawnCurrentTimer = 0 -- The internal timer counter to trigger a scheduled spawning of SpawnPrefix.
|
||||
self.SpawnSetTimer = 0 -- The internal timer value when a scheduled spawning of SpawnPrefix occurs.
|
||||
@ -103,7 +107,7 @@ trace.f( self.ClassName, { SpawnTime, SpawnTimeVariation } )
|
||||
self:ScheduleStart()
|
||||
end
|
||||
|
||||
trace.i( self.ClassName, { self.SpawnLowTimer, self.SpawnHighTimer } )
|
||||
self:T( { self.SpawnLowTimer, self.SpawnHighTimer } )
|
||||
|
||||
return self
|
||||
end
|
||||
@ -111,7 +115,7 @@ end
|
||||
--- Will start the SPAWNing timers.
|
||||
-- This function is called automatically when @{Schedule} is called.
|
||||
function SPAWN:ScheduleStart()
|
||||
trace.f( self.ClassName )
|
||||
self:T()
|
||||
|
||||
--local ClientUnit = #AlivePlayerUnits()
|
||||
|
||||
@ -128,7 +132,7 @@ end
|
||||
|
||||
--- Will stop the scheduled SPAWNing activity.
|
||||
function SPAWN:ScheduleStop()
|
||||
trace.f( self.ClassName )
|
||||
self:T()
|
||||
self.SpawnScheduled = false
|
||||
end
|
||||
|
||||
@ -146,7 +150,7 @@ end
|
||||
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):Limit( 2, 24 )
|
||||
|
||||
function SPAWN:Limit( SpawnMaxGroupsAlive, SpawnMaxGroups )
|
||||
trace.f( self.ClassName, { SpawnMaxGroupsAlive, SpawnMaxGroups } )
|
||||
self:T( { SpawnMaxGroupsAlive, SpawnMaxGroups } )
|
||||
|
||||
self.SpawnMaxGroupsAlive = SpawnMaxGroupsAlive -- The maximum amount of groups that can be alive of SpawnPrefix at the same time.
|
||||
self.SpawnMaxGroups = SpawnMaxGroups -- The maximum amount of groups that can be spawned.
|
||||
@ -173,7 +177,7 @@ end
|
||||
-- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):Limit( 12, 150 ):Schedule( 200, 0.4 ):RandomizeTemplate( Spawn_US_Platoon ):RandomizeRoute( 3, 3, 2000 )
|
||||
|
||||
function SPAWN:RandomizeTemplate( SpawnPrefixTable )
|
||||
trace.f( self.ClassName, { SpawnPrefix, SpawnPrefixTable } )
|
||||
self:T( { SpawnPrefix, SpawnPrefixTable } )
|
||||
|
||||
self.SpawnPrefixTable = SpawnPrefixTable
|
||||
|
||||
@ -190,7 +194,7 @@ end
|
||||
-- SpawnRU_SU34 = SPAWN:New( 'TF1 RU Su-34 Krymsk@AI - Attack Ships' ):Schedule( 2, 3, 1800, 0.4 ):SpawnUncontrolled():RandomizeRoute( 1, 1, 3000 ):RepeatOnEngineShutDown()
|
||||
|
||||
function SPAWN:Repeat()
|
||||
trace.f( self.ClassName )
|
||||
self:T()
|
||||
|
||||
self.SpawnRepeat = true
|
||||
self.RepeatOnEngineShutDown = false
|
||||
@ -209,7 +213,7 @@ end
|
||||
-- @see Repeat
|
||||
|
||||
function SPAWN:RepeatOnLanding()
|
||||
trace.f( self.ClassName )
|
||||
self:T()
|
||||
|
||||
self:Repeat()
|
||||
self.RepeatOnEngineShutDown = false
|
||||
@ -223,7 +227,7 @@ end
|
||||
-- @see Repeat
|
||||
|
||||
function SPAWN:RepeatOnEngineShutDown()
|
||||
trace.f( self.ClassName )
|
||||
self:T()
|
||||
|
||||
self:Repeat()
|
||||
self.RepeatOnEngineShutDown = true
|
||||
@ -232,15 +236,64 @@ trace.f( self.ClassName )
|
||||
return self
|
||||
end
|
||||
|
||||
function SPAWN:CleanUp( SpawnCleanUpInterval )
|
||||
self:T()
|
||||
|
||||
self.SpawnCleanUpInterval = SpawnCleanUpInterval
|
||||
self.SpawnCleanUpTimeStamps = {}
|
||||
self.CleanUpFunction = routines.scheduleFunction( self._SpawnCleanUpScheduler, { self }, timer.getTime() + 1, 60 )
|
||||
end
|
||||
|
||||
function SPAWN:_SpawnCleanUpScheduler()
|
||||
self:T()
|
||||
|
||||
local SpawnGroup = self:GetFirstAliveGroup()
|
||||
|
||||
while SpawnGroup do
|
||||
|
||||
if SpawnGroup:AllOnGround() and SpawnGroup:GetMaxVelocity() < 1 then
|
||||
if not self.SpawnCleanUpTimeStamps[SpawnGroup:GetName()] then
|
||||
self.SpawnCleanUpTimeStamps[SpawnGroup:GetName()] = timer.getTime()
|
||||
else
|
||||
if self.SpawnCleanUpTimeStamps[SpawnGroup:GetName()] + self.SpawnCleanUpInterval < timer.getTime() then
|
||||
SpawnGroup:Destroy()
|
||||
end
|
||||
end
|
||||
else
|
||||
self.SpawnCleanUpTimeStamps[SpawnGroup:GetName()] = nil
|
||||
end
|
||||
|
||||
SpawnGroup = self:GetNextAliveGroup()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Will SPAWN a Group whenever you want to do this.
|
||||
-- Note that the configuration with the above functions will apply when calling this method: Maxima, Randomization of routes, Scheduler, ...
|
||||
-- Uses @{DATABASE} global object defined in MOOSE.
|
||||
-- @treturn SPAWN
|
||||
function SPAWN:Spawn()
|
||||
trace.f( self.ClassName )
|
||||
local SpawnTemplate = self:_Prepare( true )
|
||||
if self.SpawnStartPoint ~= 0 or self.SpawnEndPoint ~= 0 then
|
||||
function SPAWN:Spawn( SpawnGroupName )
|
||||
self:T( { self.SpawnPrefix, SpawnGroupName } )
|
||||
local SpawnTemplate = self:_Prepare( SpawnGroupName )
|
||||
if self.SpawnRandomize then
|
||||
SpawnTemplate = self:_RandomizeRoute( SpawnTemplate )
|
||||
end
|
||||
_Database:Spawn( SpawnTemplate )
|
||||
if self.SpawnRepeat then
|
||||
_Database:SetStatusGroup( SpawnTemplate.name, "ReSpawn" )
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Will SPAWN a Group with a specified index number whenever you want to do this.
|
||||
-- Note that the configuration with the above functions will apply when calling this method: Maxima, Randomization of routes, Scheduler, ...
|
||||
-- Uses @{DATABASE} global object defined in MOOSE.
|
||||
-- @treturn SPAWN
|
||||
function SPAWN:SpawnWithIndex( SpawnIndex )
|
||||
self:T( { self.SpawnPrefix, SpawnIndex } )
|
||||
local SpawnTemplate = self:_Prepare( self:SpawnGroupName( SpawnIndex ) )
|
||||
if self.SpawnRandomize then
|
||||
SpawnTemplate = self:_RandomizeRoute( SpawnTemplate )
|
||||
end
|
||||
_Database:Spawn( SpawnTemplate )
|
||||
@ -257,12 +310,15 @@ end
|
||||
-- @treturn SPAWN
|
||||
-- Uses _Database global object defined in MOOSE.
|
||||
function SPAWN:ReSpawn( SpawnGroupName )
|
||||
trace.f( self.ClassName, { SpawnGroupName } )
|
||||
self:T( { SpawnGroupName } )
|
||||
|
||||
local SpawnGroup = Group.getByName( SpawnGroupName )
|
||||
SpawnGroup:destroy()
|
||||
local SpawnTemplate = self:_Prepare( false )
|
||||
-- Give the Group the original name of the Group.
|
||||
SpawnTemplate.name = SpawnGroupName
|
||||
if SpawnGroup then
|
||||
SpawnGroup:destroy()
|
||||
end
|
||||
|
||||
local SpawnTemplate = self:_Prepare( SpawnGroupName )
|
||||
|
||||
-- Give the units of the Group the name following the SPAWN naming convention, so that they don't replace other units within the ME.
|
||||
local SpawnUnits = table.getn( SpawnTemplate.units )
|
||||
for u = 1, SpawnUnits do
|
||||
@ -276,13 +332,13 @@ end
|
||||
--- Will SPAWN a Group whenever you want to do this, but for AIR Groups only to be applied, and will SPAWN the Group in Uncontrolled mode... This will be similar to the Uncontrolled flag setting in the ME.
|
||||
-- @treturn SPAWN
|
||||
function SPAWN:SpawnUncontrolled()
|
||||
trace.f( self.ClassName )
|
||||
self:T()
|
||||
|
||||
self.UnControlled = true
|
||||
|
||||
local SpawnCountStart = self.SpawnCount + 1
|
||||
for SpawnCount = SpawnCountStart, self.SpawnMaxGroups do
|
||||
local SpawnTemplate = self:_Prepare( true )
|
||||
local SpawnTemplate = self:_Prepare( )
|
||||
SpawnTemplate.uncontrolled = true
|
||||
_Database:Spawn( SpawnTemplate )
|
||||
end
|
||||
@ -293,94 +349,212 @@ end
|
||||
|
||||
|
||||
--- Will SPAWN a Group from a Carrier. This function is mostly advisable to be used if you want to simulate SPAWNing from air units, like helicopters, which are dropping infantry into a defined Landing Zone.
|
||||
-- @tparam Group CarrierGroup is the Group of the AIR unit or GROUND unit dropping or unloading other units.
|
||||
-- @tparam Group HostUnit is the AIR unit or GROUND unit dropping or unloading the Spawn group.
|
||||
-- @tparam string TargetZonePrefix is the Prefix of the Zone defined in the ME where the Group should be moving to after drop.
|
||||
-- @tparam string NewGroupName (forgot this).
|
||||
-- @tparam bool LateActivate (optional) does the SPAWNing with Lateactivation on.
|
||||
function SPAWN:FromCarrier( CarrierGroup, TargetZonePrefix, NewGroupName, LateActivate )
|
||||
trace.f( self.ClassName, { CarrierGroup, TargetZonePrefix, NewGroupName, LateActivate } )
|
||||
function SPAWN:FromHost( HostUnit, OuterRadius, InnerRadius, NewGroupName, LateActivate )
|
||||
self:T( { HostUnit, OuterRadius, InnerRadius, NewGroupName, LateActivate } )
|
||||
|
||||
local SpawnTemplate
|
||||
|
||||
if CarrierGroup and CarrierGroup:isExist() and CarrierGroup:getUnit(1) then -- and CarrierGroup:getUnit(1):inAir() == false then
|
||||
if HostUnit and HostUnit:isExist() then -- and HostUnit:getUnit(1):inAir() == false then
|
||||
|
||||
local GroupUnits = CarrierGroup:getUnits()
|
||||
local GroupUnitCount = table.getn(GroupUnits)
|
||||
trace.i( self.ClassName, "CarrierGroup:getSize() = " .. CarrierGroup:getSize() )
|
||||
trace.i( self.ClassName, 'GroupUnitCount = ' .. GroupUnitCount )
|
||||
|
||||
for UnitId, UnitData in pairs(GroupUnits) do
|
||||
SpawnTemplate = self:_Prepare( NewGroupName )
|
||||
|
||||
UnitDeploy = UnitData
|
||||
|
||||
SpawnTemplate = self:_Prepare( true )
|
||||
|
||||
if ( self.SpawnMaxGroups == 0 ) or ( self.SpawnCount <= self.SpawnMaxGroups ) then
|
||||
if ( self.SpawnMaxGroupsAlive == 0 ) or ( self.AliveUnits < self.SpawnMaxGroupsAlive * #self.SpawnTemplate.units ) or self.UnControlled then
|
||||
if ( self.SpawnMaxGroups == 0 ) or ( self.SpawnCount <= self.SpawnMaxGroups ) then
|
||||
if ( self.SpawnMaxGroupsAlive == 0 ) or ( self.AliveUnits < self.SpawnMaxGroupsAlive * #self.SpawnTemplate.units ) or self.UnControlled then
|
||||
|
||||
if NewGroupName ~= nil then
|
||||
SpawnTemplate.name = NewGroupName
|
||||
if LateActivate ~= nil then
|
||||
if LateActivate == true then
|
||||
SpawnTemplate.lateActivation = true
|
||||
SpawnTemplate.visible = true
|
||||
end
|
||||
|
||||
if LateActivate ~= nil then
|
||||
if LateActivate == true then
|
||||
SpawnTemplate.lateActivation = true
|
||||
SpawnTemplate.visible = true
|
||||
end
|
||||
end
|
||||
|
||||
SpawnTemplate = self:_RandomizeRoute( SpawnTemplate )
|
||||
|
||||
local TargetZone = trigger.misc.getZone( TargetZonePrefix )
|
||||
local TargetZonePos = {}
|
||||
TargetZonePos.x = TargetZone.point.x + math.random(TargetZone.radius * -1, TargetZone.radius)
|
||||
TargetZonePos.z = TargetZone.point.z + math.random(TargetZone.radius * -1, TargetZone.radius)
|
||||
|
||||
local RouteCount = table.getn( SpawnTemplate.route.points )
|
||||
trace.i( self.ClassName, "RouteCount = " .. RouteCount )
|
||||
|
||||
local UnitDeployPosition = UnitDeploy:getPoint()
|
||||
SpawnTemplate.route.points[1].x = UnitDeployPosition.x - 50
|
||||
SpawnTemplate.route.points[1].y = UnitDeployPosition.z
|
||||
SpawnTemplate.route.points[1].alt = nil
|
||||
SpawnTemplate.route.points[1].alt_type = nil
|
||||
|
||||
if SpawnStartPoint ~= 0 and SpawnEndPoint ~= 0 then
|
||||
SpawnTemplate.route.points[RouteCount].x = TargetZonePos.x
|
||||
SpawnTemplate.route.points[RouteCount].y = TargetZonePos.z
|
||||
else
|
||||
SpawnTemplate.route.points[RouteCount].x = TargetZone.point.x
|
||||
SpawnTemplate.route.points[RouteCount].y = TargetZone.point.z
|
||||
end
|
||||
|
||||
trace.i( self.ClassName, 'SpawnTemplate.route.points['..RouteCount..'].x = ' .. SpawnTemplate.route.points[RouteCount].x .. ', SpawnTemplate.route.points['..RouteCount..'].y = ' .. SpawnTemplate.route.points[RouteCount].y )
|
||||
|
||||
for v = 1, table.getn( SpawnTemplate.units ) do
|
||||
local SpawnPos = routines.getRandPointInCircle( UnitDeployPosition, 40, 10 )
|
||||
SpawnTemplate.units[v].x = SpawnPos.x
|
||||
SpawnTemplate.units[v].y = SpawnPos.y
|
||||
trace.i( self.ClassName, 'SpawnTemplate.units['..v..'].x = ' .. SpawnTemplate.units[v].x .. ', SpawnTemplate.units['..v..'].y = ' .. SpawnTemplate.units[v].y )
|
||||
end
|
||||
|
||||
_Database:Spawn( SpawnTemplate )
|
||||
end
|
||||
|
||||
SpawnTemplate = self:_RandomizeRoute( SpawnTemplate )
|
||||
|
||||
local RouteCount = table.getn( SpawnTemplate.route.points )
|
||||
self:T( "RouteCount = " .. RouteCount )
|
||||
|
||||
local UnitDeployPosition = HostUnit:getPoint()
|
||||
for PointID, Point in pairs( SpawnTemplate.route.points ) do
|
||||
Point.x = UnitDeployPosition.x
|
||||
Point.y = UnitDeployPosition.z
|
||||
Point.alt = nil
|
||||
Point.alt_type = nil
|
||||
end
|
||||
|
||||
for v = 1, table.getn( SpawnTemplate.units ) do
|
||||
local SpawnPos = routines.getRandPointInCircle( UnitDeployPosition, OuterRadius, InnerRadius )
|
||||
SpawnTemplate.units[v].x = SpawnPos.x
|
||||
SpawnTemplate.units[v].y = SpawnPos.y
|
||||
self:T( 'SpawnTemplate.units['..v..'].x = ' .. SpawnTemplate.units[v].x .. ', SpawnTemplate.units['..v..'].y = ' .. SpawnTemplate.units[v].y )
|
||||
end
|
||||
|
||||
_Database:Spawn( SpawnTemplate )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
trace.r( self.ClassName, "" )
|
||||
return SpawnTemplate
|
||||
end
|
||||
|
||||
--- Will SPAWN a Group from a Carrier. This function is mostly advisable to be used if you want to simulate SPAWNing from air units, like helicopters, which are dropping infantry into a defined Landing Zone.
|
||||
-- @tparam Group CarrierUnit is the AIR unit or GROUND unit dropping or unloading the Spawn group.
|
||||
-- @tparam string TargetZonePrefix is the Prefix of the Zone defined in the ME where the Group should be moving to after drop.
|
||||
-- @tparam string NewGroupName (forgot this).
|
||||
-- @tparam bool LateActivate (optional) does the SPAWNing with Lateactivation on.
|
||||
function SPAWN:FromCarrier( CarrierUnit, TargetZonePrefix, NewGroupName, LateActivate )
|
||||
self:T( { CarrierUnit, TargetZonePrefix, NewGroupName, LateActivate } )
|
||||
|
||||
local SpawnTemplate
|
||||
|
||||
if CarrierUnit and CarrierUnit:isExist() then -- and CarrierUnit:getUnit(1):inAir() == false then
|
||||
|
||||
SpawnTemplate = self:_Prepare( NewGroupName )
|
||||
|
||||
if ( self.SpawnMaxGroups == 0 ) or ( self.SpawnCount <= self.SpawnMaxGroups ) then
|
||||
if ( self.SpawnMaxGroupsAlive == 0 ) or ( self.AliveUnits < self.SpawnMaxGroupsAlive * #self.SpawnTemplate.units ) or self.UnControlled then
|
||||
|
||||
if LateActivate ~= nil then
|
||||
if LateActivate == true then
|
||||
SpawnTemplate.lateActivation = true
|
||||
SpawnTemplate.visible = true
|
||||
end
|
||||
end
|
||||
|
||||
SpawnTemplate = self:_RandomizeRoute( SpawnTemplate )
|
||||
|
||||
local TargetZone = trigger.misc.getZone( TargetZonePrefix )
|
||||
local TargetZonePos = {}
|
||||
TargetZonePos.x = TargetZone.point.x + math.random(TargetZone.radius / 2 * -1, TargetZone.radius / 2 )
|
||||
TargetZonePos.z = TargetZone.point.z + math.random(TargetZone.radius / 2 * -1, TargetZone.radius / 2 )
|
||||
|
||||
local RouteCount = table.getn( SpawnTemplate.route.points )
|
||||
self:T( "RouteCount = " .. RouteCount )
|
||||
|
||||
local UnitDeployPosition = CarrierUnit:getPosition().p
|
||||
SpawnTemplate.route.points[1].x = UnitDeployPosition.x - 50
|
||||
SpawnTemplate.route.points[1].y = UnitDeployPosition.z
|
||||
SpawnTemplate.route.points[1].alt = nil
|
||||
SpawnTemplate.route.points[1].alt_type = nil
|
||||
|
||||
if self.SpawnRandomize then
|
||||
SpawnTemplate.route.points[RouteCount].x = TargetZonePos.x
|
||||
SpawnTemplate.route.points[RouteCount].y = TargetZonePos.z
|
||||
else
|
||||
SpawnTemplate.route.points[RouteCount].x = TargetZone.point.x
|
||||
SpawnTemplate.route.points[RouteCount].y = TargetZone.point.z
|
||||
end
|
||||
|
||||
self:T( 'SpawnTemplate.route.points['..RouteCount..'].x = ' .. SpawnTemplate.route.points[RouteCount].x .. ', SpawnTemplate.route.points['..RouteCount..'].y = ' .. SpawnTemplate.route.points[RouteCount].y )
|
||||
|
||||
for v = 1, table.getn( SpawnTemplate.units ) do
|
||||
local SpawnPos = routines.getRandPointInCircle( UnitDeployPosition, 40, 10 )
|
||||
SpawnTemplate.units[v].x = SpawnPos.x
|
||||
SpawnTemplate.units[v].y = SpawnPos.y
|
||||
self:T( 'SpawnTemplate.units['..v..'].x = ' .. SpawnTemplate.units[v].x .. ', SpawnTemplate.units['..v..'].y = ' .. SpawnTemplate.units[v].y )
|
||||
end
|
||||
|
||||
_Database:Spawn( SpawnTemplate )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return SpawnTemplate
|
||||
end
|
||||
|
||||
|
||||
--- Will return the SpawnGroupName either with with a specific count number or without any count.
|
||||
-- @tparam number SpawnIndex is the number of the Group that is to be SPAWNed.
|
||||
-- @treturn string SpawnGroupName
|
||||
function SPAWN:SpawnGroupName( SpawnIndex )
|
||||
self:T( { self.SpawnPrefix, SpawnIndex } )
|
||||
|
||||
if SpawnIndex then
|
||||
self:T( string.format( '%s#%03d', self.SpawnPrefix, SpawnIndex ) )
|
||||
return string.format( '%s#%03d', self.SpawnPrefix, SpawnIndex )
|
||||
else
|
||||
self:T( self.SpawnPrefix )
|
||||
return self.SpawnPrefix
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SPAWN:GetIndexFromGroup( Group )
|
||||
self:T( { self.SpawnPrefix, Group } )
|
||||
|
||||
local IndexString = string.match( Group:GetName(), "#.*$" )
|
||||
local Index = tonumber( IndexString:sub(2) )
|
||||
|
||||
self:T( IndexString, Index )
|
||||
return Index
|
||||
|
||||
end
|
||||
|
||||
function SPAWN:GetLastIndex()
|
||||
|
||||
return self.SpawnCount
|
||||
end
|
||||
|
||||
|
||||
|
||||
function SPAWN:GetFirstAliveGroup()
|
||||
self:T()
|
||||
|
||||
self.SpawnIndex = 1
|
||||
for SpawnIndex = 1, self.SpawnCount do
|
||||
SpawnGroupName = self:SpawnGroupName( SpawnIndex )
|
||||
SpawnGroup = Group.getByName( SpawnGroupName )
|
||||
if SpawnGroup and SpawnGroup:isExist() then
|
||||
self.SpawnIndex = SpawnIndex
|
||||
return GROUP:New( SpawnGroup )
|
||||
end
|
||||
end
|
||||
|
||||
self.SpawnIndex = nil
|
||||
return nil
|
||||
end
|
||||
|
||||
function SPAWN:GetNextAliveGroup()
|
||||
self:T()
|
||||
|
||||
self.SpawnIndex = self.SpawnIndex + 1
|
||||
for SpawnIndex = self.SpawnIndex, self.SpawnCount do
|
||||
SpawnGroupName = self:SpawnGroupName( SpawnIndex )
|
||||
SpawnGroup = Group.getByName( SpawnGroupName )
|
||||
if SpawnGroup and SpawnGroup:isExist() then
|
||||
self.SpawnIndex = SpawnIndex
|
||||
return GROUP:New( SpawnGroup )
|
||||
end
|
||||
end
|
||||
|
||||
self.SpawnIndex = nil
|
||||
return nil
|
||||
end
|
||||
|
||||
function SPAWN:GetLastAliveGroup()
|
||||
self:T()
|
||||
|
||||
local LastGroupName = self:SpawnGroupName( self:GetLastIndex() )
|
||||
|
||||
return GROUP:New( Group.getByName( LastGroupName ) )
|
||||
end
|
||||
|
||||
--- Will SPAWN a Group within a given ZoneName.
|
||||
-- @tparam string ZonePrefix is the name of the zone where the Group is to be SPAWNed.
|
||||
-- @treturn SpawnTemplate
|
||||
function SPAWN:InZone( ZonePrefix )
|
||||
trace.f("Spawn", ZonePrefix )
|
||||
function SPAWN:InZone( ZonePrefix, SpawnGroupName )
|
||||
self:T( ZonePrefix )
|
||||
|
||||
local SpawnTemplate = self:_Prepare( true )
|
||||
local SpawnTemplate
|
||||
|
||||
if SpawnGroupName then
|
||||
SpawnTemplate = self:_Prepare( SpawnGroupName )
|
||||
else
|
||||
SpawnTemplate = self:_Prepare()
|
||||
end
|
||||
|
||||
local Zone = trigger.misc.getZone( ZonePrefix )
|
||||
local ZonePos = {}
|
||||
@ -443,7 +617,7 @@ end
|
||||
--- Gets the Group Template from the ME environment definition.
|
||||
-- This method used the @{DATABASE} object, which contains ALL initial and new SPAWNed object in MOOSE.
|
||||
function SPAWN:_GetTemplate( SpawnPrefix )
|
||||
trace.f( self.ClassName, SpawnPrefix )
|
||||
self:T( SpawnPrefix )
|
||||
|
||||
local SpawnTemplate = nil
|
||||
|
||||
@ -457,13 +631,13 @@ trace.f( self.ClassName, SpawnPrefix )
|
||||
SpawnTemplate.SpawnCategoryID = self:_GetGroupCategoryID( SpawnPrefix )
|
||||
SpawnTemplate.SpawnCountryID = self:_GetGroupCountryID( SpawnPrefix )
|
||||
|
||||
trace.r( self.ClassName, "", { SpawnTemplate } )
|
||||
self:T( { SpawnTemplate } )
|
||||
return SpawnTemplate
|
||||
end
|
||||
|
||||
--- Prepares the new Group Template before Spawning.
|
||||
function SPAWN:_Prepare( SpawnIncrement )
|
||||
trace.f( self.ClassName )
|
||||
function SPAWN:_Prepare( SpawnGroupName )
|
||||
self:T()
|
||||
|
||||
local SpawnCount
|
||||
local SpawnUnits
|
||||
@ -476,11 +650,14 @@ trace.f( self.ClassName )
|
||||
end
|
||||
|
||||
-- Increase the spawn counter for the group
|
||||
if SpawnIncrement == true then
|
||||
if SpawnGroupName then
|
||||
SpawnTemplate.name = SpawnGroupName
|
||||
else
|
||||
self.SpawnCount = self.SpawnCount + 1
|
||||
SpawnTemplate.name = self:SpawnGroupName( self.SpawnCount )
|
||||
end
|
||||
|
||||
SpawnTemplate.name = string.format( self.SpawnPrefix .. '#%03d', self.SpawnCount )
|
||||
|
||||
SpawnTemplate.groupId = nil
|
||||
SpawnTemplate.lateActivation = false
|
||||
if SpawnTemplate.SpawnCategoryID == Group.Category.GROUND then
|
||||
@ -501,32 +678,32 @@ trace.f( self.ClassName )
|
||||
|
||||
SpawnUnits = table.getn( SpawnTemplate.units )
|
||||
for u = 1, SpawnUnits do
|
||||
SpawnTemplate.units[u].name = string.format( self.SpawnPrefix .. '#%03d-%02d', self.SpawnCount, u )
|
||||
SpawnTemplate.units[u].name = string.format( SpawnTemplate.name .. '-%02d', u )
|
||||
SpawnTemplate.units[u].unitId = nil
|
||||
SpawnTemplate.units[u].x = SpawnTemplate.route.points[1].x
|
||||
SpawnTemplate.units[u].y = SpawnTemplate.route.points[1].y
|
||||
SpawnTemplate.units[u].x = SpawnTemplate.route.points[1].x + math.random( -50, 50 )
|
||||
SpawnTemplate.units[u].y = SpawnTemplate.route.points[1].y + math.random( -50, 50 )
|
||||
end
|
||||
|
||||
trace.r( self.ClassName, "", SpawnTemplate.name )
|
||||
self:T( SpawnTemplate.name )
|
||||
return SpawnTemplate
|
||||
end
|
||||
|
||||
--- Will randomize the route of the Group Template.
|
||||
function SPAWN:_RandomizeRoute( SpawnTemplate )
|
||||
trace.f( self.ClassName, SpawnTemplate.name )
|
||||
self:T( SpawnTemplate.name )
|
||||
|
||||
if self.SpawnStartPoint and self.SpawnEndPoint then
|
||||
if self.SpawnRandomize then
|
||||
local RouteCount = table.getn( SpawnTemplate.route.points )
|
||||
for t = self.SpawnStartPoint, RouteCount - self.SpawnEndPoint do
|
||||
for t = self.SpawnStartPoint+1, RouteCount - self.SpawnEndPoint do
|
||||
SpawnTemplate.route.points[t].x = SpawnTemplate.route.points[t].x + math.random( self.SpawnRadius * -1, self.SpawnRadius )
|
||||
SpawnTemplate.route.points[t].y = SpawnTemplate.route.points[t].y + math.random( self.SpawnRadius * -1, self.SpawnRadius )
|
||||
SpawnTemplate.route.points[t].alt = nil
|
||||
--SpawnGroup.route.points[t].alt_type = nil
|
||||
trace.i( self.ClassName, 'SpawnTemplate.route.points[' .. t .. '].x = ' .. SpawnTemplate.route.points[t].x .. ', SpawnTemplate.route.points[' .. t .. '].y = ' .. SpawnTemplate.route.points[t].y )
|
||||
self:T( 'SpawnTemplate.route.points[' .. t .. '].x = ' .. SpawnTemplate.route.points[t].x .. ', SpawnTemplate.route.points[' .. t .. '].y = ' .. SpawnTemplate.route.points[t].y )
|
||||
end
|
||||
end
|
||||
|
||||
trace.r( self.ClassName, "", SpawnTemplate.name )
|
||||
self:T( SpawnTemplate.name )
|
||||
return SpawnTemplate
|
||||
end
|
||||
|
||||
@ -536,16 +713,16 @@ end
|
||||
--- Obscolete
|
||||
-- @todo Need to delete this... _Database does this now ...
|
||||
function SPAWN:OnBirth( event )
|
||||
trace.f( self.ClassName, { event } )
|
||||
self:T( { event } )
|
||||
|
||||
if timer.getTime0() < timer.getAbsTime() then -- dont need to add units spawned in at the start of the mission if mist is loaded in init line
|
||||
if event.initiator and event.initiator:getName() then
|
||||
trace.l(self.ClassName, "OnBirth", "Birth object : " .. event.initiator:getName() )
|
||||
self:T( "Birth object : " .. event.initiator:getName() )
|
||||
local EventPrefix = string.match( event.initiator:getName(), ".*#" )
|
||||
if EventPrefix == self.SpawnPrefix .. '#' then
|
||||
--MessageToAll( "Mission command: unit " .. SpawnPrefix .. " spawned." , 5, EventPrefix .. '/Event')
|
||||
self.AliveUnits = self.AliveUnits + 1
|
||||
trace.l(self.ClassName, "OnBirth", self.AliveUnits )
|
||||
self:T( self.AliveUnits )
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -555,17 +732,17 @@ end
|
||||
--- Obscolete
|
||||
-- @todo Need to delete this... _Database does this now ...
|
||||
function SPAWN:OnDeadOrCrash( event )
|
||||
trace.f( self.ClassName, { event } )
|
||||
self:T( { event } )
|
||||
|
||||
if event.initiator and event.initiator:getName() then
|
||||
trace.l( self.ClassName, "OnDeadOrCrash", "Dead object : " .. event.initiator:getName() )
|
||||
self:T( "Dead object : " .. event.initiator:getName() )
|
||||
local EventPrefix = string.match( event.initiator:getName(), ".*#" )
|
||||
if EventPrefix == self.SpawnPrefix .. '#' then
|
||||
-- local DestroyedUnit = Unit.getByName( EventPrefix )
|
||||
-- if DestroyedUnit and DestroyedUnit.getLife() <= 1.0 then
|
||||
--MessageToAll( "Mission command: unit " .. SpawnPrefix .. " crashed." , 5, EventPrefix .. '/Event')
|
||||
self.AliveUnits = self.AliveUnits - 1
|
||||
trace.l( self.ClassName, "OnDeadOrCrash", self.AliveUnits )
|
||||
self:T( self.AliveUnits )
|
||||
-- end
|
||||
end
|
||||
end
|
||||
@ -575,17 +752,17 @@ end
|
||||
-- This is needed to ensure that Re-SPAWNing is only done for landed AIR Groups.
|
||||
-- @todo Need to test for AIR Groups only...
|
||||
function SPAWN:OnLand( event )
|
||||
trace.f( self.ClassName, { event } )
|
||||
self:T( { event } )
|
||||
|
||||
if event.initiator and event.initiator:getName() then
|
||||
trace.l( self.ClassName, "OnLand", "Landed object : " .. event.initiator:getName() )
|
||||
self:T( "Landed object : " .. event.initiator:getName() )
|
||||
local EventPrefix = string.match( event.initiator:getName(), ".*#" )
|
||||
if EventPrefix == self.SpawnPrefix .. '#' then
|
||||
self.Landed = true
|
||||
trace.l( self.ClassName, "OnLand", "self.Landed = true" )
|
||||
self:T( "self.Landed = true" )
|
||||
if self.Landed and self.RepeatOnLanding then
|
||||
local SpawnGroupName = Unit.getGroup(event.initiator):getName()
|
||||
trace.l( self.ClassName, "OnLand", "ReSpawn " .. SpawnGroupName )
|
||||
self:T( "ReSpawn " .. SpawnGroupName )
|
||||
self:ReSpawn( SpawnGroupName )
|
||||
end
|
||||
end
|
||||
@ -596,13 +773,13 @@ end
|
||||
-- This is needed to ensure that Re-SPAWNing only is done for landed AIR Groups.
|
||||
-- @todo Need to test for AIR Groups only...
|
||||
function SPAWN:OnTakeOff( event )
|
||||
trace.f( self.ClassName, { event } )
|
||||
self:T( { event } )
|
||||
|
||||
if event.initiator and event.initiator:getName() then
|
||||
trace.l( self.ClassName, "OnTakeOff", "TakeOff object : " .. event.initiator:getName() )
|
||||
self:T( "TakeOff object : " .. event.initiator:getName() )
|
||||
local EventPrefix = string.match( event.initiator:getName(), ".*#" )
|
||||
if EventPrefix == self.SpawnPrefix .. '#' then
|
||||
trace.l( self.ClassName, "OnTakeOff", "self.Landed = false" )
|
||||
self:T( "self.Landed = false" )
|
||||
self.Landed = false
|
||||
end
|
||||
end
|
||||
@ -615,15 +792,15 @@ end
|
||||
-- @see OnLand
|
||||
-- @todo Need to test for AIR Groups only...
|
||||
function SPAWN:OnEngineShutDown( event )
|
||||
trace.f( self.ClassName, { event } )
|
||||
self:T( { event } )
|
||||
|
||||
if event.initiator and event.initiator:getName() then
|
||||
trace.l( self.ClassName, "OnEngineShutDown", "EngineShutDown object : " .. event.initiator:getName() )
|
||||
self:T( "EngineShutDown object : " .. event.initiator:getName() )
|
||||
local EventPrefix = string.match( event.initiator:getName(), ".*#" )
|
||||
if EventPrefix == self.SpawnPrefix .. '#' then
|
||||
if self.Landed and self.RepeatOnEngineShutDown then
|
||||
local SpawnGroupName = Unit.getGroup(event.initiator):getName()
|
||||
trace.l( self.ClassName, "OnEngineShutDown", "ReSpawn " .. SpawnGroupName )
|
||||
self:T( "ReSpawn " .. SpawnGroupName )
|
||||
self:ReSpawn( SpawnGroupName )
|
||||
end
|
||||
end
|
||||
@ -636,7 +813,7 @@ end
|
||||
--- This function is called automatically by the Spawning scheduler.
|
||||
-- It is the internal worker method SPAWNing new Groups on the defined time intervals.
|
||||
function SPAWN:_Scheduler()
|
||||
trace.l( self.ClassName, '_Scheduler', self.SpawnPrefix )
|
||||
self:T( self.SpawnPrefix )
|
||||
|
||||
if self.SpawnInit or self.SpawnCurrentTimer == self.SpawnSetTimer then
|
||||
-- Validate if there are still groups left in the batch...
|
||||
|
||||
731
Moose/Stage.lua
731
Moose/Stage.lua
@ -27,13 +27,12 @@ STAGE = {
|
||||
|
||||
|
||||
function STAGE:New()
|
||||
trace.f(self.ClassName)
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:T()
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGE:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
|
||||
local Valid = true
|
||||
|
||||
@ -41,13 +40,10 @@ trace.f(self.ClassName)
|
||||
end
|
||||
|
||||
function STAGE:Executing( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
|
||||
end
|
||||
|
||||
function STAGE:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
|
||||
local Valid = true
|
||||
|
||||
return Valid
|
||||
@ -56,31 +52,30 @@ end
|
||||
|
||||
STAGEBRIEF = {
|
||||
ClassName = "BRIEF",
|
||||
MSG = { ID = "Brief", TIME = 30 },
|
||||
MSG = { ID = "Brief", TIME = 1 },
|
||||
Name = "Brief",
|
||||
StageBriefingTime = 0,
|
||||
StageBriefingDuration = 30
|
||||
StageBriefingDuration = 1
|
||||
}
|
||||
|
||||
function STAGEBRIEF:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, STAGE:New() )
|
||||
Child.StageType = 'CLIENT'
|
||||
return Child
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGEBRIEF:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
local Valid = BASE:Inherited(self):Execute( Mission, Client, Task )
|
||||
self:T()
|
||||
Mission:ShowBriefing( Client )
|
||||
self.StageBriefingTime = timer.getTime()
|
||||
return Valid
|
||||
end
|
||||
|
||||
function STAGEBRIEF:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
local Valid = STAGE:Validate( Mission, Client, Task )
|
||||
self:T()
|
||||
|
||||
if timer.getTime() - self.StageBriefingTime <= self.StageBriefingDuration then
|
||||
return 0
|
||||
@ -94,34 +89,33 @@ end
|
||||
|
||||
STAGESTART = {
|
||||
ClassName = "START",
|
||||
MSG = { ID = "Start", TIME = 30 },
|
||||
MSG = { ID = "Start", TIME = 1 },
|
||||
Name = "Start",
|
||||
StageStartTime = 0,
|
||||
StageStartDuration = 30
|
||||
StageStartDuration = 1
|
||||
}
|
||||
|
||||
function STAGESTART:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, STAGE:New() )
|
||||
Child.StageType = 'CLIENT'
|
||||
return Child
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGESTART:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
local Valid = BASE:Inherited(self):Execute( Mission, Client, Task )
|
||||
if Task.TaskBriefing then
|
||||
Client:Message( Task.TaskBriefing, self.StageStartDuration, Mission.Name .. "/Stage", "Mission Command: Tasking" )
|
||||
Client:Message( Task.TaskBriefing, 30, Mission.Name .. "/Stage", "Mission Command: Tasking" )
|
||||
else
|
||||
Client:Message( 'Task ' .. Task.TaskNumber .. '.', self.StageStartDuration, Mission.Name .. "/Stage", "Mission Command: Tasking" )
|
||||
Client:Message( 'Task ' .. Task.TaskNumber .. '.', 30, Mission.Name .. "/Stage", "Mission Command: Tasking" )
|
||||
end
|
||||
self.StageStartTime = timer.getTime()
|
||||
return Valid
|
||||
end
|
||||
|
||||
function STAGESTART:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
local Valid = STAGE:Validate( Mission, Client, Task )
|
||||
|
||||
if timer.getTime() - self.StageStartTime <= self.StageStartDuration then
|
||||
@ -135,17 +129,90 @@ trace.f(self.ClassName)
|
||||
|
||||
end
|
||||
|
||||
STAGE_CARGO_LOAD = {
|
||||
ClassName = "STAGE_CARGO_LOAD"
|
||||
}
|
||||
|
||||
function STAGE_CARGO_LOAD:New()
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGE_CARGO_LOAD:Execute( Mission, Client, Task )
|
||||
self:T()
|
||||
local Valid = BASE:Inherited(self):Execute( Mission, Client, Task )
|
||||
|
||||
for LoadCargoID, LoadCargo in pairs( Task.Cargos.LoadCargos ) do
|
||||
LoadCargo:Load( Client )
|
||||
end
|
||||
|
||||
if Mission.MissionReportFlash and Client:IsTransport() then
|
||||
Client:ShowCargo()
|
||||
end
|
||||
|
||||
return Valid
|
||||
end
|
||||
|
||||
function STAGE_CARGO_LOAD:Validate( Mission, Client, Task )
|
||||
self:T()
|
||||
local Valid = STAGE:Validate( Mission, Client, Task )
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
|
||||
STAGE_CARGO_INIT = {
|
||||
ClassName = "STAGE_CARGO_INIT"
|
||||
}
|
||||
|
||||
function STAGE_CARGO_INIT:New()
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGE_CARGO_INIT:Execute( Mission, Client, Task )
|
||||
self:T()
|
||||
local Valid = BASE:Inherited(self):Execute( Mission, Client, Task )
|
||||
|
||||
for InitLandingZoneID, InitLandingZone in pairs( Task.LandingZones.LandingZones ) do
|
||||
self:T( InitLandingZone )
|
||||
InitLandingZone:Spawn()
|
||||
end
|
||||
|
||||
|
||||
self:T( Task.Cargos.InitCargos )
|
||||
for InitCargoID, InitCargoData in pairs( Task.Cargos.InitCargos ) do
|
||||
self:T( { InitCargoData } )
|
||||
InitCargoData:Spawn()
|
||||
end
|
||||
|
||||
return Valid
|
||||
end
|
||||
|
||||
|
||||
function STAGE_CARGO_INIT:Validate( Mission, Client, Task )
|
||||
self:T()
|
||||
local Valid = STAGE:Validate( Mission, Client, Task )
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
|
||||
|
||||
STAGEROUTE = {
|
||||
ClassName = "STAGEROUTE",
|
||||
MSG = { ID = "Route", TIME = 1 },
|
||||
MSG = { ID = "Route", TIME = 5 },
|
||||
Frequency = STAGE.FREQUENCY.REPEAT,
|
||||
Name = "Route"
|
||||
}
|
||||
|
||||
function STAGEROUTE:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'CLIENT'
|
||||
self.MessageSwitch = true
|
||||
return self
|
||||
@ -153,19 +220,17 @@ end
|
||||
|
||||
|
||||
function STAGEROUTE:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
local Valid = BASE:Inherited(self):Execute( Mission, Client, Task )
|
||||
|
||||
if type( Task.LandingZones) == "table" then
|
||||
local RouteMessage = "Fly to "
|
||||
for LandingZoneID, LandingZoneName in pairs( Task.LandingZones ) do
|
||||
RouteMessage = RouteMessage .. LandingZoneName .. ' at ' .. routines.getBRStringZone( { zone = LandingZoneName, ref = Client:ClientGroup():getUnit(1):getPoint(), true, true } ) .. ' km. '
|
||||
end
|
||||
Client:Message( RouteMessage, self.MSG.TIME, Mission.Name .. "/StageRoute", "Co-Pilot: Route", 10 )
|
||||
else
|
||||
Client:Message( "Fly to " .. Task.LandingZones .. ' at ' .. routines.getBRStringZone( { zone = Task.LandingZones, ref = Client:ClientGroup():getUnit(1):getPoint(), true, true } ) .. ' km. ', self.MSG.TIME, Mission.Name .. "/StageRoute", "Co-Pilot: Route", 1 )
|
||||
local RouteMessage = "Fly to "
|
||||
self:T( Task.LandingZones )
|
||||
for LandingZoneID, LandingZoneName in pairs( Task.LandingZones.LandingZoneNames ) do
|
||||
RouteMessage = RouteMessage .. LandingZoneName .. ' at ' .. routines.getBRStringZone( { zone = LandingZoneName, ref = Client:GetClientGroupUnit():getPoint(), true, true } ) .. ' km. '
|
||||
end
|
||||
if Client:IsTransport() then
|
||||
Client:Message( RouteMessage, self.MSG.TIME, Mission.Name .. "/StageRoute", "Co-Pilot: Route", 20 )
|
||||
|
||||
if Mission.MissionReportFlash and Client:IsTransport() then
|
||||
Client:ShowCargo()
|
||||
end
|
||||
|
||||
@ -173,59 +238,32 @@ trace.f(self.ClassName)
|
||||
end
|
||||
|
||||
function STAGEROUTE:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
local Valid = STAGE:Validate( Mission, Client, Task )
|
||||
self:T()
|
||||
local Valid = STAGE:Validate( Mission, Client, Task )
|
||||
|
||||
-- check if the Client is in the landing zone
|
||||
self:T( Task.LandingZones.LandingZoneNames )
|
||||
Task.CurrentLandingZoneName = routines.IsUnitInZones( Client:GetClientGroupUnit(), Task.LandingZones.LandingZoneNames )
|
||||
|
||||
if Task.CurrentLandingZoneName then
|
||||
|
||||
-- check if this carrier is in the landing zone
|
||||
Task.CurrentLandingZoneID = routines.IsUnitInZones( Client:ClientGroup():getUnits()[1], Task.LandingZones )
|
||||
if ( Task.CurrentLandingZoneID ) then
|
||||
if not Task.Signalled then
|
||||
|
||||
if Task.LandingZoneSignalType then
|
||||
env.info( 'TransportSchedule: Task.LandingZoneSignalType = ' .. Task.LandingZoneSignalType.TEXT )
|
||||
if Task.LandingZoneSignalUnitNames then
|
||||
local LandingZoneSignalUnit = Task.LandingZoneSignalUnitNames[Task.CurrentLandingZoneID]
|
||||
trace.i( self.ClassName, 'LandingZoneSignalUnit = ' .. LandingZoneSignalUnit )
|
||||
|
||||
local SignalUnit = Unit.getByName(LandingZoneSignalUnit)
|
||||
if SignalUnit == nil then
|
||||
SignalUnit = StaticObject.getByName( LandingZoneSignalUnit )
|
||||
end
|
||||
if SignalUnit ~= nil then
|
||||
trace.i( self.ClassName, 'Signalling Unit' )
|
||||
local SignalVehiclePos = SignalUnit:getPosition().p
|
||||
SignalVehiclePos.y = SignalVehiclePos.y + Task.LandingZoneSignalHeight
|
||||
if Task.LandingZoneSignalType.ID == Task.SIGNAL.TYPE.SMOKE.ID then
|
||||
trigger.action.smoke( SignalVehiclePos, Task.LandingZoneSignalColor.COLOR )
|
||||
elseif Task.LandingZoneSignalType.ID == Task.SIGNAL.TYPE.FLARE.ID then
|
||||
trigger.action.signalFlare( SignalVehiclePos, Task.LandingZoneSignalColor.COLOR, 0 )
|
||||
end
|
||||
end
|
||||
else
|
||||
env.info( 'TransportSchedule: Signaling landing zone ' )
|
||||
|
||||
local LandingZone = trigger.misc.getZone( Task.LandingZones [ Task.CurrentLandingZoneID ] )
|
||||
local CurrentPosition = { x = LandingZone.point.x, y = LandingZone.point.z }
|
||||
LandingZone.point.y = land.getHeight( CurrentPosition ) + 10
|
||||
|
||||
if Task.LandingZoneSignalType.ID == Task.SIGNAL.TYPE.SMOKE.ID then
|
||||
env.info( 'TransportSchedule: Smoking zone x = ' .. LandingZone.point.x .. ' y = ' .. LandingZone.point.y .. ' z = ' .. LandingZone.point.z )
|
||||
trigger.action.smoke( LandingZone.point, Task.LandingZoneSignalColor.COLOR )
|
||||
elseif Task.LandingZoneSignalType.ID == Task.SIGNAL.TYPE.SMOKE.FLARE.ID then
|
||||
env.info( 'TransportSchedule: Flaring zone x = ' .. LandingZone.point.x .. ' y = ' .. LandingZone.point.y .. ' z = ' .. LandingZone.point.z )
|
||||
trigger.action.signalFlare( LandingZone.point, Task.LandingZoneSignalColor.COLOR, 0 )
|
||||
end
|
||||
Task.CurrentLandingZone = Task.LandingZones.LandingZones[Task.CurrentLandingZoneName].CargoZone
|
||||
Task.CurrentCargoZone = Task.LandingZones.LandingZones[Task.CurrentLandingZoneName]
|
||||
|
||||
if Task.CurrentCargoZone then
|
||||
if not Task.Signalled then
|
||||
Task.Signalled = Task.CurrentCargoZone:Signal()
|
||||
end
|
||||
end
|
||||
self.Signalled = true
|
||||
|
||||
return 1
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
return 0
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
|
||||
STAGELANDING = {
|
||||
ClassName = "STAGELANDING",
|
||||
MSG = { ID = "Landing", TIME = 10 },
|
||||
@ -234,37 +272,96 @@ STAGELANDING = {
|
||||
}
|
||||
|
||||
function STAGELANDING:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, STAGE:New() )
|
||||
Child.StageType = 'CLIENT'
|
||||
return Child
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGELANDING:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
Client:Message( 'We have arrived at ' .. Task.LandingZones[Task.CurrentLandingZoneID] .. '. Land the helicopter to ' .. Task.TEXT[1] .. ' the ' .. Task.CargoType.TEXT .. '.',
|
||||
self.MSG.TIME, Mission.Name .. "/Stage", "Co-Pilot: Landing" )
|
||||
|
||||
Client:Message( "We have arrived at the landing zone.", self.MSG.TIME, Mission.Name .. "/StageArrived", "Co-Pilot: Arrived", 10 )
|
||||
|
||||
Task.HostUnit = Task.CurrentCargoZone:GetHostUnit()
|
||||
|
||||
if Task.HostUnit then
|
||||
|
||||
Task.HostUnitName = Task.HostUnit:getName()
|
||||
Task.HostUnitTypeName = Task.HostUnit:getTypeName()
|
||||
|
||||
local HostMessage = ""
|
||||
Task.CargoNames = ""
|
||||
|
||||
local IsFirst = true
|
||||
|
||||
for CargoID, Cargo in pairs( CARGOS ) do
|
||||
if Cargo.CargoType == Task.CargoType then
|
||||
|
||||
if Cargo:IsLandingRequired() then
|
||||
self:T( "Task for cargo " .. Cargo.CargoType .. " requires landing.")
|
||||
Task.IsLandingRequired = true
|
||||
end
|
||||
|
||||
if Cargo:IsSlingLoad() then
|
||||
self:T( "Task for cargo " .. Cargo.CargoType .. " is a slingload.")
|
||||
Task.IsSlingLoad = true
|
||||
end
|
||||
|
||||
if IsFirst then
|
||||
IsFirst = false
|
||||
Task.CargoNames = Task.CargoNames .. Cargo.CargoName .. "( " .. Cargo.CargoWeight .. " )"
|
||||
else
|
||||
Task.CargoNames = Task.CargoNames .. "; " .. Cargo.CargoName .. "( " .. Cargo.CargoWeight .. " )"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if Task.IsLandingRequired then
|
||||
HostMessage = "Land the helicopter to " .. Task.TEXT[1] .. " " .. Task.CargoNames .. "."
|
||||
else
|
||||
HostMessage = "Use the Radio menu and F6 to find the cargo, then fly or land near the cargo and " .. Task.TEXT[1] .. " " .. Task.CargoNames .. "."
|
||||
end
|
||||
|
||||
Client:Message( HostMessage, self.MSG.TIME, Mission.Name .. "/STAGELANDING.EXEC." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" .. ":", 10 )
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function STAGELANDING:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
if routines.IsUnitInZones( Client:ClientGroup():getUnits()[1], Task.LandingZones[Task.CurrentLandingZoneID] ) then
|
||||
else
|
||||
Task.Signalled = false
|
||||
Task:RemoveCargoMenus( Client )
|
||||
return -1
|
||||
end
|
||||
Task.CurrentLandingZoneName = routines.IsUnitInZones( Client:GetClientGroupUnit(), Task.LandingZones.LandingZoneNames )
|
||||
if Task.CurrentLandingZoneName then
|
||||
|
||||
-- Client is in de landing zone.
|
||||
self:T( Task.CurrentLandingZoneName )
|
||||
|
||||
Task.CurrentLandingZone = Task.LandingZones.LandingZones[Task.CurrentLandingZoneName].CargoZone
|
||||
Task.CurrentCargoZone = Task.LandingZones.LandingZones[Task.CurrentLandingZoneName]
|
||||
|
||||
if Task.CurrentCargoZone then
|
||||
if not Task.Signalled then
|
||||
Task.Signalled = Task.CurrentCargoZone:Signal()
|
||||
end
|
||||
end
|
||||
else
|
||||
if Task.CurrentLandingZone then
|
||||
Task.CurrentLandingZone = nil
|
||||
end
|
||||
if Task.CurrentCargoZone then
|
||||
Task.CurrentCargoZone = nil
|
||||
end
|
||||
Task.Signalled = false
|
||||
Task:RemoveCargoMenus( Client )
|
||||
return -1
|
||||
end
|
||||
|
||||
if not Client:ClientGroup():getUnits()[1]:inAir() then
|
||||
else
|
||||
return 0
|
||||
end
|
||||
if Task.IsLandingRequired and Client:GetClientGroupUnit():inAir() then
|
||||
return 0
|
||||
end
|
||||
|
||||
return 1
|
||||
return 1
|
||||
end
|
||||
|
||||
STAGELANDED = {
|
||||
@ -275,46 +372,52 @@ STAGELANDED = {
|
||||
}
|
||||
|
||||
function STAGELANDED:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, STAGE:New() )
|
||||
Child.StageType = 'CLIENT'
|
||||
return Child
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGELANDED:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
Client:Message( 'We have landed within the landing zone. Use the radio menu (F10) to ' .. Task.TEXT[1] .. ' the ' .. Task.CargoType.TEXT .. '.', self.MSG.TIME, Mission.Name .. "/Stage", "Co-Pilot: Landed" )
|
||||
if not self.MenusAdded then
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task:AddCargoMenus( Client, Mission._Cargos, 250 )
|
||||
self:T()
|
||||
|
||||
if Task.IsLandingRequired then
|
||||
Client:Message( 'We have landed within the landing zone. Use the radio menu (F10) to ' .. Task.TEXT[1] .. ' the ' .. Task.CargoType .. '.',
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDED.EXEC." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" .. ":" )
|
||||
if not self.MenusAdded then
|
||||
Task.Cargo = nil
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task:AddCargoMenus( Client, CARGOS, 250 )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function STAGELANDED:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
if routines.IsUnitInZones( Client:ClientGroup():getUnits()[1], Task.LandingZones[Task.CurrentLandingZoneID] ) then
|
||||
else
|
||||
Task.Signalled = false
|
||||
Task:RemoveCargoMenus( Client )
|
||||
return -2
|
||||
end
|
||||
if not routines.IsUnitInZones( Client:GetClientGroupUnit(), Task.CurrentLandingZoneName ) then
|
||||
self:T( "Client is not anymore in the landing zone, go back to stage Route, and remove cargo menus." )
|
||||
Task.Signalled = false
|
||||
Task:RemoveCargoMenus( Client )
|
||||
return -2
|
||||
end
|
||||
|
||||
if not Client:ClientGroup():getUnits()[1]:inAir() then
|
||||
else
|
||||
Task.Signalled = false
|
||||
return -1
|
||||
end
|
||||
if Task.IsLandingRequired and Client:GetClientGroupUnit():inAir() then
|
||||
self:T( "Client went back in the air. Go back to stage Landing." )
|
||||
Task.Signalled = false
|
||||
return -1
|
||||
end
|
||||
|
||||
if Task.ExecuteStage == _TransportExecuteStage.EXECUTING then
|
||||
else
|
||||
return 0
|
||||
end
|
||||
-- Wait until cargo is selected from the menu.
|
||||
if Task.IsLandingRequired then
|
||||
if not Task.Cargo then
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
return 1
|
||||
return 1
|
||||
end
|
||||
|
||||
STAGEUNLOAD = {
|
||||
@ -324,72 +427,63 @@ STAGEUNLOAD = {
|
||||
}
|
||||
|
||||
function STAGEUNLOAD:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, STAGE:New() )
|
||||
Child.StageType = 'CLIENT'
|
||||
return Child
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGEUNLOAD:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
Client:Message( 'The ' .. Task.CargoType.TEXT .. ' are being ' .. Task.TEXT[2] .. ' within the landing zone. Wait until the helicopter is ' .. Task.TEXT[3] .. '.',
|
||||
self.MSG.TIME, Mission.Name .. "/Stage", "Co-Pilot: Unload" )
|
||||
Task:RemoveCargoMenus( Client )
|
||||
self:T()
|
||||
Client:Message( 'The ' .. Task.CargoType .. ' are being ' .. Task.TEXT[2] .. ' within the landing zone. Wait until the helicopter is ' .. Task.TEXT[3] .. '.',
|
||||
self.MSG.TIME, Mission.Name .. "/StageUnLoad", "Co-Pilot: Unload" )
|
||||
Task:RemoveCargoMenus( Client )
|
||||
end
|
||||
|
||||
function STAGEUNLOAD:Executing( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
env.info( 'STAGEUNLOAD:Executing() Task.CargoName = ' .. Task.CargoName )
|
||||
local Cargo = Client:RemoveCargo( Task.CargoName )
|
||||
if Cargo then
|
||||
env.info( 'STAGEUNLOAD:Executing() Cargo.CargoName = ' .. Cargo.CargoName )
|
||||
env.info( 'STAGEUNLOAD:Executing() Cargo.CargoGroupName = ' .. Cargo.CargoGroupName )
|
||||
env.info( 'STAGEUNLOAD:Executing() Mission._Cargos[Cargo.CargoName].CargoGroupTemplate = ' .. Mission._Cargos[Cargo.CargoName].CargoGroupTemplate )
|
||||
|
||||
if Cargo.CargoType.TRANSPORT == CARGO_TRANSPORT.UNIT then
|
||||
if Cargo.CargoName then
|
||||
if Task.TargetZoneName then
|
||||
SPAWN:New( Mission._Cargos[Cargo.CargoName].CargoGroupTemplate ):FromCarrier ( Client:ClientGroup(),
|
||||
Task.TargetZoneName,
|
||||
Mission._Cargos[Cargo.CargoName].CargoGroupName )
|
||||
else
|
||||
SPAWN:New( Mission._Cargos[Cargo.CargoName].CargoGroupTemplate ):FromCarrier ( Client:ClientGroup(),
|
||||
Task.LandingZones[Task.CurrentLandingZoneID],
|
||||
Mission._Cargos[Cargo.CargoName].CargoGroupName )
|
||||
end
|
||||
end
|
||||
end
|
||||
self:T()
|
||||
env.info( 'STAGEUNLOAD:Executing() Task.Cargo.CargoName = ' .. Task.Cargo.CargoName )
|
||||
|
||||
local TargetZoneName
|
||||
|
||||
if Task.TargetZoneName then
|
||||
TargetZoneName = Task.TargetZoneName
|
||||
else
|
||||
TargetZoneName = Task.CurrentLandingZoneName
|
||||
end
|
||||
|
||||
if Task.Cargo:UnLoad( Client, TargetZoneName ) then
|
||||
Task.ExecuteStage = _TransportExecuteStage.SUCCESS
|
||||
Client:ShowCargo()
|
||||
if Mission.MissionReportFlash then
|
||||
Client:ShowCargo()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function STAGEUNLOAD:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
env.info( 'STAGEUNLOAD:Validate()' )
|
||||
|
||||
if routines.IsUnitInZones( Client:ClientGroup():getUnits()[1], Task.LandingZones[Task.CurrentLandingZoneID] ) then
|
||||
if routines.IsUnitInZones( Client:GetClientGroupUnit(), Task.CurrentLandingZoneName ) then
|
||||
else
|
||||
Task.ExecuteStage = _TransportExecuteStage.FAILED
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Client:Message( 'The ' .. Task.CargoType.TEXT .. " haven't been successfully " .. Task.TEXT[3] .. ' within the landing zone. Task and mission has failed.',
|
||||
Client:Message( 'The ' .. Task.CargoType .. " haven't been successfully " .. Task.TEXT[3] .. ' within the landing zone. Task and mission has failed.',
|
||||
_TransportStageMsgTime.DONE, Mission.Name .. "/StageFailure", "Co-Pilot: Unload" )
|
||||
return 1
|
||||
end
|
||||
|
||||
if not Client:ClientGroup():getUnits()[1]:inAir() then
|
||||
if not Client:GetClientGroupUnit():inAir() then
|
||||
else
|
||||
Task.ExecuteStage = _TransportExecuteStage.FAILED
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Client:Message( 'The ' .. Task.CargoType.TEXT .. " haven't been successfully " .. Task.TEXT[3] .. ' within the landing zone. Task and mission has failed.',
|
||||
Client:Message( 'The ' .. Task.CargoType .. " haven't been successfully " .. Task.TEXT[3] .. ' within the landing zone. Task and mission has failed.',
|
||||
_TransportStageMsgTime.DONE, Mission.Name .. "/StageFailure", "Co-Pilot: Unload" )
|
||||
return 1
|
||||
end
|
||||
|
||||
if Task.ExecuteStage == _TransportExecuteStage.SUCCESS then
|
||||
Client:Message( 'The ' .. Task.CargoType.TEXT .. ' have been sucessfully ' .. Task.TEXT[3] .. ' within the landing zone.', _TransportStageMsgTime.DONE, Mission.Name .. "/Stage", "Co-Pilot: Unload" )
|
||||
Mission._Cargos[Task.CargoName].Status = CARGOSTATUS.UNLOADED
|
||||
Client:Message( 'The ' .. Task.CargoType .. ' have been sucessfully ' .. Task.TEXT[3] .. ' within the landing zone.', _TransportStageMsgTime.DONE, Mission.Name .. "/Stage", "Co-Pilot: Unload" )
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task.MissionTask:AddGoalCompletion( Task.MissionTask.GoalVerb, Task.CargoName, 1 ) -- We set the cargo as one more goal completed in the mission.
|
||||
return 1
|
||||
@ -405,173 +499,131 @@ STAGELOAD = {
|
||||
}
|
||||
|
||||
function STAGELOAD:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, STAGE:New() )
|
||||
Child.StageType = 'CLIENT'
|
||||
return Child
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGELOAD:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
Client:Message( 'The ' .. Task.CargoType.TEXT .. ' are being ' .. Task.TEXT[2] .. ' within the landing zone. Wait until the helicopter is ' .. Task.TEXT[3] .. '.',
|
||||
_TransportStageMsgTime.EXECUTING, Mission.Name .. "/Stage", "Co-Pilot: Load" )
|
||||
self:T()
|
||||
|
||||
if not Task.IsSlingLoad then
|
||||
Client:Message( 'The ' .. Task.CargoType .. ' are being ' .. Task.TEXT[2] .. ' within the landing zone. Wait until the helicopter is ' .. Task.TEXT[3] .. '.',
|
||||
_TransportStageMsgTime.EXECUTING, Mission.Name .. "/STAGELOAD.EXEC." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" .. ":" )
|
||||
|
||||
-- Route the cargo to the Carrier
|
||||
if Mission._Cargos[Task.CargoName].CargoType.TRANSPORT == CARGO_TRANSPORT.UNIT then
|
||||
Task:OnBoardCargo( Client:ClientGroup(), Mission._Cargos )
|
||||
-- Route the cargo to the Carrier
|
||||
Task.Cargo:OnBoard( Client, Task.CurrentCargoZone, Task.OnBoardSide )
|
||||
Task.ExecuteStage = _TransportExecuteStage.EXECUTING
|
||||
else
|
||||
-- Add the group to the internal cargo;
|
||||
Client:AddCargo( Task.CargoName, Mission._Cargos[Task.CargoName].CargoGroupName, Mission._Cargos[Task.CargoName].CargoType, Mission._Cargos[Task.CargoName].CargoWeight, Mission._Cargos[Task.CargoName].CargoGroupTemplate )
|
||||
Task.ExecuteStage = _TransportExecuteStage.SUCCESS
|
||||
Task.ExecuteStage = _TransportExecuteStage.EXECUTING
|
||||
end
|
||||
end
|
||||
|
||||
function STAGELOAD:Executing( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
-- Remove the loaded object from the battle zone.
|
||||
|
||||
if routines.IsPartOfGroupInRadius( Group.getByName(Mission._Cargos[Task.CargoName].CargoGroupName), Client:ClientGroup(), 75 ) then
|
||||
routines.DestroyGroupInRadiusFromGroup( Group.getByName(Mission._Cargos[Task.CargoName].CargoGroupName), Client:ClientGroup(), 75 )
|
||||
env.info('trying to remove cargo')
|
||||
-- If the Cargo is ready to be loaded, load it into the Client.
|
||||
|
||||
-- Add the group to the internal cargo;
|
||||
Client:AddCargo( Task.CargoName, Mission._Cargos[Task.CargoName].CargoGroupName, Mission._Cargos[Task.CargoName].CargoType, Mission._Cargos[Task.CargoName].CargoWeight, Mission._Cargos[Task.CargoName].CargoGroupTemplate )
|
||||
|
||||
-- Message to the pilot that cargo has been loaded.
|
||||
Client:Message( "The cargo " .. Task.CargoName .. " has been loaded in our helicopter.", 20, Mission.Name .. "/Stage", "Co-Pilot: Load" )
|
||||
Task.ExecuteStage = _TransportExecuteStage.SUCCESS
|
||||
Client:ShowCargo()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if not Task.IsSlingLoad then
|
||||
trace.i(self.ClassName, Task.Cargo.CargoName)
|
||||
|
||||
if Task.Cargo:OnBoarded( Client, Task.CurrentCargoZone ) then
|
||||
|
||||
function STAGELOAD:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
if routines.IsUnitInZones( Client:ClientGroup():getUnits()[1], Task.LandingZones[Task.CurrentLandingZoneID] ) then
|
||||
-- Load the Cargo onto the Client
|
||||
Task.Cargo:Load( Client )
|
||||
|
||||
-- Message to the pilot that cargo has been loaded.
|
||||
Client:Message( "The cargo " .. Task.Cargo.CargoName .. " has been loaded in our helicopter.",
|
||||
20, Mission.Name .. "/STAGELANDING.LOADING1." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" .. ":" )
|
||||
Task.ExecuteStage = _TransportExecuteStage.SUCCESS
|
||||
|
||||
Client:ShowCargo()
|
||||
end
|
||||
else
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task.ExecuteStage = _TransportExecuteStage.FAILED
|
||||
Task.CargoName = nil
|
||||
Client:Message( "The " .. Task.CargoType.TEXT .. " loading has been aborted. You flew outside the pick-up zone while loading. ",
|
||||
_TransportStageMsgTime.DONE, Mission.Name .. "/StageSuccess", "Co-Pilot: Load" )
|
||||
return 1
|
||||
end
|
||||
|
||||
if not Client:ClientGroup():getUnits()[1]:inAir() then
|
||||
else
|
||||
-- The carrier is back in the air, undo the loading process.
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task.ExecuteStage = _TransportExecuteStage.NONE
|
||||
Task.CargoName = nil
|
||||
Client:Message( "The " .. Task.CargoType.TEXT .. " loading has been aborted. Land the helicopter and load the cargo. Don't fly outside the pick-up zone. ",
|
||||
_TransportStageMsgTime.DONE, Mission.Name .. "/StageSuccess", "Co-Pilot: Load" )
|
||||
return -1
|
||||
end
|
||||
|
||||
if Task.ExecuteStage == _TransportExecuteStage.SUCCESS then
|
||||
Mission._Cargos[Task.CargoName].Status = CARGOSTATUS.LOADED
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Client:Message( 'Co-Pilot: The ' .. Task.CargoType.TEXT .. ' have been sucessfully ' .. Task.TEXT[3] .. ' within the landing zone.',
|
||||
_TransportStageMsgTime.DONE, Mission.Name .. "/Stage", "Co-Pilot: Load" )
|
||||
Task.MissionTask:AddGoalCompletion( Task.MissionTask.GoalVerb, Task.CargoName, 1 )
|
||||
return 1
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
STAGE_SLINGLOAD_HOOK = {
|
||||
ClassName = "STAGE_SLINGLOAD_HOOK",
|
||||
MSG = { ID = "SlingLoadHook", TIME = 10 },
|
||||
Name = "SlingLoadHook"
|
||||
}
|
||||
|
||||
function STAGE_SLINGLOAD_HOOK:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGE_SLINGLOAD_HOOK:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
Client:Message( 'Hook the Cargo onto the helicopter, and fly out the pick-up zone. Due to a bug in DCS world it cannot be chacked (for the moment) ' ..
|
||||
'if the cargo is in our out of the zone and attached to your helicopter...', self.MSG.TIME, Mission.Name .. "/Stage", "Co-Pilot: Hook" )
|
||||
end
|
||||
|
||||
function STAGE_SLINGLOAD_HOOK:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
|
||||
|
||||
for CargoID, CargoName in pairs( Task.CargoPrefixes ) do
|
||||
env.info( CargoName )
|
||||
if StaticObject.getByName( CargoName ):inAir() then
|
||||
Task.CargoName = CargoName
|
||||
Task.CargoID = CargoID
|
||||
Client:Message( 'Co-Pilot: The Cargo has been successfully hooked onto the helicopter within the landing zone.', self.MSG.TIME, Mission.Name .. "/StageSuccess" )
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if Task.CargoName then
|
||||
if routines.IsStaticInZones( StaticObject.getByName( Task.CargoName ), Task.LandingZones[Task.CurrentLandingZoneID] ) then
|
||||
else
|
||||
Mission._Cargos[Task.CargoName].Status = CARGOSTATUS.LOADED
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
STAGE_SLINGLOAD_UNHOOK = {
|
||||
ClassName = "STAGE_SLINGLOAD_UNHOOK",
|
||||
MSG = { ID = "SlingLoadUnHook", TIME = 10 },
|
||||
Name = "SlingLoadUnHook"
|
||||
}
|
||||
|
||||
function STAGE_SLINGLOAD_UNHOOK:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGE_SLINGLOAD_UNHOOK:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
Client:Message( 'Deploy the Cargo in the Landing Zone and unhook the cargo, and fly out of the drop zone.', self.MSG.TIME, Mission.Name .. "/StageUnhook", "Co-Pilot: Unhook" )
|
||||
end
|
||||
|
||||
function STAGE_SLINGLOAD_UNHOOK:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
|
||||
for CargoID, CargoName in pairs( Task.CargoPrefixes ) do
|
||||
if StaticObject.getByName( CargoName ):inAir() then
|
||||
Task.CargoName = CargoName
|
||||
Task.CargoID = CargoID
|
||||
Client:Message( 'Co-Pilot: Drop the cargo within the landing zone and unhook.', self.MSG.TIME, Mission.Name .. "/Stage" )
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if Task.CargoName then
|
||||
if not StaticObject.getByName( Task.CargoName ):inAir() then
|
||||
if routines.IsUnitInZones( Client:ClientGroup():getUnits()[1], Task.LandingZones[Task.CurrentLandingZoneID] ) then
|
||||
else
|
||||
Client:Message( 'Co-Pilot: The Cargo is Dropped in the Landing Zone, and You have flown outside of the landing zone.', self.MSG.TIME, Mission.Name .. "/Stage" )
|
||||
return 1
|
||||
Client:Message( "Hook the " .. Task.CargoNames .. " onto the helicopter " .. Task.TEXT[3] .. " within the landing zone.",
|
||||
_TransportStageMsgTime.EXECUTING, Mission.Name .. "/STAGELOAD.LOADING.1." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" .. ":", 10 )
|
||||
for CargoID, Cargo in pairs( CARGOS ) do
|
||||
self:T( "Cargo.CargoName = " .. Cargo.CargoName )
|
||||
|
||||
if Cargo:IsSlingLoad() then
|
||||
local CargoStatic = StaticObject.getByName( Cargo.CargoStaticName )
|
||||
if CargoStatic then
|
||||
trace.i(self.ClassName, "Cargo is found in the DCS simulator.")
|
||||
local CargoStaticPosition = CargoStatic:getPosition().p
|
||||
trace.i(self.ClassName, "Cargo Position x = " .. CargoStaticPosition.x .. ", y = " .. CargoStaticPosition.y .. ", z = " .. CargoStaticPosition.z )
|
||||
local CargoStaticHeight = routines.GetUnitHeight( CargoStatic )
|
||||
if CargoStaticHeight > 5 then
|
||||
trace.i(self.ClassName, "Cargo is airborne.")
|
||||
Cargo:StatusLoaded()
|
||||
Task.Cargo = Cargo
|
||||
Client:Message( 'The Cargo has been successfully hooked onto the helicopter and is now being sling loaded. Fly outside the landing zone.',
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.LOADING.2." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" .. ":" )
|
||||
Task.ExecuteStage = _TransportExecuteStage.SUCCESS
|
||||
break
|
||||
end
|
||||
else
|
||||
self:T( "Cargo not found in the DCS simulator." )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
function STAGELOAD:Validate( Mission, Client, Task )
|
||||
self:T()
|
||||
|
||||
self:T( "Task.CurrentLandingZoneName = " .. Task.CurrentLandingZoneName )
|
||||
|
||||
if not Task.IsSlingLoad then
|
||||
if not routines.IsUnitInZones( Client:GetClientGroupUnit(), Task.CurrentLandingZoneName ) then
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task.ExecuteStage = _TransportExecuteStage.FAILED
|
||||
Task.CargoName = nil
|
||||
Client:Message( "The " .. Task.CargoType .. " loading has been aborted. You flew outside the pick-up zone while loading. ",
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.1." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" .. ":" )
|
||||
return -1
|
||||
end
|
||||
|
||||
if not Client:GetClientGroupUnit():inAir() then
|
||||
else
|
||||
-- The carrier is back in the air, undo the loading process.
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task.ExecuteStage = _TransportExecuteStage.NONE
|
||||
Task.CargoName = nil
|
||||
Client:Message( "The " .. Task.CargoType .. " loading has been aborted. Re-start the " .. Task.TEXT[3] .. " process. Don't fly outside the pick-up zone.",
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.2." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" .. ":" )
|
||||
return -1
|
||||
end
|
||||
|
||||
if Task.ExecuteStage == _TransportExecuteStage.SUCCESS then
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Client:Message( "Good Job. The " .. Task.CargoType .. " has been sucessfully " .. Task.TEXT[3] .. " within the landing zone.",
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.3." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" .. ":" )
|
||||
Task.MissionTask:AddGoalCompletion( Task.MissionTask.GoalVerb, Task.CargoName, 1 )
|
||||
return 1
|
||||
end
|
||||
|
||||
else
|
||||
if Task.ExecuteStage == _TransportExecuteStage.SUCCESS then
|
||||
CargoStatic = StaticObject.getByName( Task.Cargo.CargoStaticName )
|
||||
if CargoStatic and not routines.IsStaticInZones( CargoStatic, Task.CurrentLandingZoneName ) then
|
||||
Client:Message( "Good Job. The " .. Task.CargoType .. " has been sucessfully " .. Task.TEXT[3] .. " and flown outside of the landing zone.",
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.4." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" .. ":" )
|
||||
Task.MissionTask:AddGoalCompletion( Task.MissionTask.GoalVerb, Task.Cargo.CargoName, 1 )
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
STAGEDONE = {
|
||||
ClassName = "STAGEDONE",
|
||||
MSG = { ID = "Done", TIME = 10 },
|
||||
@ -579,20 +631,19 @@ STAGEDONE = {
|
||||
}
|
||||
|
||||
function STAGEDONE:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, STAGE:New() )
|
||||
Child.StageType = 'AI'
|
||||
return Child
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'AI'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGEDONE:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
end
|
||||
|
||||
function STAGEDONE:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
Task:Done()
|
||||
|
||||
@ -606,24 +657,23 @@ STAGEARRIVE = {
|
||||
}
|
||||
|
||||
function STAGEARRIVE:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, STAGE:New() )
|
||||
Child.StageType = 'CLIENT'
|
||||
return Child
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'CLIENT'
|
||||
return self
|
||||
end
|
||||
|
||||
function STAGEARRIVE:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
Client:Message( 'We have arrived at ' .. Task.LandingZones[Task.CurrentLandingZoneID] .. ".", self.MSG.TIME, Mission.Name .. "/Stage", "Co-Pilot: Arrived" )
|
||||
Client:Message( 'We have arrived at ' .. Task.CurrentLandingZoneName .. ".", self.MSG.TIME, Mission.Name .. "/Stage", "Co-Pilot: Arrived" )
|
||||
|
||||
end
|
||||
|
||||
function STAGEARRIVE:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
Task.CurrentLandingZoneID = routines.IsUnitInZones( Client:ClientGroup():getUnits()[1], Task.LandingZones )
|
||||
Task.CurrentLandingZoneID = routines.IsUnitInZones( Client:GetClientGroupUnit(), Task.LandingZones )
|
||||
if ( Task.CurrentLandingZoneID ) then
|
||||
else
|
||||
return -1
|
||||
@ -641,11 +691,10 @@ STAGEGROUPSDESTROYED = {
|
||||
}
|
||||
|
||||
function STAGEGROUPSDESTROYED:New()
|
||||
trace.f(self.ClassName)
|
||||
-- Arrange meta tables
|
||||
local Child = BASE:Inherit( self, STAGE:New() )
|
||||
Child.StageType = 'AI'
|
||||
return Child
|
||||
local self = BASE:Inherit( self, STAGE:New() )
|
||||
self:T()
|
||||
self.StageType = 'AI'
|
||||
return self
|
||||
end
|
||||
|
||||
--function STAGEGROUPSDESTROYED:Execute( Mission, Client, Task )
|
||||
@ -655,7 +704,7 @@ end
|
||||
--end
|
||||
|
||||
function STAGEGROUPSDESTROYED:Validate( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
self:T()
|
||||
|
||||
if Task.MissionTask:IsGoalReached() then
|
||||
return 1
|
||||
@ -665,8 +714,8 @@ trace.f(self.ClassName)
|
||||
end
|
||||
|
||||
function STAGEGROUPSDESTROYED:Execute( Mission, Client, Task )
|
||||
trace.f(self.ClassName)
|
||||
trace.i( self.ClassName, { Task.ClassName, Task.Destroyed } )
|
||||
self:T()
|
||||
self:T( { Task.ClassName, Task.Destroyed } )
|
||||
--env.info( 'Event Table Task = ' .. tostring(Task) )
|
||||
|
||||
end
|
||||
|
||||
@ -9,29 +9,37 @@ Include.File( "Stage" )
|
||||
|
||||
TASK = {
|
||||
|
||||
-- Defines the different signal types with a Task.
|
||||
SIGNAL = {
|
||||
COLOR = {
|
||||
RED = { ID = 1, COLOR = trigger.smokeColor.Red, TEXT = "A red" },
|
||||
GREEN = { ID = 2, COLOR = trigger.smokeColor.Green, TEXT = "A green" },
|
||||
BLUE = { ID = 3, COLOR = trigger.smokeColor.Blue, TEXT = "A blue" },
|
||||
WHITE = { ID = 4, COLOR = trigger.smokeColor.White, TEXT = "A white" },
|
||||
ORANGE = { ID = 5, COLOR = trigger.smokeColor.Orange, TEXT = "An orange" }
|
||||
},
|
||||
TYPE = {
|
||||
SMOKE = { ID = 1, TEXT = "smoke" },
|
||||
FLARE = { ID = 2, TEXT = "flare" }
|
||||
}
|
||||
},
|
||||
ClassName = "TASK",
|
||||
Mission = {}, -- Owning mission of the Task
|
||||
Name = '',
|
||||
Stages = {},
|
||||
Stage = {},
|
||||
ActiveStage = 0,
|
||||
TaskDone = false,
|
||||
TaskFailed = false,
|
||||
GoalTasks = {}
|
||||
-- Defines the different signal types with a Task.
|
||||
SIGNAL = {
|
||||
COLOR = {
|
||||
RED = { ID = 1, COLOR = trigger.smokeColor.Red, TEXT = "A red" },
|
||||
GREEN = { ID = 2, COLOR = trigger.smokeColor.Green, TEXT = "A green" },
|
||||
BLUE = { ID = 3, COLOR = trigger.smokeColor.Blue, TEXT = "A blue" },
|
||||
WHITE = { ID = 4, COLOR = trigger.smokeColor.White, TEXT = "A white" },
|
||||
ORANGE = { ID = 5, COLOR = trigger.smokeColor.Orange, TEXT = "An orange" }
|
||||
},
|
||||
TYPE = {
|
||||
SMOKE = { ID = 1, TEXT = "smoke" },
|
||||
FLARE = { ID = 2, TEXT = "flare" }
|
||||
}
|
||||
},
|
||||
ClassName = "TASK",
|
||||
Mission = {}, -- Owning mission of the Task
|
||||
Name = '',
|
||||
Stages = {},
|
||||
Stage = {},
|
||||
Cargos = {
|
||||
InitCargos = {},
|
||||
LoadCargos = {}
|
||||
},
|
||||
LandingZones = {
|
||||
LandingZoneNames = {},
|
||||
LandingZones = {}
|
||||
},
|
||||
ActiveStage = 0,
|
||||
TaskDone = false,
|
||||
TaskFailed = false,
|
||||
GoalTasks = {}
|
||||
}
|
||||
|
||||
--- Instantiates a new TASK Base. Should never be used. Interface Class.
|
||||
@ -120,7 +128,9 @@ trace.f(self.ClassName)
|
||||
end
|
||||
end
|
||||
|
||||
Client:Message( GoalsText, 10, "/TASKPROGRESS" .. self.ClassName, "Mission Command: Task Status", 30 )
|
||||
if Mission.MissionReportFlash or Mission.MissionReportShow then
|
||||
Client:Message( GoalsText, 10, "/TASKPROGRESS" .. self.ClassName, "Mission Command: Task Status", 30 )
|
||||
end
|
||||
end
|
||||
|
||||
--- Sets a TASK to status Done.
|
||||
@ -132,7 +142,7 @@ end
|
||||
--- Returns if a TASK is done.
|
||||
-- @treturn bool
|
||||
function TASK:IsDone()
|
||||
trace.f(self.ClassName)
|
||||
trace.i( self.ClassName, self.TaskDone )
|
||||
return self.TaskDone
|
||||
end
|
||||
|
||||
@ -145,7 +155,7 @@ end
|
||||
--- Returns if a TASk has failed.
|
||||
-- @return bool
|
||||
function TASK:IsFailed()
|
||||
trace.f(self.ClassName)
|
||||
trace.i( self.ClassName, self.TaskFailed )
|
||||
return self.TaskFailed
|
||||
end
|
||||
|
||||
@ -268,7 +278,6 @@ end
|
||||
--- Returns if all the Goals of the TASK were achieved.
|
||||
-- @treturn bool
|
||||
function TASK:IsGoalReached( )
|
||||
trace.f(self.ClassName)
|
||||
|
||||
local GoalReached = true
|
||||
|
||||
@ -287,6 +296,7 @@ trace.f(self.ClassName)
|
||||
end
|
||||
end
|
||||
|
||||
trace.i( self.ClassName, GoalReached )
|
||||
return GoalReached
|
||||
end
|
||||
|
||||
@ -319,10 +329,9 @@ end
|
||||
|
||||
function TASK.MenuAction( Parameter )
|
||||
trace.menu("TASK","MenuAction")
|
||||
trace.l( "TASK", "MenuAction", { Parameter } )
|
||||
trace.l( "TASK", "MenuAction" )
|
||||
Parameter.ReferenceTask.ExecuteStage = _TransportExecuteStage.EXECUTING
|
||||
Parameter.ReferenceTask.CargoName = Parameter.CargoName
|
||||
|
||||
Parameter.ReferenceTask.Cargo = Parameter.CargoTask
|
||||
end
|
||||
|
||||
function TASK:StageExecute()
|
||||
|
||||
@ -62,6 +62,7 @@ trace.names.FollowPlayers = false
|
||||
trace.names.AddPlayerFromUnit = false
|
||||
trace.names.FromCarrier = false
|
||||
trace.names.OnDeadOrCrash = false
|
||||
|
||||
trace.classes.CLEANUP = false
|
||||
trace.cache = {}
|
||||
|
||||
@ -249,8 +250,9 @@ end
|
||||
trace.i = function(object, variable)
|
||||
|
||||
local info = debug.getinfo( 2, "nl" )
|
||||
if info.name ~= trace.nametrace then
|
||||
trace.nametrace = info.name
|
||||
trace.nametrace = info.name
|
||||
if trace.nametrace == nil then
|
||||
trace.nametrace = "function"
|
||||
end
|
||||
if trace.names.all or trace.tracefunction( trace.nametrace ) or trace.classes[ object ] then
|
||||
local objecttrace = ""
|
||||
|
||||
58
Moose/Unit.lua
Normal file
58
Moose/Unit.lua
Normal file
@ -0,0 +1,58 @@
|
||||
--- UNIT Classes
|
||||
-- @classmod UNIT
|
||||
|
||||
Include.File( "Routines" )
|
||||
Include.File( "Base" )
|
||||
Include.File( "Message" )
|
||||
|
||||
UNITS = {}
|
||||
|
||||
|
||||
UNIT = {
|
||||
ClassName="UNIT",
|
||||
}
|
||||
|
||||
function UNIT:New( _Unit )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:T( _Unit:getName() )
|
||||
|
||||
self._Unit = _Unit
|
||||
self.UnitName = _Unit:getName()
|
||||
self.UnitID = _Unit:getID()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function UNIT:GetCallSign()
|
||||
self:T( self.UnitName )
|
||||
|
||||
return self._Unit:getCallsign()
|
||||
end
|
||||
|
||||
function UNIT:GetPositionVec3()
|
||||
self:T( self.UnitName )
|
||||
|
||||
local UnitPos = self._Unit:getPosition().p
|
||||
|
||||
self:T( UnitPos )
|
||||
return UnitPos
|
||||
end
|
||||
|
||||
function UNIT:OtherUnitInRadius( AwaitUnit, Radius )
|
||||
self:T( { self.UnitName, AwaitUnit.UnitName, Radius } )
|
||||
|
||||
local UnitPos = self:GetPositionVec3()
|
||||
local AwaitUnitPos = AwaitUnit:GetPositionVec3()
|
||||
|
||||
if (((UnitPos.x - AwaitUnitPos.x)^2 + (UnitPos.z - AwaitUnitPos.z)^2)^0.5 <= Radius) then
|
||||
self:T( "true" )
|
||||
return true
|
||||
else
|
||||
self:T( "false" )
|
||||
return false
|
||||
end
|
||||
|
||||
self:T( "false" )
|
||||
return false
|
||||
end
|
||||
|
||||
57
Moose/Zone.lua
Normal file
57
Moose/Zone.lua
Normal file
@ -0,0 +1,57 @@
|
||||
--- ZONE Classes
|
||||
-- @classmod ZONE
|
||||
|
||||
Include.File( "Routines" )
|
||||
Include.File( "Base" )
|
||||
Include.File( "Message" )
|
||||
|
||||
ZONES = {}
|
||||
|
||||
|
||||
ZONE = {
|
||||
ClassName="ZONE",
|
||||
}
|
||||
|
||||
function ZONE:New( ZoneName )
|
||||
trace.f( self.ClassName, ZoneName )
|
||||
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
|
||||
local Zone = trigger.misc.getZone( ZoneName )
|
||||
|
||||
if not Zone then
|
||||
error( "Zone " .. ZoneName .. " does not exist." )
|
||||
return nil
|
||||
end
|
||||
|
||||
self.Zone = Zone
|
||||
self.ZoneName = ZoneName
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function ZONE:GetRandomPoint()
|
||||
trace.f( self.ClassName, self.ZoneName )
|
||||
|
||||
local Point = {}
|
||||
|
||||
local Zone = trigger.misc.getZone( self.ZoneName )
|
||||
|
||||
Point.x = Zone.point.x + math.random( Zone.radius * -1, Zone.radius )
|
||||
Point.y = Zone.point.z + math.random( Zone.radius * -1, Zone.radius )
|
||||
|
||||
trace.i( self.ClassName, { Zone } )
|
||||
trace.i( self.ClassName, { Point } )
|
||||
|
||||
return Point
|
||||
end
|
||||
|
||||
function ZONE:GetRadius()
|
||||
trace.f( self.ClassName, self.ZoneName )
|
||||
|
||||
local Zone = trigger.misc.getZone( self.ZoneName )
|
||||
|
||||
trace.i( self.ClassName, { Zone } )
|
||||
|
||||
return Zone.radius
|
||||
end
|
||||
126
Test Missions/MOOSE_Pickup_Test.lua
Normal file
126
Test Missions/MOOSE_Pickup_Test.lua
Normal file
@ -0,0 +1,126 @@
|
||||
Include.File( "Mission" )
|
||||
Include.File( "Client" )
|
||||
Include.File( "DeployTask" )
|
||||
Include.File( "PickupTask" )
|
||||
Include.File( "DestroyGroupsTask" )
|
||||
Include.File( "DestroyRadarsTask" )
|
||||
Include.File( "DestroyUnitTypesTask" )
|
||||
Include.File( "GoHomeTask" )
|
||||
Include.File( "Spawn" )
|
||||
Include.File( "Movement" )
|
||||
Include.File( "Sead" )
|
||||
Include.File( "CleanUp" )
|
||||
|
||||
do
|
||||
local Mission = MISSION:New( 'Pickup', 'Operational', 'Pickup Troops', 'NATO' )
|
||||
|
||||
Mission:AddClient( CLIENT:New( 'DE Pickup Test 1' ):Transport() )
|
||||
Mission:AddClient( CLIENT:New( 'DE Pickup Test 2' ):Transport() )
|
||||
|
||||
local CargoTable = {}
|
||||
|
||||
local EngineerNames = { "Alpha", "Beta", "Gamma", "Delta", "Theta" }
|
||||
|
||||
Cargo_Pickup_Zone_1 = CARGO_ZONE:New( 'Pickup Zone 1', 'DE Communication Center 1' ):BlueSmoke()
|
||||
Cargo_Pickup_Zone_2 = CARGO_ZONE:New( 'Pickup Zone 2', 'DE Communication Center 2' ):RedSmoke()
|
||||
|
||||
for CargoItem = 1, 2 do
|
||||
CargoTable[CargoItem] = CARGO_GROUP:New( 'Engineers', 'Team ' .. EngineerNames[CargoItem], math.random( 70, 100 ) * 3, 'DE Infantry', Cargo_Pickup_Zone_1 )
|
||||
end
|
||||
|
||||
for CargoItem = 3, 5 do
|
||||
CargoTable[CargoItem] = CARGO_GROUP:New( 'Engineers', 'Team ' .. EngineerNames[CargoItem], math.random( 70, 100 ) * 3, 'DE Infantry', Cargo_Pickup_Zone_2 )
|
||||
end
|
||||
|
||||
--Cargo_Package = CARGO_INVISIBLE:New( 'Letter', 0.1, 'DE Secret Agent', 'Pickup Zone Package' )
|
||||
--Cargo_Goods = CARGO_STATIC:New( 'Goods', 20, 'Goods', 'Pickup Zone Goods', 'DE Collection Point' )
|
||||
--Cargo_SlingLoad = CARGO_SLING:New( 'Basket', 40, 'Basket', 'Pickup Zone Sling Load', 'DE Cargo Guard' )
|
||||
|
||||
|
||||
-- Assign the Pickup Task
|
||||
local PickupTask = PICKUPTASK:New( 'Engineers', CLIENT.ONBOARDSIDE.LEFT )
|
||||
PickupTask:FromZone( Cargo_Pickup_Zone_1 )
|
||||
PickupTask:FromZone( Cargo_Pickup_Zone_2 )
|
||||
PickupTask:InitCargo( CargoTable )
|
||||
PickupTask:SetGoalTotal( 3 )
|
||||
Mission:AddTask( PickupTask, 1 )
|
||||
|
||||
|
||||
Cargo_Deploy_Zone_1 = CARGO_ZONE:New( 'Deploy Zone 1', 'DE Communication Center 3' ):RedFlare()
|
||||
Cargo_Deploy_Zone_2 = CARGO_ZONE:New( 'Deploy Zone 2', 'DE Communication Center 4' ):WhiteFlare()
|
||||
|
||||
-- Assign the Pickup Task
|
||||
local DeployTask = DEPLOYTASK:New( 'Engineers' )
|
||||
DeployTask:ToZone( Cargo_Deploy_Zone_1 )
|
||||
DeployTask:ToZone( Cargo_Deploy_Zone_2 )
|
||||
DeployTask:SetGoalTotal( 3 )
|
||||
Mission:AddTask( DeployTask, 2 )
|
||||
|
||||
MISSIONSCHEDULER.AddMission( Mission )
|
||||
end
|
||||
|
||||
do
|
||||
local Mission = MISSION:New( 'Deliver secret letter', 'Operational', 'Pickup letter to the commander.', 'NATO' )
|
||||
|
||||
Mission:AddClient( CLIENT:New( 'BE Package Test 1' ):Transport() )
|
||||
Mission:AddClient( CLIENT:New( 'BE Package Test 2' ):Transport() )
|
||||
Mission:AddClient( CLIENT:New( 'DE Pickup Test 1' ):Transport() )
|
||||
Mission:AddClient( CLIENT:New( 'DE Pickup Test 2' ):Transport() )
|
||||
|
||||
Package_Pickup_Zone = CARGO_ZONE:New( 'Package Pickup Zone', 'DE Guard' ):GreenSmoke()
|
||||
|
||||
Cargo_Package = CARGO_PACKAGE:New( 'Letter', 'Letter to Command', 0.1, 'DE Guard' )
|
||||
--Cargo_Goods = CARGO_STATIC:New( 'Goods', 20, 'Goods', 'Pickup Zone Goods', 'DE Collection Point' )
|
||||
--Cargo_SlingLoad = CARGO_SLING:New( 'Basket', 40, 'Basket', 'Pickup Zone Sling Load', 'DE Cargo Guard' )
|
||||
|
||||
|
||||
-- Assign the Pickup Task
|
||||
local PickupTask = PICKUPTASK:New( 'Letter', CLIENT.ONBOARDSIDE.FRONT )
|
||||
PickupTask:FromZone( Package_Pickup_Zone )
|
||||
PickupTask:InitCargo( { Cargo_Package } )
|
||||
PickupTask:SetGoalTotal( 1 )
|
||||
Mission:AddTask( PickupTask, 1 )
|
||||
|
||||
|
||||
Package_Deploy_Zone = CARGO_ZONE:New( 'Package Deploy Zone', 'DE Secret Car' ):GreenFlare()
|
||||
|
||||
-- Assign the Pickup Task
|
||||
local DeployTask = DEPLOYTASK:New( 'Letter' )
|
||||
DeployTask:ToZone( Package_Deploy_Zone )
|
||||
DeployTask:SetGoalTotal( 1 )
|
||||
Mission:AddTask( DeployTask, 2 )
|
||||
|
||||
MISSIONSCHEDULER.AddMission( Mission )
|
||||
end
|
||||
|
||||
do
|
||||
local Mission = MISSION:New( 'Sling load Cargo', 'Operational', 'Sling Load Cargo to Deploy Zone.', 'NATO' )
|
||||
|
||||
Mission:AddClient( CLIENT:New( 'Sling Load Test Client 1' ):Transport() )
|
||||
Mission:AddClient( CLIENT:New( 'Sling Load Test Client 2' ):Transport() )
|
||||
|
||||
Sling_Load_Pickup_Zone = CARGO_ZONE:New( 'Sling Load Pickup Zone', 'Sling Load Guard' ):RedSmoke()
|
||||
|
||||
Cargo_Sling_Load = CARGO_SLINGLOAD:New( 'Sling', 'Food Boxes', 200, 'Sling Load Pickup Zone', 'Sling Load Guard', country.id.USA )
|
||||
--Cargo_Goods = CARGO_STATIC:New( 'Goods', 20, 'Goods', 'Pickup Zone Goods', 'DE Collection Point' )
|
||||
--Cargo_SlingLoad = CARGO_SLING:New( 'Basket', 40, 'Basket', 'Pickup Zone Sling Load', 'DE Cargo Guard' )
|
||||
|
||||
|
||||
-- Assign the Pickup Task
|
||||
local PickupTask = PICKUPTASK:New( 'Sling', CLIENT.ONBOARDSIDE.FRONT )
|
||||
PickupTask:FromZone( Sling_Load_Pickup_Zone )
|
||||
PickupTask:InitCargo( { Cargo_Sling_Load } )
|
||||
PickupTask:SetGoalTotal( 1 )
|
||||
Mission:AddTask( PickupTask, 1 )
|
||||
|
||||
MISSIONSCHEDULER.AddMission( Mission )
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- MISSION SCHEDULER STARTUP
|
||||
MISSIONSCHEDULER.Start()
|
||||
MISSIONSCHEDULER.ReportMenu()
|
||||
MISSIONSCHEDULER.ReportMissionsHide()
|
||||
|
||||
env.info( "Test Mission loaded" )
|
||||
BIN
Test Missions/MOOSE_Pickup_Test.miz
Normal file
BIN
Test Missions/MOOSE_Pickup_Test.miz
Normal file
Binary file not shown.
15
Test Missions/MOOSE_Spawn_Test.lua
Normal file
15
Test Missions/MOOSE_Spawn_Test.lua
Normal file
@ -0,0 +1,15 @@
|
||||
Include.File( "Spawn" )
|
||||
|
||||
SpawnTest = SPAWN:New( 'TEST' ):Schedule( 1, 1, 15, 0.4 ):Repeat()
|
||||
|
||||
SpawnTestPlane = SPAWN:New( 'TESTPLANE' ):Schedule( 1, 1, 15, 0.4 ):RepeatOnLanding()
|
||||
|
||||
SpawnTestShipPlane = SPAWN:New( 'SHIPPLANE' ):Schedule( 1, 1, 15, 0.4 ):RepeatOnLanding()
|
||||
|
||||
SpawnTestShipHeli = SPAWN:New( 'SHIPHELI' ):Schedule( 1, 1, 15, 0.4 ):RepeatOnLanding()
|
||||
|
||||
SpawnCH53E = SPAWN:New( 'VEHICLE' )
|
||||
|
||||
|
||||
SpawnTestHelicopterCleanUp = SPAWN:New( "TEST_HELI_CLEANUP" ):Limit( 3, 100 ):Schedule( 10, 0 ):RandomizeRoute( 1, 1, 1000 ):CleanUp( 180 )
|
||||
SpawnTestVehiclesCleanUp = SPAWN:New( "TEST_AAA_CLEANUP" ):Limit( 3, 100 ):Schedule( 10, 0 ):RandomizeRoute( 1, 1, 1000 )
|
||||
BIN
Test Missions/MOOSE_Spawn_Test.miz
Normal file
BIN
Test Missions/MOOSE_Spawn_Test.miz
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user