mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
ARTY improvements.
This commit is contained in:
parent
0ec3192fb7
commit
b14a672b0e
@ -52,8 +52,10 @@
|
||||
-- @field #ARTY
|
||||
ARTY={
|
||||
ClassName = "ARTY",
|
||||
Debug = false,
|
||||
Debug = true,
|
||||
targets = {},
|
||||
currentTarget = nil,
|
||||
Nshots=0,
|
||||
}
|
||||
|
||||
--- Enumerator of possible rules of engagement.
|
||||
@ -80,6 +82,10 @@ ARTY.MenuF10=nil
|
||||
-- @field #string id
|
||||
ARTY.id="ARTY | "
|
||||
|
||||
--- Range script version.
|
||||
-- @field #number version
|
||||
ARTY.version="0.1.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO list:
|
||||
@ -100,15 +106,15 @@ function ARTY:New(group)
|
||||
|
||||
-- Check that group is present.
|
||||
if group then
|
||||
self:T(ARTY.id.."ARTY group "..group:GetName())
|
||||
self:T(ARTY.id..string.format("ARTY script version %s. Added group %s.", ARTY.version, group:GetName()))
|
||||
else
|
||||
self:E(ARTY.id.."ARTY: Requested group does not exist! (Has to be a MOOSE group.)")
|
||||
self:E(ARTY.id.."ERROR! Requested ARTY group does not exist! (Has to be a MOOSE group.)")
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Check that we actually have a GROUND group.
|
||||
if group:IsGround()==false and group:IsShip()==false then
|
||||
self:E(ARTY.id.."ARTY group "..group:GetName().." has to be a GROUND or SHIP group!")
|
||||
self:E(ARTY.id..string.format("ERROR! ARTY group %s has to be a GROUND or SHIP group!",group:GetName()))
|
||||
return nil
|
||||
end
|
||||
|
||||
@ -143,6 +149,7 @@ function ARTY:New(group)
|
||||
self:AddTransition("*", "Start", "CombatReady")
|
||||
self:AddTransition("CombatReady", "OpenFire", "Firing")
|
||||
self:AddTransition("Firing", "CeaseFire", "CombatReady")
|
||||
self:AddTransition("*", "NoAmmo", "OutOfAmmo")
|
||||
self:AddTransition("*", "Dead", "*")
|
||||
|
||||
return self
|
||||
@ -152,6 +159,41 @@ end
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Assign a group of target(s).
|
||||
-- @param #ARTY self
|
||||
-- @param Wrapper.Group#GROUP group Group of targets.
|
||||
-- @param #number radius (Optional) Radius. Default is 100 m.
|
||||
-- @param #number nshells (Optional) How many shells are fired on target per unit. Default 5.
|
||||
-- @param #number prio (Optional) Priority of target. Number between 1 (high) and 100 (low). Default 50.
|
||||
function ARTY:AssignTargetGroup(group, radius, nshells, prio)
|
||||
self:E({group=group, radius=radius, nshells=nshells, prio=prio})
|
||||
|
||||
-- Set default values.
|
||||
nshells=nshells or 5
|
||||
radius=radius or 100
|
||||
prio=prio or 50
|
||||
prio=math.max( 1, prio)
|
||||
prio=math.min(100, prio)
|
||||
|
||||
-- Coordinate and name.
|
||||
local coord=group:GetCoordinate()
|
||||
local name=group:GetName()
|
||||
|
||||
-- Prepare target array.
|
||||
local _target={name=name, coord=coord, radius=radius, nshells=nshells, engaged=0, underfire=false, prio=prio}
|
||||
|
||||
-- Add to table.
|
||||
table.insert(self.targets, _target)
|
||||
|
||||
-- Debug info.
|
||||
env.info(ARTY.id..string.format("Added target %s, radius=%d, nshells=%d, prio=%d.", name, radius, nshells, prio))
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- After "Start" event. Initialized ROE and alarm state. Starts the event handler.
|
||||
-- @param #ARTY self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group.
|
||||
@ -182,6 +224,13 @@ function ARTY:onafterStart(Controllable, From, Event, To)
|
||||
text=text..string.format("******************************************************\n")
|
||||
self:T(ARTY.id..text)
|
||||
|
||||
-- Get Ammo.
|
||||
self:_GetAmmo(self.Controllable)
|
||||
|
||||
for _, target in pairs(self.targets) do
|
||||
env.info(ARTY.id..string.format("Target %s, radius=%d, nshells=%d, prio=%d.", target.name, target.radius, target.nshells, target.prio))
|
||||
end
|
||||
|
||||
-- Add event handler.
|
||||
self:HandleEvent(EVENTS.Shot, self._OnEventShot)
|
||||
self:HandleEvent(EVENTS.Dead, self._OnEventDead)
|
||||
@ -191,64 +240,57 @@ function ARTY:onafterStart(Controllable, From, Event, To)
|
||||
|
||||
end
|
||||
|
||||
--- Assign a group of targets
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Eventhandler for shot event.
|
||||
-- @param #ARTY self
|
||||
function ARTY:_CheckTaskQueue()
|
||||
self:F()
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function ARTY:_OnEventShot(EventData)
|
||||
self:F(EventData)
|
||||
|
||||
local _counter=0
|
||||
for _,target in pairs(self.targets) do
|
||||
if target.underfire==false then
|
||||
env.info(ARTY.id..string.format("Opening fire on target %s", target.name))
|
||||
self:OpenFire(target)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Assign a group of targets
|
||||
-- @param #ARTY self
|
||||
-- @param Wrapper.Group#GROUP group Group of targets.
|
||||
-- @param #number radius (Optional) Radius. Default is 100 m.
|
||||
-- @param #number nshells (Optional) How many shells are fired on target per unit. Default 5.
|
||||
function ARTY:AssignTargetGroup(group, radius, nshells)
|
||||
self:E({group=group, radius=radius, nshells=nshells})
|
||||
|
||||
nshells=nshells or 5
|
||||
radius=radius or 100
|
||||
|
||||
local coord=group:GetCoordinate()
|
||||
local name=group:GetName()
|
||||
|
||||
-- Prepare target array.
|
||||
local _target={name=name, coord=coord, radius=radius, nshells=nshells, engaged=0, underfire=false}
|
||||
|
||||
-- Add to table.
|
||||
table.insert(self.targets, _target)
|
||||
-- Weapon data.
|
||||
local _weapon = EventData.Weapon:getTypeName() -- should be the same as Event.WeaponTypeName
|
||||
local _weaponStrArray = self:_split(_weapon,"%.")
|
||||
local _weaponName = _weaponStrArray[#_weaponStrArray]
|
||||
|
||||
-- Debug info.
|
||||
env.info(ARTY.id.."Targets:")
|
||||
for _,target in pairs(self.targets) do
|
||||
env.info(ARTY.id..string.format("Name: %s", target.name))
|
||||
self:T(ARTY.id.."EVENT SHOT: Ini unit = "..EventData.IniUnitName)
|
||||
self:T(ARTY.id.."EVENT SHOT: Ini group = "..EventData.IniGroupName)
|
||||
self:T(ARTY.id.."EVENT SHOT: Weapon type = ".._weapon)
|
||||
self:T(ARTY.id.."EVENT SHOT: Weapon name = ".._weaponName)
|
||||
|
||||
local group = EventData.IniGroup --Wrapper.Group#GROUP
|
||||
|
||||
if group and group:IsAlive() then
|
||||
|
||||
if EventData.IniGroupName == self.Controllable:GetName() then
|
||||
|
||||
if self.currentTarget then
|
||||
|
||||
-- Increase number of shots fired by this group on this target.
|
||||
self.Nshots=self.Nshots+1
|
||||
|
||||
-- Debug output.
|
||||
self:T(ARTY.id..string.format("Group %s fired shot # %d on target %s.", self.Controllable:GetName(), self.Nshots, self.currentTarget.name))
|
||||
|
||||
-- Check if number of shots reached max.
|
||||
if self.Nshots >= self.currentTarget.nshells then
|
||||
self:CeaseFire(self.currentTarget)
|
||||
self.Nshots=0
|
||||
end
|
||||
|
||||
else
|
||||
self:T(ARTY.id..string.format("No current target?!"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
function ARTY:_OnEventShot(EventData)
|
||||
env.info("Event Shot")
|
||||
self:F(EventData)
|
||||
end
|
||||
|
||||
--- Eventhandler for dead event.
|
||||
-- @param #ARTY self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function ARTY:_OnEventDead(EventData)
|
||||
self:F(EventData)
|
||||
end
|
||||
@ -257,7 +299,7 @@ end
|
||||
-- @param #ARTY self
|
||||
-- @param Core.Point#COORDINATE coord Coordinates to fire upon.
|
||||
-- @param #number radius Radius around coordinate.
|
||||
-- @param #number nshells Number of shells to fire per unit.
|
||||
-- @param #number nshells Number of shells to fire.
|
||||
function ARTY:_FireAtCoord(coord, radius, nshells)
|
||||
self:E({coord=coord, radius=radius, nshells=nshells})
|
||||
|
||||
@ -288,41 +330,211 @@ end
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Before "OpenFire" event.
|
||||
-- @param #SUPPRESSION self
|
||||
-- @param #ARTY self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #table target Array holding the target info.
|
||||
-- @return boolean
|
||||
-- @return #boolean If true proceed to onafterOpenfire.
|
||||
function ARTY:onbeforeOpenFire(Controllable, From, Event, To, target)
|
||||
self:_EventFromTo("onbeforeOpenFire", Event, From, To)
|
||||
|
||||
if self.currentTarget then
|
||||
self:T(ARTY.id..string.format("Group %s already has a target %s.", self.Controllable:GetName(), target.name))
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- After "OpenFire" event.
|
||||
-- @param #SUPPRESSION self
|
||||
-- @param #ARTY self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #table target Array holding the target info. _target={coord=coord, radius=radius, nshells=nshells, engaged=0, underattack=false}
|
||||
function ARTY:onbeforeOpenFire(Controllable, From, Event, To, target)
|
||||
function ARTY:onafterOpenFire(Controllable, From, Event, To, target)
|
||||
self:_EventFromTo("onafterOpenFire", Event, From, To)
|
||||
|
||||
local _coord=target.coord --Core.Point#COORDINATE
|
||||
|
||||
--_coord:MarkToAll("Arty Target")
|
||||
|
||||
-- Get target array index.
|
||||
local id=self:_GetTargetByName(target.name)
|
||||
|
||||
-- Target is now under fire and has been engaged once more.
|
||||
if id then
|
||||
self.targets[id].underfire=true
|
||||
self.targets[id].engaged=self.targets[id].engaged+1
|
||||
self.currentTarget=target
|
||||
end
|
||||
|
||||
-- Start firing.
|
||||
self:_FireAtCoord(target.coord, target.radius, target.nshells)
|
||||
|
||||
end
|
||||
|
||||
--- Before "CeaseFire" event.
|
||||
-- @param #ARTY self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #table target Array holding the target info.
|
||||
-- @return #boolean
|
||||
function ARTY:onbeforeCeaseFire(Controllable, From, Event, To, target)
|
||||
self:_EventFromTo("onbeforeCeaseFire", Event, From, To)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- After "CeaseFire" event.
|
||||
-- @param #ARTY self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #table target Array holding the target info.
|
||||
function ARTY:onafterCeaseFire(Controllable, From, Event, To, target)
|
||||
self:_EventFromTo("onafterCeaseFire", Event, From, To)
|
||||
|
||||
local name=self.currentTarget.name
|
||||
|
||||
local id=self:_GetTargetByName(name)
|
||||
|
||||
self.targets[id].underfire=false
|
||||
|
||||
self.currentTarget=nil
|
||||
|
||||
--Controllable:ClearTasks()
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Go through queue of assigned tasks.
|
||||
-- @param #ARTY self
|
||||
function ARTY:_CheckTaskQueue()
|
||||
self:F()
|
||||
|
||||
-- Sort targets.
|
||||
self:_SortTaskQueue()
|
||||
|
||||
for i=1,#self.targets do
|
||||
|
||||
local _target=self.targets[i]
|
||||
|
||||
if _target.underfire==false then
|
||||
|
||||
env.info(ARTY.id..string.format("Opening fire on target %s. Prio = %d, engaged = %d", _target.name, _target.prio, _target.engaged))
|
||||
|
||||
-- Call OpenFire event.
|
||||
self:OpenFire(_target)
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Sort targets with respect to priority and number of times it was already engaged.
|
||||
-- @param #ARTY self
|
||||
function ARTY:_SortTaskQueue()
|
||||
self:F()
|
||||
|
||||
-- Sort results table wrt times they have already been engaged.
|
||||
local function _sort(a, b)
|
||||
return (a.engaged < b.engaged) or (a.engaged==b.engaged and a.prio < b.prio)
|
||||
end
|
||||
table.sort(self.targets, _sort)
|
||||
|
||||
-- Debug output.
|
||||
env.info(ARTY.id.."Sorted targets:")
|
||||
for i=1,#self.targets do
|
||||
env.info(ARTY.id..string.format("Target %s. Prio = %d, engaged = %d", self.targets[i].name, self.targets[i].prio, self.targets[i].engaged))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Get the number of shells a unit or group currently has. For a group the ammo count of all units is summed up.
|
||||
-- @param #ARTY self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE controllable
|
||||
-- @return Number of shells left
|
||||
function ARTY:_GetAmmo(controllable)
|
||||
self:F2(controllable)
|
||||
|
||||
-- Get all units.
|
||||
local units=controllable:GetUnits()
|
||||
|
||||
-- Init counter.
|
||||
local ammo=0
|
||||
|
||||
for _,unit in pairs(units) do
|
||||
|
||||
local ammotable=unit:GetAmmo()
|
||||
self:T2({ammotable=ammotable})
|
||||
|
||||
local name=unit:GetName()
|
||||
|
||||
if ammotable ~= nil then
|
||||
|
||||
local weapons=#ammotable
|
||||
self:T2(ARTY.id..string.format("Number of weapons %d.", weapons))
|
||||
|
||||
for w=1,weapons do
|
||||
|
||||
local Nammo=ammotable[w]["count"]
|
||||
local Tammo=ammotable[w]["desc"]["typeName"]
|
||||
|
||||
-- We are specifically looking for shells here.
|
||||
if string.match(Tammo, "shell") then
|
||||
|
||||
-- Add up all shells
|
||||
ammo=ammo+Nammo
|
||||
|
||||
local text=string.format("Unit %s has %d rounds ammo of type %s (shells)", name, Nammo, Tammo)
|
||||
self:T(ARTY.id..text)
|
||||
MESSAGE:New(text, 10):ToAllIf(self.Debug)
|
||||
else
|
||||
local text=string.format("Unit %s has %d ammo of type %s", name, Nammo, Tammo)
|
||||
self:T(ARTY.id..text)
|
||||
MESSAGE:New(text, 10):ToAllIf(self.Debug)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return ammo
|
||||
end
|
||||
|
||||
|
||||
--- Get a target by its name.
|
||||
-- @param #ARTY self
|
||||
-- @param #string name Name of target.
|
||||
-- @return #number Arrayindex of target.
|
||||
function ARTY:_GetTargetByName(name)
|
||||
self:F2(name)
|
||||
|
||||
for i=1,#self.targets do
|
||||
local targetname=self.targets[i].name
|
||||
if targetname==name then
|
||||
self:E(ARTY.id..string.format("Found target with name %s. Index = %d", name, i))
|
||||
return i
|
||||
end
|
||||
end
|
||||
|
||||
self:E(ARTY.id..string.format("ERROR: Target with name %s could not be found!", name))
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Print event-from-to string to DCS log file.
|
||||
-- @param #ARTY self
|
||||
-- @param #string BA Before/after info.
|
||||
@ -330,8 +542,26 @@ end
|
||||
-- @param #string From From state.
|
||||
-- @param #string To To state.
|
||||
function ARTY:_EventFromTo(BA, Event, From, To)
|
||||
local text=string.format("\n%s: %s EVENT %s: %s --> %s", BA, self.Controllable:GetName(), Event, From, To)
|
||||
local text=string.format("%s: %s EVENT %s: %s --> %s", BA, self.Controllable:GetName(), Event, From, To)
|
||||
self:T(ARTY.id..text)
|
||||
end
|
||||
|
||||
|
||||
--- Split string. Cf http://stackoverflow.com/questions/1426954/split-string-in-lua
|
||||
-- @param #ARTY self
|
||||
-- @param #string str Sting to split.
|
||||
-- @param #string sep Speparator for split.
|
||||
-- @return #table Split text.
|
||||
function ARTY:_split(str, sep)
|
||||
self:F2({str=str, sep=sep})
|
||||
|
||||
local result = {}
|
||||
local regex = ("([^%s]+)"):format(sep)
|
||||
for each in str:gmatch(regex) do
|
||||
table.insert(result, each)
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Loading…
x
Reference in New Issue
Block a user