mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Ops
This commit is contained in:
parent
5c6e50e7f9
commit
682c1f5ef2
@ -37,6 +37,7 @@ __Moose.Include( 'Scripts/Moose/Wrapper/Client.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Static.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Airbase.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Scenery.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Marker.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Cargo/Cargo.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoUnit.lua' )
|
||||
@ -69,6 +70,11 @@ __Moose.Include( 'Scripts/Moose/Ops/Airboss.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/RecoveryTanker.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/RescueHelo.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/ATIS.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/AirWing.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Auftrag.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/FlightGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/NavyGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Squadron.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air.lua' )
|
||||
|
||||
2274
Moose Development/Moose/Ops/AirWing.lua
Normal file
2274
Moose Development/Moose/Ops/AirWing.lua
Normal file
File diff suppressed because it is too large
Load Diff
3273
Moose Development/Moose/Ops/Auftrag.lua
Normal file
3273
Moose Development/Moose/Ops/Auftrag.lua
Normal file
File diff suppressed because it is too large
Load Diff
3758
Moose Development/Moose/Ops/FlightGroup.lua
Normal file
3758
Moose Development/Moose/Ops/FlightGroup.lua
Normal file
File diff suppressed because it is too large
Load Diff
852
Moose Development/Moose/Ops/NavyGroup.lua
Normal file
852
Moose Development/Moose/Ops/NavyGroup.lua
Normal file
@ -0,0 +1,852 @@
|
||||
--- **Ops** - Enhanced Naval Group.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Dynamically add and remove waypoints
|
||||
-- * Let the group steam into the wind
|
||||
-- * Command a full stop
|
||||
-- * Let a submarine dive and surface
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- @module Ops.NavyGroup
|
||||
-- @image OPS_NavyGroup.png
|
||||
|
||||
|
||||
--- NAVYGROUP class.
|
||||
-- @type NAVYGROUP
|
||||
-- @field #boolean turning If true, group is currently turning.
|
||||
-- @field #NAVYGROUP.IntoWind intowind Into wind info.
|
||||
-- @extends Ops.OpsGroup#OPSGROUP
|
||||
|
||||
--- *Something must be left to chance; nothing is sure in a sea fight above all.* -- Horatio Nelson
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # The NAVYGROUP Concept
|
||||
--
|
||||
-- This class enhances naval groups.
|
||||
--
|
||||
-- @field #NAVYGROUP
|
||||
NAVYGROUP = {
|
||||
ClassName = "NAVYGROUP",
|
||||
verbose = 2,
|
||||
turning = false,
|
||||
intowind = nil,
|
||||
}
|
||||
|
||||
--- Navy group element.
|
||||
-- @type NAVYGROUP.Element
|
||||
-- @field #string name Name of the element, i.e. the unit.
|
||||
-- @field #string typename Type name.
|
||||
|
||||
--- Navy group element.
|
||||
-- @type NAVYGROUP.IntoWind
|
||||
-- @field #number Tstart Time to start.
|
||||
-- @field #number Tstop Time to stop.
|
||||
-- @field #boolean Uturn U-turn.
|
||||
-- @field #number Speed Speed in knots.
|
||||
|
||||
|
||||
--- NavyGroup version.
|
||||
-- @field #string version
|
||||
NAVYGROUP.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Stop and resume route.
|
||||
-- TODO: Add waypoints.
|
||||
-- TODO: Add tasks.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new NAVYGROUP class object.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string GroupName Name of the group.
|
||||
-- @return #NAVYGROUP self
|
||||
function NAVYGROUP:New(GroupName)
|
||||
|
||||
-- Inherit everything from FSM class.
|
||||
local self=BASE:Inherit(self, OPSGROUP:New(GroupName)) -- #NAVYGROUP
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("NAVYGROUP %s | ", self.groupname)
|
||||
|
||||
-- Defaults
|
||||
self:SetDefaultROE()
|
||||
self:SetDetection()
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("*", "FullStop", "Holding") -- Hold position.
|
||||
self:AddTransition("*", "Cruise", "Cruising") -- Hold position.
|
||||
|
||||
self:AddTransition("*", "TurnIntoWind", "*") -- Command the group to turn into the wind.
|
||||
self:AddTransition("*", "TurningStarted", "*") -- Group started turning.
|
||||
self:AddTransition("*", "TurningStopped", "*") -- Group stopped turning.
|
||||
|
||||
self:AddTransition("*", "Dive", "Diving") -- Command a submarine to dive.
|
||||
self:AddTransition("Diving", "Surface", "Cruising") -- Command a submarine to go to the surface.
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the NAVYGROUP and all its event handlers.
|
||||
-- @param #NAVYGROUP self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the NAVYGROUP and all its event handlers.
|
||||
-- @function [parent=#NAVYGROUP] __Stop
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
-- TODO: Add pseudo functions.
|
||||
|
||||
|
||||
-- Init waypoints.
|
||||
self:InitWaypoints()
|
||||
|
||||
-- Initialize the group.
|
||||
self:_InitGroup()
|
||||
|
||||
-- Debug trace.
|
||||
if false then
|
||||
self.Debug=true
|
||||
BASE:TraceOnOff(true)
|
||||
BASE:TraceClass(self.ClassName)
|
||||
BASE:TraceLevel(1)
|
||||
end
|
||||
|
||||
-- Handle events:
|
||||
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
||||
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
||||
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
||||
|
||||
-- Start the status monitoring.
|
||||
self:__CheckZone(-1)
|
||||
self:__Status(-2)
|
||||
self:__QueueUpdate(-3)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add a *scheduled* task.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param Core.Point#COORDINATE Coordinate Coordinate of the target.
|
||||
-- @param #number Radius Radius in meters. Default 100 m.
|
||||
-- @param #number Nshots Number of shots to fire. Default 3.
|
||||
-- @param #number WeaponType Type of weapon. Default auto.
|
||||
-- @param #string Clock Time when to start the attack.
|
||||
-- @param #number Prio Priority of the task.
|
||||
function NAVYGROUP:AddTaskFireAtPoint(Coordinate, Radius, Nshots, WeaponType, Clock, Prio)
|
||||
|
||||
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, Coordinate:GetVec2(), Radius, Nshots, WeaponType)
|
||||
|
||||
self:AddTask(DCStask, Clock, nil, Prio)
|
||||
|
||||
end
|
||||
|
||||
--- Add a *scheduled* task.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param Wrapper.Group#GROUP TargetGroup Target group.
|
||||
-- @param #number WeaponExpend How much weapons does are used.
|
||||
-- @param #number WeaponType Type of weapon. Default auto.
|
||||
-- @param #string Clock Time when to start the attack.
|
||||
-- @param #number Prio Priority of the task.
|
||||
function NAVYGROUP:AddTaskAttackGroup(TargetGroup, WeaponExpend, WeaponType, Clock, Prio)
|
||||
|
||||
local DCStask=CONTROLLABLE.TaskAttackGroup(nil, TargetGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit, GroupAttack)
|
||||
|
||||
self:AddTask(DCStask, Clock, nil, Prio)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Update status.
|
||||
-- @param #NAVYGROUP self
|
||||
function NAVYGROUP:onafterStatus(From, Event, To)
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
---
|
||||
-- Detection
|
||||
---
|
||||
|
||||
-- Check if group has detected any units.
|
||||
if self.detectionOn then
|
||||
self:_CheckDetectedUnits()
|
||||
end
|
||||
|
||||
|
||||
-- Current heading and position of the carrier.
|
||||
local hdg=self:GetHeading()
|
||||
local pos=self:GetCoordinate()
|
||||
local speed=self.group:GetVelocityKNOTS()
|
||||
|
||||
-- Check if group started or stopped turning.
|
||||
self:_CheckTurning()
|
||||
|
||||
-- Check water is ahead.
|
||||
local collision=self:_CheckCollisionCoord(pos:Translate(self.collisiondist or 5000, hdg))
|
||||
|
||||
local intowind=false
|
||||
if self.intowind then
|
||||
|
||||
if timer.getAbsTime()>=self.intowind.Tstop then
|
||||
|
||||
if self.intowind.Uturn then
|
||||
self:UpdateRoute(self.currentwp)
|
||||
else
|
||||
self:UpdateRoute()
|
||||
end
|
||||
|
||||
self.intowind=nil
|
||||
|
||||
else
|
||||
intowind=true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Get number of tasks and missions.
|
||||
local nTaskTot, nTaskSched, nTaskWP=self:CountRemainingTasks()
|
||||
local nMissions=self:CountRemainingMissison()
|
||||
|
||||
-- Info text.
|
||||
local text=string.format("State %s: Speed=%.1f knots Heading=%03d intowind=%s turning=%s collision=%s Tasks=%d Missions=%d", fsmstate, speed, hdg, tostring(intowind), tostring(self.turning), tostring(collision), nTaskTot, nMissions)
|
||||
self:I(self.lid..text)
|
||||
|
||||
|
||||
---
|
||||
-- Tasks
|
||||
---
|
||||
|
||||
-- Task queue.
|
||||
if #self.taskqueue>0 and self.verbose>1 then
|
||||
local text=string.format("Tasks #%d", #self.taskqueue)
|
||||
for i,_task in pairs(self.taskqueue) do
|
||||
local task=_task --Ops.OpsGroup#OPSGROUP.Task
|
||||
local name=task.description
|
||||
local taskid=task.dcstask.id or "unknown"
|
||||
local status=task.status
|
||||
local clock=UTILS.SecondsToClock(task.time, true)
|
||||
local eta=task.time-timer.getAbsTime()
|
||||
local started=task.timestamp and UTILS.SecondsToClock(task.timestamp, true) or "N/A"
|
||||
local duration=-1
|
||||
if task.duration then
|
||||
duration=task.duration
|
||||
if task.timestamp then
|
||||
-- Time the task is running.
|
||||
duration=task.duration-(timer.getAbsTime()-task.timestamp)
|
||||
else
|
||||
-- Time the task is supposed to run.
|
||||
duration=task.duration
|
||||
end
|
||||
end
|
||||
-- Output text for element.
|
||||
if task.type==OPSGROUP.TaskType.SCHEDULED then
|
||||
text=text..string.format("\n[%d] %s (%s): status=%s, scheduled=%s (%d sec), started=%s, duration=%d", i, taskid, name, status, clock, eta, started, duration)
|
||||
elseif task.type==OPSGROUP.TaskType.WAYPOINT then
|
||||
text=text..string.format("\n[%d] %s (%s): status=%s, waypoint=%d, started=%s, duration=%d, stopflag=%d", i, taskid, name, status, task.waypoint, started, duration, task.stopflag:Get())
|
||||
end
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
---
|
||||
-- Missions
|
||||
---
|
||||
|
||||
-- Current mission name.
|
||||
if self.verbose>0 then
|
||||
local Mission=self:GetMissionByID(self.currentmission)
|
||||
|
||||
-- Current status.
|
||||
local text=string.format("Missions %d, Current: %s", self:CountRemainingMissison(), Mission and Mission.name or "none")
|
||||
for i,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
local Cstart= UTILS.SecondsToClock(mission.Tstart, true)
|
||||
local Cstop = mission.Tstop and UTILS.SecondsToClock(mission.Tstop, true) or "INF"
|
||||
text=text..string.format("\n[%d] %s (%s) status=%s (%s), Time=%s-%s, prio=%d wp=%s targets=%d",
|
||||
i, tostring(mission.name), mission.type, mission:GetGroupStatus(self), tostring(mission.status), Cstart, Cstop, mission.prio, tostring(mission:GetGroupWaypointIndex(self)), mission:CountMissionTargets())
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- Next check in ~30 seconds.
|
||||
if not self:IsStopped() then
|
||||
self:__Status(-10)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Events
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after "ElementSpawned" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #NAVYGROUP.Element Element The group element.
|
||||
function NAVYGROUP:onafterElementSpawned(From, Event, To, Element)
|
||||
self:I(self.lid..string.format("Element spawned %s", Element.name))
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.SPAWNED)
|
||||
|
||||
end
|
||||
|
||||
--- On after "Spawned" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function NAVYGROUP:onafterSpawned(From, Event, To)
|
||||
self:I(self.lid..string.format("Group spawned!"))
|
||||
|
||||
if self.ai then
|
||||
|
||||
-- Set default ROE and ROT options.
|
||||
self:SetOptionROE(self.roe)
|
||||
|
||||
end
|
||||
|
||||
-- Get orientation.
|
||||
self.Corientlast=self.group:GetUnit(1):GetOrientationX()
|
||||
|
||||
-- Update route.
|
||||
self:__Cruise(-1)
|
||||
|
||||
end
|
||||
|
||||
--- On after "UpdateRoute" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number n Waypoint number. Default is next waypoint.
|
||||
-- @param #number Speed Speed in knots. Default cruise speed.
|
||||
-- @param #number Depth Depth in meters. Default 0 meters.
|
||||
function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Depth)
|
||||
|
||||
-- Update route from this waypoint number onwards.
|
||||
n=n or self.currentwp+1
|
||||
|
||||
-- Update waypoint tasks, i.e. inject WP tasks into waypoint table.
|
||||
self:_UpdateWaypointTasks()
|
||||
|
||||
-- Waypoints.
|
||||
local waypoints={}
|
||||
|
||||
-- Speed.
|
||||
local speed=Speed and UTILS.KnotsToKmph(Speed) or self.speedCruise
|
||||
|
||||
-- Depth for submarines.
|
||||
local depth=Depth or 0
|
||||
|
||||
local current=self:GetCoordinate():WaypointNaval(speed, depth)
|
||||
table.insert(waypoints, current)
|
||||
|
||||
-- Add remaining waypoints to route.
|
||||
for i=n, #self.waypoints do
|
||||
local wp=self.waypoints[i]
|
||||
|
||||
-- Set speed.
|
||||
wp.speed=UTILS.KmphToMps(speed)
|
||||
wp.alt=-depth --Depth and -Depth or wp.alt
|
||||
|
||||
-- Add waypoint.
|
||||
table.insert(waypoints, wp)
|
||||
end
|
||||
|
||||
|
||||
if #waypoints>1 then
|
||||
|
||||
self:I(self.lid..string.format("Updateing route: WP=%d, Speed=%.1f knots, depth=%d meters", #self.waypoints-n+1, UTILS.KmphToKnots(speed), depth))
|
||||
|
||||
-- Route group to all defined waypoints remaining.
|
||||
self:Route(waypoints)
|
||||
|
||||
else
|
||||
|
||||
---
|
||||
-- No waypoints left
|
||||
---
|
||||
|
||||
self:I(self.lid..string.format("No waypoints left"))
|
||||
|
||||
-- TODO: Switch to waypoint 1
|
||||
|
||||
--self:UpdateRoute(1)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after "TurnIntoWind" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number Duration Duration in seconds.
|
||||
-- @param #number Speed Speed in knots.
|
||||
-- @param #boolean Uturn Return to the place we came from.
|
||||
function NAVYGROUP:onafterTurnIntoWind(From, Event, To, Duration, Speed, Uturn)
|
||||
|
||||
local headingTo=self:GetCoordinate():GetWind(50)
|
||||
|
||||
local intowind={} --#NAVYGROUP.IntoWind
|
||||
intowind.Speed=Speed
|
||||
intowind.Tstart=timer.getAbsTime()
|
||||
intowind.Tstop=intowind.Tstart+Duration
|
||||
intowind.Uturn=Uturn or false
|
||||
intowind.Heading=headingTo
|
||||
|
||||
self.intowind=intowind
|
||||
|
||||
self:I(self.lid..string.format("Steaming into wind: Heading=%03d Speed=%.1f knots, Tstart=%d Tstop=%d", intowind.Heading, intowind.Speed, intowind.Tstart, intowind.Tstop))
|
||||
|
||||
local distance=UTILS.NMToMeters(1000)
|
||||
|
||||
local wp={}
|
||||
|
||||
local coord=self:GetCoordinate()
|
||||
local Coord=coord:Translate(distance, headingTo)
|
||||
|
||||
wp[1]=coord:WaypointNaval(Speed)
|
||||
wp[2]=Coord:WaypointNaval(Speed)
|
||||
|
||||
self:Route(wp)
|
||||
|
||||
end
|
||||
|
||||
--- On after "FullStop" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function NAVYGROUP:onafterFullStop(From, Event, To)
|
||||
|
||||
-- Get current position.
|
||||
local pos=self:GetCoordinate()
|
||||
|
||||
-- Create a new waypoint.
|
||||
local wp=pos:WaypointNaval(0)
|
||||
|
||||
-- Create new route consisting of only this position ==> Stop!
|
||||
self:Route({wp})
|
||||
|
||||
end
|
||||
|
||||
--- On after "Cruise" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function NAVYGROUP:onafterCruise(From, Event, To)
|
||||
|
||||
self:UpdateRoute()
|
||||
|
||||
end
|
||||
|
||||
--- On after "Dive" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number Depth Dive depth in meters.
|
||||
function NAVYGROUP:onafterDive(From, Event, To, Depth)
|
||||
|
||||
env.info("FF Diving")
|
||||
self:UpdateRoute(nil, nil, Depth)
|
||||
|
||||
end
|
||||
|
||||
--- On after "Surface" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number Depth Dive depth in meters.
|
||||
function NAVYGROUP:onafterSurface(From, Event, To)
|
||||
|
||||
self:UpdateRoute(nil, nil, 0)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Events DCS
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Event function handling the birth of a unit.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||
function NAVYGROUP:OnEventBirth(EventData)
|
||||
|
||||
-- Check that this is the right group.
|
||||
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
|
||||
local unit=EventData.IniUnit
|
||||
local group=EventData.IniGroup
|
||||
local unitname=EventData.IniUnitName
|
||||
|
||||
if self.respawning then
|
||||
|
||||
local function reset()
|
||||
self.respawning=nil
|
||||
end
|
||||
|
||||
-- Reset switch in 1 sec. This should allow all birth events of n>1 groups to have passed.
|
||||
-- TODO: Can I do this more rigorously?
|
||||
self:ScheduleOnce(1, reset)
|
||||
|
||||
else
|
||||
|
||||
-- Get element.
|
||||
local element=self:GetElementByName(unitname)
|
||||
|
||||
-- Set element to spawned state.
|
||||
self:T3(self.lid..string.format("EVENT: Element %s born ==> spawned", element.name))
|
||||
self:ElementSpawned(element)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Routing
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add an a waypoint to the route.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param Core.Point#COORDINATE coordinate The coordinate of the waypoint. Use COORDINATE:SetAltitude(altitude) to define the altitude.
|
||||
-- @param #number wpnumber Waypoint number. Default at the end.
|
||||
-- @param #number speed Speed in knots. Default 11 kts.
|
||||
-- @param #boolean updateroute If true or nil, call UpdateRoute. If false, no call.
|
||||
-- @return #number Waypoint index.
|
||||
function NAVYGROUP:AddWaypoint(coordinate, wpnumber, speed, updateroute)
|
||||
|
||||
-- Waypoint number. Default is at the end.
|
||||
wpnumber=wpnumber or #self.waypoints+1
|
||||
|
||||
if wpnumber>self.currentwp then
|
||||
self.passedfinalwp=false
|
||||
end
|
||||
|
||||
-- Speed in knots.
|
||||
speed=speed or 11
|
||||
|
||||
-- Speed at waypoint.
|
||||
local speedkmh=UTILS.KnotsToKmph(speed)
|
||||
|
||||
-- Create a Naval waypoint.
|
||||
local wp=coordinate:WaypointNaval(speedkmh)
|
||||
|
||||
-- Add to table.
|
||||
table.insert(self.waypoints, wpnumber, wp)
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Adding NAVAL waypoint #%d, speed=%.1f knots. Last waypoint passed was #%s. Total waypoints #%d", wpnumber, speed, self.currentwp, #self.waypoints))
|
||||
|
||||
-- Shift all waypoint tasks after the inserted waypoint.
|
||||
for _,_task in pairs(self.taskqueue) do
|
||||
local task=_task --Ops.OpsGroup#OPSGROUP.Task
|
||||
if task.type==OPSGROUP.TaskType.WAYPOINT and task.waypoint and task.waypoint>=wpnumber then
|
||||
task.waypoint=task.waypoint+1
|
||||
end
|
||||
end
|
||||
|
||||
-- Shift all mission waypoints after the inserted waypoint.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
-- Get mission waypoint index.
|
||||
local wpidx=mission:GetGroupWaypointIndex(self)
|
||||
|
||||
-- Increase number if this waypoint lies in the future.
|
||||
if wpidx and wpidx>=wpnumber then
|
||||
mission:SetGroupWaypointIndex(self, wpidx+1)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Update route.
|
||||
if updateroute==nil or updateroute==true then
|
||||
self:_CheckGroupDone(1)
|
||||
end
|
||||
|
||||
return wpnumber
|
||||
end
|
||||
|
||||
--- Initialize group parameters. Also initializes waypoints if self.waypoints is nil.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @return #NAVYGROUP self
|
||||
function NAVYGROUP:_InitGroup()
|
||||
|
||||
-- First check if group was already initialized.
|
||||
if self.groupinitialized then
|
||||
self:E(self.lid.."WARNING: Group was already initialized!")
|
||||
return
|
||||
end
|
||||
|
||||
-- Get template of group.
|
||||
self.template=self.group:GetTemplate()
|
||||
|
||||
-- Define category.
|
||||
self.isAircraft=false
|
||||
self.isNaval=true
|
||||
self.isGround=false
|
||||
|
||||
|
||||
-- Helo group.
|
||||
--self.isSubmarine=self.group:IsSubmarine()
|
||||
|
||||
-- Ships are always AI.
|
||||
self.ai=true
|
||||
|
||||
-- Is (template) group late activated.
|
||||
self.isLateActivated=self.template.lateActivation
|
||||
|
||||
-- Naval groups cannot be uncontrolled.
|
||||
self.isUncontrolled=false
|
||||
|
||||
-- Max speed in km/h.
|
||||
self.speedmax=self.group:GetSpeedMax()
|
||||
|
||||
-- Cruise speed: 70% of max speed but within limit.
|
||||
self.speedCruise=self.speedmax*0.7
|
||||
|
||||
-- Group ammo.
|
||||
--self.ammo=self:GetAmmoTot()
|
||||
|
||||
self.traveldist=0
|
||||
self.traveltime=timer.getAbsTime()
|
||||
self.position=self:GetCoordinate()
|
||||
|
||||
-- Radio parameters from template.
|
||||
self.radioOn=true -- Radio is always on for ships.
|
||||
self.radioFreq=tonumber(self.template.units[1].frequency)/1000000
|
||||
self.radioModu=tonumber(self.template.units[1].modulation)/1000000
|
||||
|
||||
-- If not set by the use explicitly yet, we take the template values as defaults.
|
||||
if not self.radioFreqDefault then
|
||||
self.radioFreqDefault=self.radioFreq
|
||||
self.radioModuDefault=self.radioModu
|
||||
end
|
||||
|
||||
-- Set default formation.
|
||||
if not self.formationDefault then
|
||||
if self.ishelo then
|
||||
self.formationDefault=ENUMS.Formation.RotaryWing.EchelonLeft.D300
|
||||
else
|
||||
self.formationDefault=ENUMS.Formation.FixedWing.EchelonLeft.Group
|
||||
end
|
||||
end
|
||||
|
||||
local units=self.group:GetUnits()
|
||||
|
||||
for _,_unit in pairs(units) do
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
local element={} --#NAVYGROUP.Element
|
||||
element.name=unit:GetName()
|
||||
element.typename=unit:GetTypeName()
|
||||
element.status=OPSGROUP.ElementStatus.INUTERO
|
||||
table.insert(self.elements, element)
|
||||
|
||||
self:GetAmmoUnit(unit, true)
|
||||
|
||||
if unit:IsAlive() then
|
||||
self:ElementSpawned(element)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Get first unit. This is used to extract other parameters.
|
||||
local unit=self.group:GetUnit(1)
|
||||
|
||||
if unit then
|
||||
|
||||
self.descriptors=unit:GetDesc()
|
||||
|
||||
self.actype=unit:GetTypeName()
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Initialized Navy Group %s:\n", self.groupname)
|
||||
text=text..string.format("AC type = %s\n", self.actype)
|
||||
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedmax))
|
||||
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
|
||||
text=text..string.format("Elements = %d\n", #self.elements)
|
||||
text=text..string.format("Waypoints = %d\n", #self.waypoints)
|
||||
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radioFreq, UTILS.GetModulationName(self.radioModu), tostring(self.radioOn))
|
||||
--text=text..string.format("Ammo = %d (G=%d/R=%d/B=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Bombs, self.ammo.Missiles)
|
||||
text=text..string.format("FSM state = %s\n", self:GetState())
|
||||
text=text..string.format("Is alive = %s\n", tostring(self.group:IsAlive()))
|
||||
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Misc Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Check for possible collisions between two coordinates.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param Core.Point#COORDINATE coordto Coordinate to which the collision is check.
|
||||
-- @param Core.Point#COORDINATE coordfrom Coordinate from which the collision is check.
|
||||
-- @return #boolean If true, surface type ahead is not deep water.
|
||||
-- @return #number Max free distance in meters.
|
||||
function NAVYGROUP:_CheckCollisionCoord(coordto, coordfrom)
|
||||
|
||||
-- Increment in meters.
|
||||
local dx=100
|
||||
|
||||
-- From coordinate. Default 500 in front of the carrier.
|
||||
local d=0
|
||||
if coordfrom then
|
||||
d=0
|
||||
else
|
||||
d=250
|
||||
coordfrom=self:GetCoordinate():Translate(d, self:GetHeading())
|
||||
end
|
||||
|
||||
-- Distance between the two coordinates.
|
||||
local dmax=coordfrom:Get2DDistance(coordto)
|
||||
|
||||
-- Direction.
|
||||
local direction=coordfrom:HeadingTo(coordto)
|
||||
|
||||
-- Scan path between the two coordinates.
|
||||
local clear=true
|
||||
while d<=dmax do
|
||||
|
||||
-- Check point.
|
||||
local cp=coordfrom:Translate(d, direction)
|
||||
|
||||
-- Check if surface type is water.
|
||||
if not cp:IsSurfaceTypeWater() then
|
||||
|
||||
-- Debug mark points.
|
||||
if self.Debug or true then
|
||||
local st=cp:GetSurfaceType()
|
||||
cp:MarkToAll(string.format("Collision check surface type %d", st))
|
||||
end
|
||||
|
||||
-- Collision WARNING!
|
||||
clear=false
|
||||
break
|
||||
end
|
||||
|
||||
-- Increase distance.
|
||||
d=d+dx
|
||||
end
|
||||
|
||||
local text=""
|
||||
if clear then
|
||||
text=string.format("Path into direction %03d° is clear for the next %.1f NM.", direction, UTILS.MetersToNM(d))
|
||||
else
|
||||
text=string.format("Detected obstacle at distance %.1f NM into direction %03d°.", UTILS.MetersToNM(d), direction)
|
||||
end
|
||||
self:T(self.lid..text)
|
||||
|
||||
return not clear, d
|
||||
end
|
||||
|
||||
--- Check if group is turning.
|
||||
-- @param #NAVYGROUP self
|
||||
function NAVYGROUP:_CheckTurning()
|
||||
|
||||
-- Current orientation of carrier.
|
||||
local vNew=self.group:GetUnit(1):GetOrientationX()
|
||||
|
||||
-- Last orientation from 30 seconds ago.
|
||||
local vLast=self.Corientlast or vNew
|
||||
|
||||
-- We only need the X-Z plane.
|
||||
vNew.y=0 ; vLast.y=0
|
||||
|
||||
-- Angle between current heading and last time we checked ~30 seconds ago.
|
||||
local deltaLast=math.deg(math.acos(UTILS.VecDot(vNew,vLast)/UTILS.VecNorm(vNew)/UTILS.VecNorm(vLast)))
|
||||
|
||||
-- Last orientation becomes new orientation
|
||||
self.Corientlast=vNew
|
||||
|
||||
-- Carrier is turning when its heading changed by at least two degrees since last check.
|
||||
local turning=math.abs(deltaLast)>=2
|
||||
|
||||
-- Check if turning stopped.
|
||||
if self.turning and not turning then
|
||||
|
||||
-- Carrier was turning but is not any more.
|
||||
self:TurningStopped()
|
||||
|
||||
elseif turning and not self.turning then
|
||||
|
||||
-- Carrier was not turning but is now.
|
||||
self:TurningStarted()
|
||||
|
||||
end
|
||||
|
||||
-- Update turning.
|
||||
self.turning=turning
|
||||
|
||||
end
|
||||
|
||||
--- Check if group is done, i.e.
|
||||
--
|
||||
-- * passed the final waypoint,
|
||||
-- * no current task
|
||||
-- * no current mission
|
||||
-- * number of remaining tasks is zero
|
||||
-- * number of remaining missions is zero
|
||||
--
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #number delay Delay in seconds.
|
||||
function NAVYGROUP:_CheckGroupDone(delay)
|
||||
|
||||
if self:IsAlive() and self.ai then
|
||||
|
||||
if delay and delay>0 then
|
||||
-- Delayed call.
|
||||
self:ScheduleOnce(delay, NAVYGROUP._CheckGroupDone, self)
|
||||
else
|
||||
|
||||
if not self.passedfinalwp then
|
||||
self:UpdateRoute()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
2815
Moose Development/Moose/Ops/OpsGroup.lua
Normal file
2815
Moose Development/Moose/Ops/OpsGroup.lua
Normal file
File diff suppressed because it is too large
Load Diff
792
Moose Development/Moose/Ops/Squadron.lua
Normal file
792
Moose Development/Moose/Ops/Squadron.lua
Normal file
@ -0,0 +1,792 @@
|
||||
--- **Ops** - Airwing Squadron.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Set parameters like livery, skill valid for all squadron members.
|
||||
-- * Define modex and callsigns.
|
||||
-- * Define mission types, this squadron can perform (see Ops.Auftrag#AUFTRAG).
|
||||
-- * Pause/unpause squadron operations.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- @module Ops.Squadron
|
||||
-- @image OPS_Squadron.png
|
||||
|
||||
|
||||
--- SQUADRON class.
|
||||
-- @type SQUADRON
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #boolean Debug Debug mode. Messages to all about status.
|
||||
-- @field #string lid Class id string for output to DCS log file.
|
||||
-- @field #string name Name of the squadron.
|
||||
-- @field #string templatename Name of the template group.
|
||||
-- @field #string aircrafttype Type of the airframe the squadron is using.
|
||||
-- @field Wrapper.Group#GROUP templategroup Template group.
|
||||
-- @field #table assets Squadron assets.
|
||||
-- @field #table missiontypes Capabilities (mission types and performances) of the squadron.
|
||||
-- @field #string livery Livery of the squadron.
|
||||
-- @field #number skill Skill of squadron members.
|
||||
-- @field #number modex Modex.
|
||||
-- @field #number modexcounter Counter to incease modex number for assets.
|
||||
-- @field #string callsignName Callsign name.
|
||||
-- @field #number callsigncounter Counter to increase callsign names for new assets.
|
||||
-- @field Ops.AirWing#AIRWING airwing The AIRWING object the squadron belongs to.
|
||||
-- @field #number Ngroups Number of asset flight groups this squadron has.
|
||||
-- @field #number engageRange Engagement range in meters.
|
||||
-- @field #string attribute Generalized attribute of the squadron template group.
|
||||
-- @field #number tankerSystem For tanker squads, the refuel system used (boom=0 or probpe=1). Default nil.
|
||||
-- @field #number refuelSystem For refuelable squads, the refuel system used (boom=0 or probpe=1). Default nil.
|
||||
-- @field #number TACANmin TACAN min channel.
|
||||
-- @field #number TACANmax TACAN max channel.
|
||||
-- @field #table TACANused Table of used TACAN channels.
|
||||
-- @field #number radioFreq Radio frequency in MHz the squad uses.
|
||||
-- @field #number radioModu Radio modulation the squad uses.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- *It is unbelievable what a squadron of twelve aircraft did to tip the balance.* -- Adolf Galland
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # The SQUADRON Concept
|
||||
--
|
||||
-- A SQUADRON is essential part of an AIRWING and consists of **one** type of aircraft.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #SQUADRON
|
||||
SQUADRON = {
|
||||
ClassName = "SQUADRON",
|
||||
Debug = nil,
|
||||
lid = nil,
|
||||
name = nil,
|
||||
templatename = nil,
|
||||
aircrafttype = nil,
|
||||
assets = {},
|
||||
missiontypes = {},
|
||||
livery = nil,
|
||||
skill = nil,
|
||||
modex = nil,
|
||||
modexcounter = 0,
|
||||
callsignName = nil,
|
||||
callsigncounter= 11,
|
||||
airwing = nil,
|
||||
Ngroups = nil,
|
||||
engageRange = nil,
|
||||
tankerSystem = nil,
|
||||
refuelSystem = nil,
|
||||
TACANmin = nil,
|
||||
TACANmax = nil,
|
||||
TACANused = {},
|
||||
}
|
||||
|
||||
--- SQUADRON class version.
|
||||
-- @field #string version
|
||||
SQUADRON.version="0.0.7"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- DONE: Engage radius.
|
||||
-- DONE: Modex.
|
||||
-- DONE: Call signs.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new SQUADRON object and start the FSM.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string TemplateGroupName Name of the template group.
|
||||
-- @param #number Ngroups Number of asset groups of this squadron. Default 3.
|
||||
-- @param #string SquadronName Name of the squadron, e.g. "VFA-37".
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:New(TemplateGroupName, Ngroups, SquadronName)
|
||||
|
||||
-- Inherit everything from FSM class.
|
||||
local self=BASE:Inherit(self, FSM:New()) -- #SQUADRON
|
||||
|
||||
-- Name of the template group.
|
||||
self.templatename=TemplateGroupName
|
||||
|
||||
-- Squadron name.
|
||||
self.name=tostring(SquadronName or TemplateGroupName)
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("SQUADRON %s | ", self.name)
|
||||
|
||||
-- Template group.
|
||||
self.templategroup=GROUP:FindByName(self.templatename)
|
||||
|
||||
-- Check if template group exists.
|
||||
if not self.templategroup then
|
||||
self:E(self.lid..string.format("ERROR: Template group %s does not exist!", tostring(self.templatename)))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Defaults.
|
||||
self.Ngroups=Ngroups or 3
|
||||
self:SetEngagementRange()
|
||||
|
||||
-- Everyone can ORBIT.
|
||||
self:AddMissonCapability(AUFTRAG.Type.ORBIT)
|
||||
|
||||
self.attribute=self.templategroup:GetAttribute()
|
||||
|
||||
self.aircrafttype=self.templategroup:GetTypeName()
|
||||
|
||||
self.refuelSystem=select(2, self.templategroup:GetUnit(1):IsRefuelable())
|
||||
self.tankerSystem=select(2, self.templategroup:GetUnit(1):IsTanker())
|
||||
|
||||
|
||||
-- Start State.
|
||||
self:SetStartState("Stopped")
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("Stopped", "Start", "OnDuty") -- Start FSM.
|
||||
self:AddTransition("*", "Status", "*") -- Status update.
|
||||
self:AddTransition("OnDuty", "Pause", "Paused") -- Pause squadron.
|
||||
self:AddTransition("Paused", "Unpause", "OnDuty") -- Unpause squadron.
|
||||
self:AddTransition("*", "Stop", "Stopped") -- Stop squadron.
|
||||
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Start". Starts the SQUADRON. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#SQUADRON] Start
|
||||
-- @param #SQUADRON self
|
||||
|
||||
--- Triggers the FSM event "Start" after a delay. Starts the SQUADRON. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#SQUADRON] __Start
|
||||
-- @param #SQUADRON self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the SQUADRON and all its event handlers.
|
||||
-- @param #SQUADRON self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the SQUADRON and all its event handlers.
|
||||
-- @function [parent=#SQUADRON] __Stop
|
||||
-- @param #SQUADRON self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- Triggers the FSM event "Status".
|
||||
-- @function [parent=#SQUADRON] Status
|
||||
-- @param #SQUADRON self
|
||||
|
||||
--- Triggers the FSM event "Status" after a delay.
|
||||
-- @function [parent=#SQUADRON] __Status
|
||||
-- @param #SQUADRON self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
|
||||
-- Debug trace.
|
||||
if false then
|
||||
self.Debug=true
|
||||
BASE:TraceOnOff(true)
|
||||
BASE:TraceClass(self.ClassName)
|
||||
BASE:TraceLevel(1)
|
||||
end
|
||||
self.Debug=true
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set livery painted on all squadron aircraft.
|
||||
-- Note that the livery name in general is different from the name shown in the mission editor.
|
||||
--
|
||||
-- Valid names are the names of the **livery directories**. Check out the folder in your DCS installation for:
|
||||
--
|
||||
-- * Full modules: `DCS World OpenBeta\CoreMods\aircraft\<Aircraft Type>\Liveries\<Aircraft Type>\<Livery Name>`
|
||||
-- * AI units: `DCS World OpenBeta\Bazar\Liveries\<Aircraft Type>\<Livery Name>`
|
||||
--
|
||||
-- The folder name `<Livery Name>` is the string you want.
|
||||
--
|
||||
-- Or personal liveries you have installed somewhere in your saved games folder.
|
||||
--
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string LiveryName Name of the livery.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetLivery(LiveryName)
|
||||
self.livery=LiveryName
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set skill level of all squadron team members.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string Skill Skill of all flights.
|
||||
-- @usage mysquadron:SetSkill(AI.Skill.EXCELLENT)
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetSkill(Skill)
|
||||
self.skill=Skill
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set radio frequency and modulation the squad uses.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #number Frequency Radio frequency in MHz. Default 251 MHz.
|
||||
-- @param #number Modulation Radio modulation. Default 0=AM.
|
||||
-- @usage mysquadron:SetSkill(AI.Skill.EXCELLENT)
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetRadio(Frequency, Modulation)
|
||||
self.radioFreq=Frequency or 251
|
||||
self.radioModu=Modulation or radio.modulation.AM
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set mission types this squadron is able to perform.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #table MissionTypes Table of mission types. Can also be passed as a #string if only one type.
|
||||
-- @param #number Performance Performance describing how good this mission can be performed. Higher is better. Default 50. Max 100.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:AddMissonCapability(MissionTypes, Performance)
|
||||
|
||||
-- Ensure Missiontypes is a table.
|
||||
if MissionTypes and type(MissionTypes)~="table" then
|
||||
MissionTypes={MissionTypes}
|
||||
end
|
||||
|
||||
-- Set table.
|
||||
self.missiontypes=self.missiontypes or {}
|
||||
|
||||
for _,missiontype in pairs(MissionTypes) do
|
||||
|
||||
-- Check not to add the same twice.
|
||||
if self:CheckMissionCapability(missiontype, self.missiontypes) then
|
||||
self:E(self.lid.."WARNING: Mission capability already present! No need to add it twice.")
|
||||
-- TODO: update performance.
|
||||
else
|
||||
|
||||
local capability={} --Ops.Auftrag#AUFTRAG.Capability
|
||||
capability.MissionType=missiontype
|
||||
capability.Performance=Performance or 50
|
||||
table.insert(self.missiontypes, capability)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- Debug info.
|
||||
self:I(self.missiontypes)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get mission types this squadron is able to perform.
|
||||
-- @param #SQUADRON self
|
||||
-- @return #table Table of mission types. Could be empty {}.
|
||||
function SQUADRON:GetMissionTypes()
|
||||
|
||||
local missiontypes={}
|
||||
|
||||
for _,Capability in pairs(self.missiontypes) do
|
||||
local capability=Capability --Ops.Auftrag#AUFTRAG.Capability
|
||||
table.insert(missiontypes, capability.MissionType)
|
||||
end
|
||||
|
||||
return missiontypes
|
||||
end
|
||||
|
||||
--- Get mission capabilities of this squadron.
|
||||
-- @param #SQUADRON self
|
||||
-- @return #table Table of mission capabilities.
|
||||
function SQUADRON:GetMissionCapabilities()
|
||||
return self.missiontypes
|
||||
end
|
||||
|
||||
--- Get mission performance for a given type of misson.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string MissionType Type of mission.
|
||||
-- @return #number Performance or -1.
|
||||
function SQUADRON:GetMissionPeformance(MissionType)
|
||||
|
||||
for _,Capability in pairs(self.missiontypes) do
|
||||
local capability=Capability --Ops.Auftrag#AUFTRAG.Capability
|
||||
if capability.MissionType==MissionType then
|
||||
return capability.Performance
|
||||
end
|
||||
end
|
||||
|
||||
return -1
|
||||
end
|
||||
|
||||
--- Set max engagement range.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #number EngageRange Engagement range in NM. Default 80 NM.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetEngagementRange(EngageRange)
|
||||
self.engageRange=UTILS.NMToMeters(EngageRange or 80)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set call sign.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #number Callsign Callsign from CALLSIGN.Aircraft, e.g. "Chevy" for CALLSIGN.Aircraft.CHEVY.
|
||||
-- @param #number Index Callsign index, Chevy-**1**.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetCallsign(Callsign, Index)
|
||||
self.callsignName=Callsign
|
||||
self.callsignIndex=Index
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set modex.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #number Modex A number like 100.
|
||||
-- @param #string Prefix A prefix string, which is put before the `Modex` number.
|
||||
-- @param #string Suffix A suffix string, which is put after the `Modex` number.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetModex(Modex, Prefix, Suffix)
|
||||
self.modex=Modex
|
||||
self.modexPrefix=Prefix
|
||||
self.modexSuffix=Suffix
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set airwing.
|
||||
-- @param #SQUADRON self
|
||||
-- @param Ops.AirWing#AIRWING Airwing The airwing.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetAirwing(Airwing)
|
||||
self.airwing=Airwing
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Add airwing asset to squadron.
|
||||
-- @param #SQUADRON self
|
||||
-- @param Ops.AirWing#AIRWING.SquadronAsset Asset The airwing asset.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:AddAsset(Asset)
|
||||
self:T(self.lid..string.format("Adding asset %s of type %s", Asset.spawngroupname, Asset.unittype))
|
||||
Asset.squadname=self.name
|
||||
table.insert(self.assets, Asset)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove airwing asset from squadron.
|
||||
-- @param #SQUADRON self
|
||||
-- @param Ops.AirWing#AIRWING.SquadronAsset Asset The airwing asset.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:DelAsset(Asset)
|
||||
for i,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset
|
||||
if Asset.uid==asset.uid then
|
||||
self:T2(self.lid..string.format("Removing asset %s", asset.spawngroupname))
|
||||
table.remove(self.assets, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get radio frequency and modulation.
|
||||
-- @param #SQUADRON self
|
||||
-- @return #number Radio frequency in MHz.
|
||||
-- @return #number Radio Modulation (0=AM, 1=FM).
|
||||
function SQUADRON:GetRadio()
|
||||
return self.radioFreq, self.radioModu
|
||||
end
|
||||
|
||||
--- Create a callsign for the asset.
|
||||
-- @param #SQUADRON self
|
||||
-- @param Ops.AirWing#AIRWING.SquadronAsset Asset The airwing asset.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:GetCallsign(Asset)
|
||||
|
||||
if self.callsignName then
|
||||
|
||||
Asset.callsign={}
|
||||
|
||||
for i=1,Asset.nunits do
|
||||
|
||||
local callsign={}
|
||||
callsign[1]=self.callsignName
|
||||
callsign[2]=math.floor(self.callsigncounter / 10)
|
||||
callsign[3]=self.callsigncounter % 10
|
||||
if callsign[3]==0 then
|
||||
callsign[3]=1
|
||||
self.callsigncounter=self.callsigncounter+2
|
||||
else
|
||||
self.callsigncounter=self.callsigncounter+1
|
||||
end
|
||||
|
||||
Asset.callsign[i]=callsign
|
||||
|
||||
self:T3({callsign=callsign})
|
||||
|
||||
--TODO: there is also a table entry .name, which is a string.
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Create a modex for the asset.
|
||||
-- @param #SQUADRON self
|
||||
-- @param Ops.AirWing#AIRWING.SquadronAsset Asset The airwing asset.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:GetModex(Asset)
|
||||
|
||||
if self.modex then
|
||||
|
||||
Asset.modex={}
|
||||
|
||||
for i=1,Asset.nunits do
|
||||
|
||||
Asset.modex[i]=string.format("%03d", self.modex+self.modexcounter)
|
||||
|
||||
self.modexcounter=self.modexcounter+1
|
||||
|
||||
self:T3({modex=Asset.modex[i]})
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Get an unused TACAN channel.
|
||||
-- @param #SQUADRON self
|
||||
-- @param Ops.AirWing#AIRWING.SquadronAsset Asset The airwing asset.
|
||||
-- @return #number TACAN channel or *nil* if no channel is free.
|
||||
function SQUADRON:GetTACAN()
|
||||
|
||||
if self.TACANmin and self.TACANmax then
|
||||
|
||||
for channel=self.TACANmin, self.TACANmax do
|
||||
|
||||
if not self.TACANused[channel] then
|
||||
self.TACANused[channel]=true
|
||||
return channel
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- "Return" a used TACAN channel.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #number channel The channel that is available again.
|
||||
function SQUADRON:ReturnTACAN(channel)
|
||||
self.TACANused[channel]=false
|
||||
end
|
||||
|
||||
--- Check if squadron is "OnDuty".
|
||||
-- @param #SQUADRON self
|
||||
-- @return #boolean If true, squdron is in state "OnDuty".
|
||||
function SQUADRON:IsOnDuty()
|
||||
return self:Is("OnDuty")
|
||||
end
|
||||
|
||||
--- Check if squadron is "Stopped".
|
||||
-- @param #SQUADRON self
|
||||
-- @return #boolean If true, squdron is in state "Stopped".
|
||||
function SQUADRON:IsStopped()
|
||||
return self:Is("Stopped")
|
||||
end
|
||||
|
||||
--- Check if squadron is "Paused".
|
||||
-- @param #SQUADRON self
|
||||
-- @return #boolean If true, squdron is in state "Paused".
|
||||
function SQUADRON:IsPaused()
|
||||
return self:Is("Paused")
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Start & Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function SQUADRON:onafterStart(From, Event, To)
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Starting SQUADRON", self.name)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Start the status monitoring.
|
||||
self:__Status(-1)
|
||||
end
|
||||
|
||||
--- On after "Status" event.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function SQUADRON:onafterStatus(From, Event, To)
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
-- Check if group has detected any units.
|
||||
--self:_CheckAssetStatus()
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Status %s: Assets %d", fsmstate, #self.assets)
|
||||
self:I(self.lid..text)
|
||||
|
||||
if not self:IsStopped() then
|
||||
self:__Status(-30)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Check asset status.
|
||||
-- @param #SQUADRON self
|
||||
function SQUADRON:_CheckAssetStatus()
|
||||
|
||||
for _,_asset in pairs(self.assets) do
|
||||
local asset=_asset
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after "Stop" event.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function SQUADRON:onafterStop(From, Event, To)
|
||||
|
||||
self:I(self.lid.."STOPPING Squadron!")
|
||||
|
||||
-- Remove all assets.
|
||||
for i=#self.assets,1,-1 do
|
||||
local asset=self.assets[i]
|
||||
self:DelAsset(asset)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Misc Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Check if there is a squadron that can execute a given mission.
|
||||
-- We check the mission type, the refuelling system, engagement range
|
||||
-- @param #SQUADRON self
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
-- @return #boolean If true, Squadron can do that type of mission.
|
||||
function SQUADRON:CanMission(Mission)
|
||||
|
||||
local cando=true
|
||||
|
||||
-- On duty?=
|
||||
if not self:IsOnDuty() then
|
||||
self:I(self.lid..string.format("Squad in not OnDuty but in state %s. Cannot do mission %s with target %s", self:GetState(), Mission.name, Mission:GetTargetName()))
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check mission type. WARNING: This assumes that all assets of the squad can do the same mission types!
|
||||
if not self:CheckMissionType(Mission.type, self:GetMissionTypes()) then
|
||||
self:I(self.lid..string.format("INFO: Squad cannot do mission type %s (%s, %s)", Mission.type, Mission.name, Mission:GetTargetName()))
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check that tanker mission
|
||||
if Mission.type==AUFTRAG.Type.TANKER then
|
||||
|
||||
if Mission.refuelSystem and Mission.refuelSystem==self.tankerSystem then
|
||||
-- Correct refueling system.
|
||||
else
|
||||
self:I(self.lid..string.format("INFO: Wrong refueling system requested=%s != %s=available", tostring(Mission.refuelSystem), tostring(self.tankerSystem)))
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Distance to target.
|
||||
local TargetDistance=Mission:GetTargetDistance(self.airwing:GetCoordinate())
|
||||
|
||||
-- Max engage range.
|
||||
local engagerange=Mission.engageRange and math.max(self.engageRange, Mission.engageRange) or self.engageRange
|
||||
|
||||
-- Set range is valid. Mission engage distance can overrule the squad engage range.
|
||||
if TargetDistance>engagerange then
|
||||
self:I(self.lid..string.format("INFO: Squad is not in range. Target dist=%d > %d NM max engage Range", UTILS.MetersToNM(TargetDistance), UTILS.MetersToNM(engagerange)))
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- Get assets for a mission.
|
||||
-- @param #SQUADRON self
|
||||
-- @return #number Assets not spawned.
|
||||
function SQUADRON:CountAssetsInStock()
|
||||
|
||||
local N=0
|
||||
for _,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset
|
||||
if asset.spawned then
|
||||
|
||||
else
|
||||
N=N+1
|
||||
end
|
||||
end
|
||||
|
||||
return N
|
||||
end
|
||||
|
||||
--- Get assets for a mission.
|
||||
-- @param #SQUADRON self
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
-- @return #table Assets that can do the required mission.
|
||||
function SQUADRON:RecruitAssets(Mission)
|
||||
|
||||
-- Number of payloads available.
|
||||
local Npayloads=self.airwing:CountPayloadsInStock(Mission.type, self.aircrafttype)
|
||||
|
||||
local assets={}
|
||||
|
||||
-- Loop over assets.
|
||||
for _,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset
|
||||
|
||||
|
||||
-- Check if asset is currently on a mission (STARTED or QUEUED).
|
||||
if self.airwing:IsAssetOnMission(asset) then
|
||||
|
||||
---
|
||||
-- Asset is already on a mission.
|
||||
---
|
||||
|
||||
-- Check if this asset is currently on a PATROL mission (STARTED or EXECUTING).
|
||||
if self.airwing:IsAssetOnMission(asset, AUFTRAG.Type.PATROL) and Mission.type==AUFTRAG.Type.INTERCEPT then
|
||||
|
||||
-- Check if the payload of this asset is compatible with the mission.
|
||||
-- Note: we do not check the payload as an asset that is on a PATROL mission should be able to do an INTERCEPT as well!
|
||||
self:I(self.lid.."Adding asset on PATROL mission for an INTERCEPT mission")
|
||||
table.insert(assets, asset)
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
---
|
||||
-- Asset as no current mission
|
||||
---
|
||||
|
||||
if asset.spawned then
|
||||
|
||||
---
|
||||
-- Asset is already SPAWNED (could be uncontrolled on the airfield or inbound after another mission)
|
||||
---
|
||||
|
||||
local flightgroup=asset.flightgroup
|
||||
|
||||
-- Firstly, check if it has the right payload.
|
||||
if self:CheckMissionCapability(Mission.type, asset.payload.capabilities) and flightgroup and flightgroup:IsAlive() then
|
||||
|
||||
-- Assume we are ready and check if any condition tells us we are not.
|
||||
local combatready=true
|
||||
|
||||
if Mission.type==AUFTRAG.Type.INTERCEPT then
|
||||
combatready=flightgroup:CanAirToAir()
|
||||
else
|
||||
combatready=flightgroup:CanAirToGround()
|
||||
end
|
||||
|
||||
-- No more attacks if fuel is already low. Safety first!
|
||||
if flightgroup:IsFuelLow() then
|
||||
combatready=false
|
||||
end
|
||||
|
||||
-- Check if in a state where we really do not want to fight any more.
|
||||
if flightgroup:IsLanding() or flightgroup:IsLanded() or flightgroup:IsArrived() or flightgroup:IsDead() then
|
||||
combatready=false
|
||||
end
|
||||
|
||||
-- This asset is "combatready".
|
||||
if combatready then
|
||||
self:I(self.lid.."Adding SPAWNED asset to ANOTHER mission as it is COMBATREADY")
|
||||
table.insert(assets, asset)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
---
|
||||
-- Asset is still in STOCK
|
||||
---
|
||||
|
||||
-- Check that asset is not already requested for another mission.
|
||||
if Npayloads>0 and not asset.requested then
|
||||
|
||||
-- Add this asset to the selection.
|
||||
table.insert(assets, asset)
|
||||
|
||||
-- Reduce number of payloads so we only return the number of assets that could do the job.
|
||||
Npayloads=Npayloads-1
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end -- loop over assets
|
||||
|
||||
return assets
|
||||
end
|
||||
|
||||
|
||||
--- Checks if a mission type is contained in a table of possible types.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string MissionType The requested mission type.
|
||||
-- @param #table PossibleTypes A table with possible mission types.
|
||||
-- @return #boolean If true, the requested mission type is part of the possible mission types.
|
||||
function SQUADRON:CheckMissionType(MissionType, PossibleTypes)
|
||||
|
||||
if type(PossibleTypes)=="string" then
|
||||
PossibleTypes={PossibleTypes}
|
||||
end
|
||||
|
||||
for _,canmission in pairs(PossibleTypes) do
|
||||
if canmission==MissionType then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- Check if a mission type is contained in a list of possible capabilities.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string MissionType The requested mission type.
|
||||
-- @param #table Capabilities A table with possible capabilities.
|
||||
-- @return #boolean If true, the requested mission type is part of the possible mission types.
|
||||
function SQUADRON:CheckMissionCapability(MissionType, Capabilities)
|
||||
|
||||
for _,cap in pairs(Capabilities) do
|
||||
local capability=cap --Ops.Auftrag#AUFTRAG.Capability
|
||||
if capability.MissionType==MissionType then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
776
Moose Development/Moose/Wrapper/Marker.lua
Normal file
776
Moose Development/Moose/Wrapper/Marker.lua
Normal file
@ -0,0 +1,776 @@
|
||||
--- **Wrapper** - Markers On the F10 map.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Convenient handling of markers via multiple user API functions.
|
||||
-- * Update text and position of marker easily via scripting.
|
||||
-- * Delay creation and removal of markers via (optional) parameters.
|
||||
-- * Retrieve data such as text and coordinate.
|
||||
-- * Marker specific FSM events when a marker is added, removed or changed.
|
||||
-- * Additional FSM events when marker text or position is changed.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- @module Wrapper.Marker
|
||||
-- @image Wrapper_Marker.png
|
||||
|
||||
|
||||
--- Marker class.
|
||||
-- @type MARKER
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #boolean Debug Debug mode. Messages to all about status.
|
||||
-- @field #string lid Class id string for output to DCS log file.
|
||||
-- @field #number mid Marker ID.
|
||||
-- @field Core.Point#COORDINATE coordinate Coordinate of the mark.
|
||||
-- @field #string text Text displayed in the mark panel.
|
||||
-- @field #string message Message dispayed when the mark is added.
|
||||
-- @field #boolean readonly Marker is read-only.
|
||||
-- @field #number coalition Coalition to which the marker is displayed.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Just because...
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # The MARKER Class Idea
|
||||
--
|
||||
-- The MARKER class simplifies creating, updating and removing of markers on the F10 map.
|
||||
--
|
||||
-- # Create a Marker
|
||||
--
|
||||
-- -- Create a MARKER object at Batumi with a trivial text.
|
||||
-- local Coordinate=AIRBASE:FindByName("Batumi"):GetCoordinate()
|
||||
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield")
|
||||
--
|
||||
-- Now this does **not** show the marker yet. We still need to specifiy to whom it is shown. There are several options, i.e.
|
||||
-- show the marker to everyone, to a speficic coaliton only, or only to a specific group.
|
||||
--
|
||||
-- ## For Everyone
|
||||
--
|
||||
-- If the marker should be visible to everyone, you can use the :ToAll() function.
|
||||
--
|
||||
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToAll()
|
||||
--
|
||||
-- ## For a Coaliton
|
||||
--
|
||||
-- If the maker should be visible to a specific coalition, you can use the :ToCoalition() function.
|
||||
--
|
||||
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToCoaliton(coaliton.side.BLUE)
|
||||
--
|
||||
-- ### To Blue Coaliton
|
||||
--
|
||||
-- ### To Red Coalition
|
||||
--
|
||||
-- This would show the marker only to the Blue coaliton.
|
||||
--
|
||||
-- ## For a Group
|
||||
--
|
||||
--
|
||||
-- # Removing a Marker
|
||||
--
|
||||
--
|
||||
-- # Updating a Marker
|
||||
--
|
||||
-- The marker text and coordinate can be updated easily as shown below.
|
||||
--
|
||||
-- However, note that **updateing involves to remove and recreate the marker if either text or its coordinate is changed**.
|
||||
-- *This is a DCS scripting engine limitation.*
|
||||
--
|
||||
-- ## Update Text
|
||||
--
|
||||
-- If you created a marker "mymarker" as shown above, you can update the dispayed test by
|
||||
--
|
||||
-- mymarker:UpdateText("I am the new text at Batumi")
|
||||
--
|
||||
-- The update can also be delayed by, e.g. 90 seconds, using
|
||||
--
|
||||
-- mymarker:UpdateText("I am the new text at Batumi", 90)
|
||||
--
|
||||
-- ## Update Coordinate
|
||||
--
|
||||
-- If you created a marker "mymarker" as shown above, you can update its coordinate on the F10 map by
|
||||
--
|
||||
-- mymarker:UpdateCoordinate(NewCoordinate)
|
||||
--
|
||||
-- The update can also be delayed by, e.g. 60 seconds, using
|
||||
--
|
||||
-- mymarker:UpdateCoordinate(NewCoordinate, 60)
|
||||
--
|
||||
-- # Retrieve Data
|
||||
--
|
||||
-- The important data as the displayed text and the coordinate of the marker can be retrieved easily.
|
||||
--
|
||||
-- ## Text
|
||||
--
|
||||
-- local text=mymarker:GetText()
|
||||
-- env.info("Marker Text = " .. text)
|
||||
--
|
||||
-- ## Coordinate
|
||||
--
|
||||
-- local Coordinate=mymarker:GetCoordinate()
|
||||
-- env.info("Marker Coordinate LL DSM = " .. Coordinate:ToStringLLDMS())
|
||||
--
|
||||
--
|
||||
-- # FSM Events
|
||||
--
|
||||
-- Moose creates addditonal events, so called FSM event, when markers are added, changed, removed, and text or the coordianteis updated.
|
||||
--
|
||||
-- These events can be captured and used for processing via OnAfter functions as shown below.
|
||||
--
|
||||
-- ## Added
|
||||
--
|
||||
-- ## Changed
|
||||
--
|
||||
-- ## Removed
|
||||
--
|
||||
-- ## TextUpdate
|
||||
--
|
||||
-- ## CoordUpdate
|
||||
--
|
||||
--
|
||||
-- # Examples
|
||||
--
|
||||
--
|
||||
-- @field #MARKER
|
||||
MARKER = {
|
||||
ClassName = "MARKER",
|
||||
Debug = false,
|
||||
lid = nil,
|
||||
mid = nil,
|
||||
coordinate = nil,
|
||||
text = nil,
|
||||
message = nil,
|
||||
readonly = nil,
|
||||
coalition = nil,
|
||||
}
|
||||
|
||||
--- Marker ID. Running number.
|
||||
_MARKERID=0
|
||||
|
||||
--- Marker class version.
|
||||
-- @field #string version
|
||||
MARKER.version="0.1.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: User "Get" functions. E.g., :GetCoordinate()
|
||||
-- DONE: Add delay to user functions.
|
||||
-- DONE: Handle events.
|
||||
-- DONE: Create FSM events.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new MARKER class object.
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Point#COORDINATE Coordinate Coordinate where to place the marker.
|
||||
-- @param #string Text Text displayed on the mark panel.
|
||||
-- @return #MARKER self
|
||||
function MARKER:New(Coordinate, Text)
|
||||
|
||||
-- Inherit everything from FSM class.
|
||||
local self=BASE:Inherit(self, FSM:New()) -- #MARKER
|
||||
|
||||
self.coordinate=Coordinate
|
||||
|
||||
self.text=Text
|
||||
|
||||
-- Defaults
|
||||
self.readonly=false
|
||||
self.message=""
|
||||
|
||||
-- New marker ID. This is not the one of the actual marker.
|
||||
_MARKERID=_MARKERID+1
|
||||
|
||||
self.myid=_MARKERID
|
||||
|
||||
-- Log ID.
|
||||
self.lid=string.format("Marker #%d | ", self.myid)
|
||||
|
||||
-- Start State.
|
||||
self:SetStartState("Invisible")
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("Invisible", "Added", "Visible") -- Marker was added.
|
||||
self:AddTransition("Visible", "Removed", "Invisible") -- Marker was removed.
|
||||
self:AddTransition("*", "Changed", "*") -- Marker was changed.
|
||||
|
||||
self:AddTransition("*", "TextUpdate", "*") -- Text updated.
|
||||
self:AddTransition("*", "CoordUpdate", "*") -- Coordinates updated.
|
||||
|
||||
--- Triggers the FSM event "Added".
|
||||
-- @function [parent=#MARKER] Added
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
|
||||
--- Triggers the delayed FSM event "Added".
|
||||
-- @function [parent=#MARKER] __Added
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
|
||||
--- On after "Added" event user function.
|
||||
-- @function [parent=#MARKER] OnAfterAdded
|
||||
-- @param #MARKER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
|
||||
|
||||
--- Triggers the FSM event "Removed".
|
||||
-- @function [parent=#MARKER] Removed
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
|
||||
--- Triggers the delayed FSM event "Removed".
|
||||
-- @function [parent=#MARKER] __Removed
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
|
||||
--- On after "Removed" event user function.
|
||||
-- @function [parent=#MARKER] OnAfterRemoved
|
||||
-- @param #MARKER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
|
||||
|
||||
--- Triggers the FSM event "Changed".
|
||||
-- @function [parent=#MARKER] Changed
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
|
||||
--- Triggers the delayed FSM event "Changed".
|
||||
-- @function [parent=#MARKER] __Changed
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
|
||||
--- On after "Changed" event user function.
|
||||
-- @function [parent=#MARKER] OnAfterChanged
|
||||
-- @param #MARKER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
|
||||
|
||||
--- Triggers the FSM event "TextUpdate".
|
||||
-- @function [parent=#MARKER] TextUpdate
|
||||
-- @param #MARKER self
|
||||
-- @param #string Text The new text.
|
||||
|
||||
--- Triggers the delayed FSM event "TextUpdate".
|
||||
-- @function [parent=#MARKER] __TextUpdate
|
||||
-- @param #MARKER self
|
||||
-- @param #string Text The new text.
|
||||
|
||||
--- On after "TextUpdate" event user function.
|
||||
-- @function [parent=#MARKER] OnAfterTextUpdate
|
||||
-- @param #MARKER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #string Text The new text.
|
||||
|
||||
|
||||
--- Triggers the FSM event "CoordUpdate".
|
||||
-- @function [parent=#MARKER] CoordUpdate
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Point#COORDINATE Coordinate The new Coordinate.
|
||||
|
||||
--- Triggers the delayed FSM event "CoordUpdate".
|
||||
-- @function [parent=#MARKER] __CoordUpdate
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Point#COORDINATE Coordinate The updated Coordinate.
|
||||
|
||||
--- On after "CoordUpdate" event user function.
|
||||
-- @function [parent=#MARKER] OnAfterCoordUpdate
|
||||
-- @param #MARKER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Point#COORDINATE Coordinate The updated Coordinate.
|
||||
|
||||
|
||||
-- Handle events.
|
||||
self:HandleEvent(EVENTS.MarkAdded)
|
||||
self:HandleEvent(EVENTS.MarkRemoved)
|
||||
self:HandleEvent(EVENTS.MarkChange)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User API Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Marker is readonly. Text cannot be changed and marker cannot be removed.
|
||||
-- @param #MARKER self
|
||||
-- @return #MARKER self
|
||||
function MARKER:ReadOnly()
|
||||
|
||||
self.readonly=true
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set message that is displayed on screen if the marker is added.
|
||||
-- @param #MARKER self
|
||||
-- @param #string Text Message displayed when the marker is added.
|
||||
-- @return #MARKER self
|
||||
function MARKER:Message(Text)
|
||||
|
||||
self.message=Text or ""
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Place marker visible for everyone.
|
||||
-- @param #MARKER self
|
||||
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||
-- @return #MARKER self
|
||||
function MARKER:ToAll(Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, MARKER.ToAll, self)
|
||||
else
|
||||
|
||||
self.toall=true
|
||||
self.tocoaliton=nil
|
||||
self.coalition=nil
|
||||
self.togroup=nil
|
||||
self.groupname=nil
|
||||
self.groupid=nil
|
||||
|
||||
-- First remove an existing mark.
|
||||
if self.shown then
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
self.mid=UTILS.GetMarkID()
|
||||
|
||||
-- Call DCS function.
|
||||
trigger.action.markToAll(self.mid, self.text, self.coordinate:GetVec3(), self.readonly, self.message)
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Place marker visible for a specific coalition only.
|
||||
-- @param #MARKER self
|
||||
-- @param #number Coalition Coalition 1=Red, 2=Blue, 0=Neutral. See `coaliton.side.RED`.
|
||||
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||
-- @return #MARKER self
|
||||
function MARKER:ToCoalition(Coalition, Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, MARKER.ToCoalition, self, Coalition)
|
||||
else
|
||||
|
||||
self.coalition=Coalition
|
||||
|
||||
self.tocoaliton=true
|
||||
self.toall=false
|
||||
self.togroup=false
|
||||
self.groupname=nil
|
||||
self.groupid=nil
|
||||
|
||||
-- First remove an existing mark.
|
||||
if self.shown then
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
self.mid=UTILS.GetMarkID()
|
||||
|
||||
-- Call DCS function.
|
||||
trigger.action.markToCoalition(self.mid, self.text, self.coordinate:GetVec3(), self.coalition, self.readonly, self.message)
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Place marker visible for the blue coalition only.
|
||||
-- @param #MARKER self
|
||||
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||
-- @return #MARKER self
|
||||
function MARKER:ToBlue(Delay)
|
||||
self:ToCoalition(coalition.side.BLUE, Delay)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Place marker visible for the blue coalition only.
|
||||
-- @param #MARKER self
|
||||
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||
-- @return #MARKER self
|
||||
function MARKER:ToRed(Delay)
|
||||
self:ToCoalition(coalition.side.RED, Delay)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Place marker visible for the neutral coalition only.
|
||||
-- @param #MARKER self
|
||||
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||
-- @return #MARKER self
|
||||
function MARKER:ToNeutral(Delay)
|
||||
self:ToCoalition(coalition.side.NEUTRAL, Delay)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Place marker visible for a specific group only.
|
||||
-- @param #MARKER self
|
||||
-- @param Wrapper.Group#GROUP Group The group to which the marker is displayed.
|
||||
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||
-- @return #MARKER self
|
||||
function MARKER:ToGroup(Group, Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, MARKER.ToGroup, self, Group)
|
||||
else
|
||||
|
||||
-- Check if group exists.
|
||||
if Group and Group:IsAlive()~=nil then
|
||||
|
||||
self.groupid=Group:GetID()
|
||||
|
||||
if self.groupid then
|
||||
|
||||
self.groupname=Group:GetName()
|
||||
|
||||
self.togroup=true
|
||||
self.tocoaliton=nil
|
||||
self.coalition=nil
|
||||
self.toall=nil
|
||||
|
||||
-- First remove an existing mark.
|
||||
if self.shown then
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
self.mid=UTILS.GetMarkID()
|
||||
|
||||
-- Call DCS function.
|
||||
trigger.action.markToGroup(self.mid, self.text, self.coordinate:GetVec3(), self.groupid, self.readonly, self.message)
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
--TODO: Warning!
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Update the text displayed on the mark panel.
|
||||
-- @param #MARKER self
|
||||
-- @param #string Text Updated text.
|
||||
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||
-- @return #MARKER self
|
||||
function MARKER:UpdateText(Text, Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, MARKER.UpdateText, self, Text)
|
||||
else
|
||||
|
||||
self.text=tostring(Text)
|
||||
|
||||
self:Refresh()
|
||||
|
||||
self:TextUpdate(tostring(Text))
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Update the coordinate where the marker is displayed.
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Point#COORDINATE Coordinate The new coordinate.
|
||||
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||
-- @return #MARKER self
|
||||
function MARKER:UpdateCoordinate(Coordinate, Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, MARKER.UpdateCoordinate, self, Coordinate)
|
||||
else
|
||||
|
||||
self.coordinate=Coordinate
|
||||
|
||||
self:Refresh()
|
||||
|
||||
self:CoordUpdate(Coordinate)
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Refresh the marker.
|
||||
-- @param #MARKER self
|
||||
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||
-- @return #MARKER self
|
||||
function MARKER:Refresh(Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, MARKER.Refresh, self)
|
||||
else
|
||||
|
||||
if self.toall then
|
||||
|
||||
self:ToAll()
|
||||
|
||||
elseif self.tocoaliton then
|
||||
|
||||
self:ToCoalition(self.coalition)
|
||||
|
||||
elseif self.togroup then
|
||||
|
||||
local group=GROUP:FindByName(self.groupname)
|
||||
|
||||
self:ToGroup(group)
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: unknown To in :Refresh()!")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove a marker.
|
||||
-- @param #MARKER self
|
||||
-- @param #number Delay (Optional) Delay in seconds, before the marker is removed.
|
||||
-- @return #MARKER self
|
||||
function MARKER:Remove(Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, MARKER.Remove, self)
|
||||
else
|
||||
|
||||
if self.shown then
|
||||
|
||||
-- Call DCS function.
|
||||
trigger.action.removeMark(self.mid)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get position of the marker.
|
||||
-- @param #MARKER self
|
||||
-- @return Core.Point#COORDINATE The coordinate of the marker.
|
||||
function MARKER:GetCoordinate()
|
||||
return self.coordinate
|
||||
end
|
||||
|
||||
--- Get text that is displayed in the marker panel.
|
||||
-- @param #MARKER self
|
||||
-- @return #string Marker text.
|
||||
function MARKER:GetText()
|
||||
return self.text
|
||||
end
|
||||
|
||||
--- Set text that is displayed in the marker panel. Note this does not show the marker.
|
||||
-- @param #MARKER self
|
||||
-- @param #string Text Marker text. Default is an empty sting "".
|
||||
-- @return #MARKER self
|
||||
function MARKER:SetText(Text)
|
||||
self.text=Text and tostring(Text) or ""
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Check if marker is currently visible on the F10 map.
|
||||
-- @param #MARKER self
|
||||
-- @return #boolean True if the marker is currently visible.
|
||||
function MARKER:IsVisible()
|
||||
return self:Is("Visible")
|
||||
end
|
||||
|
||||
--- Check if marker is currently invisible on the F10 map.
|
||||
-- @param #MARKER self
|
||||
-- @return
|
||||
function MARKER:IsInvisible()
|
||||
return self:Is("Invisible")
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Event Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Event function when a MARKER is added.
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function MARKER:OnEventMarkAdded(EventData)
|
||||
|
||||
if EventData and EventData.MarkID then
|
||||
|
||||
local MarkID=EventData.MarkID
|
||||
|
||||
self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID)))
|
||||
|
||||
if MarkID==self.mid then
|
||||
|
||||
self.shown=true
|
||||
|
||||
self:Added(EventData)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Event function when a MARKER is removed.
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function MARKER:OnEventMarkRemoved(EventData)
|
||||
|
||||
if EventData and EventData.MarkID then
|
||||
|
||||
local MarkID=EventData.MarkID
|
||||
|
||||
self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID)))
|
||||
|
||||
if MarkID==self.mid then
|
||||
|
||||
self.shown=false
|
||||
|
||||
self:Removed(EventData)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Event function when a MARKER changed.
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function MARKER:OnEventMarkChange(EventData)
|
||||
|
||||
if EventData and EventData.MarkID then
|
||||
|
||||
local MarkID=EventData.MarkID
|
||||
|
||||
self:T3(self.lid..string.format("Captured event MarkChange for Mark ID=%s", tostring(MarkID)))
|
||||
|
||||
if MarkID==self.mid then
|
||||
|
||||
self:Changed(EventData)
|
||||
|
||||
self:TextChanged(tostring(EventData.MarkText))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Event Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after "Added" event.
|
||||
-- @param #MARKER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
function MARKER:onafterAdded(From, Event, To, EventData)
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Captured event MarkAdded for myself:\n")
|
||||
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
|
||||
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
|
||||
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
|
||||
text=text..string.format("Initiator = %s\n", EventData.IniUnit and EventData.IniUnit:GetName() or "Nobody")
|
||||
text=text..string.format("Coordinate = %s\n", EventData.MarkCoordinate and EventData.MarkCoordinate:ToStringLLDMS() or "Nowhere")
|
||||
text=text..string.format("Text: \n%s", tostring(EventData.MarkText))
|
||||
self:T2(self.lid..text)
|
||||
|
||||
end
|
||||
|
||||
--- On after "Removed" event.
|
||||
-- @param #MARKER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
function MARKER:onafterRemoved(From, Event, To, EventData)
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Captured event MarkRemoved for myself:\n")
|
||||
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
|
||||
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
|
||||
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
|
||||
text=text..string.format("Initiator = %s\n", EventData.IniUnit and EventData.IniUnit:GetName() or "Nobody")
|
||||
text=text..string.format("Coordinate = %s\n", EventData.MarkCoordinate and EventData.MarkCoordinate:ToStringLLDMS() or "Nowhere")
|
||||
text=text..string.format("Text: \n%s", tostring(EventData.MarkText))
|
||||
self:T2(self.lid..text)
|
||||
|
||||
end
|
||||
|
||||
--- On after "Changed" event.
|
||||
-- @param #MARKER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
function MARKER:onafterChanged(From, Event, To, EventData)
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Captured event MarkChange for myself:\n")
|
||||
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
|
||||
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
|
||||
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
|
||||
text=text..string.format("Initiator = %s\n", EventData.IniUnit and EventData.IniUnit:GetName() or "Nobody")
|
||||
text=text..string.format("Coordinate = %s\n", EventData.MarkCoordinate and EventData.MarkCoordinate:ToStringLLDMS() or "Nowhere")
|
||||
text=text..string.format("Text: \n%s", tostring(EventData.MarkText))
|
||||
self:T2(self.lid..text)
|
||||
|
||||
end
|
||||
|
||||
--- On after "TextUpdate" event.
|
||||
-- @param #MARKER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #string Text The updated text, displayed in the mark panel.
|
||||
function MARKER:onafterTextUpdate(From, Event, To, Text)
|
||||
|
||||
self:I(self.lid..string.format("New Marker Text:\n%s", Text))
|
||||
|
||||
end
|
||||
|
||||
--- On after "CoordUpdate" event.
|
||||
-- @param #MARKER self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Point#COORDINATE Coordinate The updated coordinates.
|
||||
function MARKER:onafterCoordUpdate(From, Event, To, Coordinate)
|
||||
|
||||
self:I(self.lid..string.format("New Marker Coordinate in LL DMS: %s", Coordinate:ToStringLLDMS()))
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -33,6 +33,7 @@ Wrapper/Client.lua
|
||||
Wrapper/Static.lua
|
||||
Wrapper/Airbase.lua
|
||||
Wrapper/Scenery.lua
|
||||
Wrapper/Marker.lua
|
||||
|
||||
Cargo/Cargo.lua
|
||||
Cargo/CargoUnit.lua
|
||||
@ -64,6 +65,11 @@ Ops/Airboss.lua
|
||||
Ops/RecoveryTanker.lua
|
||||
Ops/RescueHelo.lua
|
||||
Ops/ATIS.lua
|
||||
Ops/AirWing.lua
|
||||
Ops/Auftrag.lua
|
||||
Ops/FlightGroup.lua
|
||||
Ops/NavyGroup.lua
|
||||
Ops/Squadron.lua
|
||||
|
||||
AI/AI_Balancer.lua
|
||||
AI/AI_Air.lua
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user