mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Updated documentation of SCHEDULER and ZONE and FSM
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- A Finite State Machine (FSM) models a process flow that transitions between various **States** through triggered **Events**.
|
||||
--
|
||||
-- A FSM can only be in one of a finite number of states.
|
||||
-- The machine is in only one state at a time; the state it is in at any given time is called the **current state**.
|
||||
-- It can change from one state to another when initiated by an **__internal__ or __external__ triggering event**, which is called a **transition**.
|
||||
@@ -90,8 +92,43 @@ do -- FSM
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # 1) FSM class, extends @{Base#BASE}
|
||||
--- # FSM class, extends @{Base#BASE}
|
||||
--
|
||||
-- A Finite State Machine (FSM) models a process flow that transitions between various **States** through triggered **Events**.
|
||||
--
|
||||
-- A FSM can only be in one of a finite number of states.
|
||||
-- The machine is in only one state at a time; the state it is in at any given time is called the **current state**.
|
||||
-- It can change from one state to another when initiated by an **__internal__ or __external__ triggering event**, which is called a **transition**.
|
||||
-- An **FSM implementation** is defined by **a list of its states**, **its initial state**, and **the triggering events** for **each possible transition**.
|
||||
-- An FSM implementation is composed out of **two parts**, a set of **state transition rules**, and an implementation set of **state transition handlers**, implementing those transitions.
|
||||
--
|
||||
-- The FSM class supports a **hierarchical implementation of a Finite State Machine**,
|
||||
-- that is, it allows to **embed existing FSM implementations in a master FSM**.
|
||||
-- FSM hierarchies allow for efficient FSM re-use, **not having to re-invent the wheel every time again** when designing complex processes.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The above diagram shows a graphical representation of a FSM implementation for a **Task**, which guides a Human towards a Zone,
|
||||
-- orders him to destroy x targets and account the results.
|
||||
-- Other examples of ready made FSM could be:
|
||||
--
|
||||
-- * route a plane to a zone flown by a human
|
||||
-- * detect targets by an AI and report to humans
|
||||
-- * account for destroyed targets by human players
|
||||
-- * handle AI infantry to deploy from or embark to a helicopter or airplane or vehicle
|
||||
-- * let an AI patrol a zone
|
||||
--
|
||||
-- The **MOOSE framework** uses extensively the FSM class and derived FSM\_ classes,
|
||||
-- because **the goal of MOOSE is to simplify mission design complexity for mission building**.
|
||||
-- By efficiently utilizing the FSM class and derived classes, MOOSE allows mission designers to quickly build processes.
|
||||
-- **Ready made FSM-based implementations classes** exist within the MOOSE framework that **can easily be re-used,
|
||||
-- and tailored** by mission designers through **the implementation of Transition Handlers**.
|
||||
-- Each of these FSM implementation classes start either with:
|
||||
--
|
||||
-- * an acronym **AI\_**, which indicates an FSM implementation directing **AI controlled** @{GROUP} and/or @{UNIT}. These AI\_ classes derive the @{#FSM_CONTROLLABLE} class.
|
||||
-- * an acronym **TASK\_**, which indicates an FSM implementation executing a @{TASK} executed by Groups of players. These TASK\_ classes derive the @{#FSM_TASK} class.
|
||||
-- * an acronym **ACT\_**, which indicates an Sub-FSM implementation, directing **Humans actions** that need to be done in a @{TASK}, seated in a @{CLIENT} (slot) or a @{UNIT} (CA join). These ACT\_ classes derive the @{#FSM_PROCESS} class.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The FSM class is the base class of all FSM\_ derived classes. It implements the main functionality to define and execute Finite State Machines.
|
||||
@@ -114,13 +151,13 @@ do -- FSM
|
||||
-- As explained above, a FSM supports **Linear State Transitions** and **Hierarchical State Transitions**, and both can be mixed to make a comprehensive FSM implementation.
|
||||
-- The below documentation has a seperate chapter explaining both transition modes, taking into account the **Transition Rules**, **Transition Handlers** and **Event Triggers**.
|
||||
--
|
||||
-- ## 1.1) FSM Linear Transitions
|
||||
-- ## FSM Linear Transitions
|
||||
--
|
||||
-- Linear Transitions are Transition Rules allowing an FSM to transition from one or multiple possible **From** state(s) towards a **To** state upon a Triggered **Event**.
|
||||
-- The Lineair transition rule evaluation will always be done from the **current state** of the FSM.
|
||||
-- If no valid Transition Rule can be found in the FSM, the FSM will log an error and stop.
|
||||
--
|
||||
-- ### 1.1.1) FSM Transition Rules
|
||||
-- ### FSM Transition Rules
|
||||
--
|
||||
-- The FSM has transition rules that it follows and validates, as it walks the process.
|
||||
-- These rules define when an FSM can transition from a specific state towards an other specific state upon a triggered event.
|
||||
@@ -145,7 +182,7 @@ do -- FSM
|
||||
-- * It can be switched **Off** by triggering event **SwitchOff**.
|
||||
-- * Note that once the Switch is **On** or **Middle**, it can only be switched **Off**.
|
||||
--
|
||||
-- ### Some additional comments:
|
||||
-- #### Some additional comments:
|
||||
--
|
||||
-- Note that Linear Transition Rules **can be declared in a few variations**:
|
||||
--
|
||||
@@ -156,7 +193,7 @@ do -- FSM
|
||||
--
|
||||
-- FsmSwitch:AddTransition( { "On", "Middle" }, "SwitchOff", "Off" )
|
||||
--
|
||||
-- ### 1.1.2) Transition Handling
|
||||
-- ### Transition Handling
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -178,7 +215,7 @@ do -- FSM
|
||||
--
|
||||
-- On top, each of these methods can have a variable amount of parameters passed. See the example in section [1.1.3](#1.1.3\)-event-triggers).
|
||||
--
|
||||
-- ### 1.1.3) Event Triggers
|
||||
-- ### Event Triggers
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -216,7 +253,7 @@ do -- FSM
|
||||
--
|
||||
-- Because ... When Event was asynchronously processed after 5 seconds, Amount was set to 2. So be careful when processing and passing values and objects in asynchronous processing!
|
||||
--
|
||||
-- ### 1.1.4) Linear Transition Example
|
||||
-- ### Linear Transition Example
|
||||
--
|
||||
-- This example is fully implemented in the MOOSE test mission on GITHUB: [FSM-100 - Transition Explanation](https://github.com/FlightControl-Master/MOOSE/blob/master/Moose%20Test%20Missions/FSM%20-%20Finite%20State%20Machine/FSM-100%20-%20Transition%20Explanation/FSM-100%20-%20Transition%20Explanation.lua)
|
||||
--
|
||||
@@ -298,7 +335,7 @@ do -- FSM
|
||||
-- So... When FsmDemo:Stop() is being triggered, the state of FsmDemo will transition from Red or Green to Stopped.
|
||||
-- And there is no transition handling method defined for that transition, thus, no new event is being triggered causing the FsmDemo process flow to halt.
|
||||
--
|
||||
-- ## 1.5) FSM Hierarchical Transitions
|
||||
-- ## FSM Hierarchical Transitions
|
||||
--
|
||||
-- Hierarchical Transitions allow to re-use readily available and implemented FSMs.
|
||||
-- This becomes in very useful for mission building, where mission designers build complex processes and workflows,
|
||||
|
||||
@@ -4,31 +4,30 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # 1) @{Scheduler#SCHEDULER} class, extends @{Base#BASE}
|
||||
-- SCHEDULER manages the **scheduling of functions**:
|
||||
--
|
||||
-- The @{Scheduler#SCHEDULER} class creates schedule.
|
||||
--
|
||||
-- ## 1.1) SCHEDULER constructor
|
||||
--
|
||||
-- The SCHEDULER class is quite easy to use, but note that the New constructor has variable parameters:
|
||||
--
|
||||
-- * @{Scheduler#SCHEDULER.New}( nil ): Setup a new SCHEDULER object, which is persistently executed after garbage collection.
|
||||
-- * @{Scheduler#SCHEDULER.New}( Object ): Setup a new SCHEDULER object, which is linked to the Object. When the Object is nillified or destroyed, the SCHEDULER object will also be destroyed and stopped after garbage collection.
|
||||
-- * @{Scheduler#SCHEDULER.New}( nil, Function, FunctionArguments, Start, ... ): Setup a new persistent SCHEDULER object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
|
||||
-- * @{Scheduler#SCHEDULER.New}( Object, Function, FunctionArguments, Start, ... ): Setup a new SCHEDULER object, linked to Object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
|
||||
--
|
||||
-- ## 1.2) SCHEDULER timer stopping and (re-)starting.
|
||||
--
|
||||
-- The SCHEDULER can be stopped and restarted with the following methods:
|
||||
--
|
||||
-- * @{Scheduler#SCHEDULER.Start}(): (Re-)Start the schedules within the SCHEDULER object. If a CallID is provided to :Start(), only the schedule referenced by CallID will be (re-)started.
|
||||
-- * @{Scheduler#SCHEDULER.Stop}(): Stop the schedules within the SCHEDULER object. If a CallID is provided to :Stop(), then only the schedule referenced by CallID will be stopped.
|
||||
--
|
||||
-- ## 1.3) Create a new schedule
|
||||
--
|
||||
-- With @{Scheduler#SCHEDULER.Schedule}() a new time event can be scheduled. This function is used by the :New() constructor when a new schedule is planned.
|
||||
-- * optionally in an optional specified time interval,
|
||||
-- * optionally **repeating** with a specified time repeat interval,
|
||||
-- * optionally **randomizing** with a specified time interval randomization factor,
|
||||
-- * optionally **stop** the repeating after a specified time interval.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # Demo Missions
|
||||
--
|
||||
-- ### [SCHEDULER Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SCH%20-%20Scheduler)
|
||||
--
|
||||
-- ### [SCHEDULER Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SCH%20-%20Scheduler)
|
||||
--
|
||||
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # YouTube Channel
|
||||
--
|
||||
-- ### [SCHEDULER YouTube Channel (none)]()
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- ### Contributions:
|
||||
--
|
||||
@@ -38,10 +37,6 @@
|
||||
--
|
||||
-- * FlightControl : Design & Programming
|
||||
--
|
||||
-- ### Test Missions:
|
||||
--
|
||||
-- * SCH - Scheduler
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Scheduler
|
||||
@@ -51,6 +46,153 @@
|
||||
-- @type SCHEDULER
|
||||
-- @field #number ScheduleID the ID of the scheduler.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # SCHEDULER class, extends @{Base#BASE}
|
||||
--
|
||||
-- The SCHEDULER class creates schedule.
|
||||
--
|
||||
-- A SCHEDULER can manage **multiple** (repeating) schedules. Each planned or executing schedule has a unique **ScheduleID**.
|
||||
-- The ScheduleID is returned when the method @{#SCHEDULER.Schedule}() is called.
|
||||
-- It is recommended to store the ScheduleID in a variable, as it is used in the methods @{SCHEDULER.Start}() and @{SCHEDULER.Stop}(),
|
||||
-- which can start and stop specific repeating schedules respectively within a SCHEDULER object.
|
||||
--
|
||||
-- ## SCHEDULER constructor
|
||||
--
|
||||
-- The SCHEDULER class is quite easy to use, but note that the New constructor has variable parameters:
|
||||
--
|
||||
-- The @{#SCHEDULER.New}() method returns 2 variables:
|
||||
--
|
||||
-- 1. The SCHEDULER object reference.
|
||||
-- 2. The first schedule planned in the SCHEDULER object.
|
||||
--
|
||||
-- To clarify the different appliances, lets have a look at the following examples:
|
||||
--
|
||||
-- ### Construct a SCHEDULER object without a persistent schedule.
|
||||
--
|
||||
-- * @{#SCHEDULER.New}( nil ): Setup a new SCHEDULER object, which is persistently executed after garbage collection.
|
||||
--
|
||||
-- SchedulerObject = SCHEDULER:New()
|
||||
-- SchedulerID = SchedulerObject:Schedule( nil, ScheduleFunction, {} )
|
||||
--
|
||||
-- The above example creates a new SchedulerObject, but does not schedule anything.
|
||||
-- A separate schedule is created by using the SchedulerObject using the method :Schedule..., which returns a ScheduleID
|
||||
--
|
||||
-- ### Construct a SCHEDULER object without a volatile schedule, but volatile to the Object existence...
|
||||
--
|
||||
-- * @{#SCHEDULER.New}( Object ): Setup a new SCHEDULER object, which is linked to the Object. When the Object is nillified or destroyed, the SCHEDULER object will also be destroyed and stopped after garbage collection.
|
||||
--
|
||||
-- ZoneObject = ZONE:New( "ZoneName" )
|
||||
-- SchedulerObject = SCHEDULER:New( ZoneObject )
|
||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
||||
-- ...
|
||||
-- ZoneObject = nil
|
||||
-- garbagecollect()
|
||||
--
|
||||
-- The above example creates a new SchedulerObject, but does not schedule anything, and is bound to the existence of ZoneObject, which is a ZONE.
|
||||
-- A separate schedule is created by using the SchedulerObject using the method :Schedule()..., which returns a ScheduleID
|
||||
-- Later in the logic, the ZoneObject is put to nil, and garbage is collected.
|
||||
-- As a result, the ScheduleObject will cancel any planned schedule.
|
||||
--
|
||||
-- ### Construct a SCHEDULER object with a persistent schedule.
|
||||
--
|
||||
-- * @{#SCHEDULER.New}( nil, Function, FunctionArguments, Start, ... ): Setup a new persistent SCHEDULER object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
|
||||
--
|
||||
-- SchedulerObject, SchedulerID = SCHEDULER:New( nil, ScheduleFunction, {} )
|
||||
--
|
||||
-- The above example creates a new SchedulerObject, and does schedule the first schedule as part of the call.
|
||||
-- Note that 2 variables are returned here: SchedulerObject, ScheduleID...
|
||||
--
|
||||
-- ### Construct a SCHEDULER object without a schedule, but volatile to the Object existence...
|
||||
--
|
||||
-- * @{#SCHEDULER.New}( Object, Function, FunctionArguments, Start, ... ): Setup a new SCHEDULER object, linked to Object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
|
||||
--
|
||||
-- ZoneObject = ZONE:New( "ZoneName" )
|
||||
-- SchedulerObject, SchedulerID = SCHEDULER:New( ZoneObject, ScheduleFunction, {} )
|
||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
||||
-- ...
|
||||
-- ZoneObject = nil
|
||||
-- garbagecollect()
|
||||
--
|
||||
-- The above example creates a new SchedulerObject, and schedules a method call (ScheduleFunction),
|
||||
-- and is bound to the existence of ZoneObject, which is a ZONE object (ZoneObject).
|
||||
-- Both a ScheduleObject and a SchedulerID variable are returned.
|
||||
-- Later in the logic, the ZoneObject is put to nil, and garbage is collected.
|
||||
-- As a result, the ScheduleObject will cancel the planned schedule.
|
||||
--
|
||||
-- ## SCHEDULER timer stopping and (re-)starting.
|
||||
--
|
||||
-- The SCHEDULER can be stopped and restarted with the following methods:
|
||||
--
|
||||
-- * @{#SCHEDULER.Start}(): (Re-)Start the schedules within the SCHEDULER object. If a CallID is provided to :Start(), only the schedule referenced by CallID will be (re-)started.
|
||||
-- * @{#SCHEDULER.Stop}(): Stop the schedules within the SCHEDULER object. If a CallID is provided to :Stop(), then only the schedule referenced by CallID will be stopped.
|
||||
--
|
||||
-- ZoneObject = ZONE:New( "ZoneName" )
|
||||
-- SchedulerObject, SchedulerID = SCHEDULER:New( ZoneObject, ScheduleFunction, {} )
|
||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 10 )
|
||||
-- ...
|
||||
-- SchedulerObject:Stop( SchedulerID )
|
||||
-- ...
|
||||
-- SchedulerObject:Start( SchedulerID )
|
||||
--
|
||||
-- The above example creates a new SchedulerObject, and does schedule the first schedule as part of the call.
|
||||
-- Note that 2 variables are returned here: SchedulerObject, ScheduleID...
|
||||
-- Later in the logic, the repeating schedule with SchedulerID is stopped.
|
||||
-- A bit later, the repeating schedule with SchedulerId is (re)-started.
|
||||
--
|
||||
-- ## Create a new schedule
|
||||
--
|
||||
-- With the method @{#SCHEDULER.Schedule}() a new time event can be scheduled.
|
||||
-- This method is used by the :New() constructor when a new schedule is planned.
|
||||
--
|
||||
-- Consider the following code fragment of the SCHEDULER object creation.
|
||||
--
|
||||
-- ZoneObject = ZONE:New( "ZoneName" )
|
||||
-- SchedulerObject = SCHEDULER:New( ZoneObject )
|
||||
--
|
||||
-- Several parameters can be specified that influence the behaviour of a Schedule.
|
||||
--
|
||||
-- ### A single schedule, immediately executed
|
||||
--
|
||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
||||
--
|
||||
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within milleseconds ...
|
||||
--
|
||||
-- ### A single schedule, planned over time
|
||||
--
|
||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10 )
|
||||
--
|
||||
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds ...
|
||||
--
|
||||
-- ### A schedule with a repeating time interval, planned over time
|
||||
--
|
||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60 )
|
||||
--
|
||||
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
|
||||
-- and repeating 60 every seconds ...
|
||||
--
|
||||
-- ### A schedule with a repeating time interval, planned over time, with time interval randomization
|
||||
--
|
||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60, 0.5 )
|
||||
--
|
||||
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
|
||||
-- and repeating 60 seconds, with a 50% time interval randomization ...
|
||||
-- So the repeating time interval will be randomized using the **0.5**,
|
||||
-- and will calculate between **60 - ( 60 * 0.5 )** and **60 + ( 60 * 0.5 )** for each repeat,
|
||||
-- which is in this example between **30** and **90** seconds.
|
||||
--
|
||||
-- ### A schedule with a repeating time interval, planned over time, with time interval randomization, and stop after a time interval
|
||||
--
|
||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60, 0.5, 300 )
|
||||
--
|
||||
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
|
||||
-- The schedule will repeat every 60 seconds.
|
||||
-- So the repeating time interval will be randomized using the **0.5**,
|
||||
-- and will calculate between **60 - ( 60 * 0.5 )** and **60 + ( 60 * 0.5 )** for each repeat,
|
||||
-- which is in this example between **30** and **90** seconds.
|
||||
-- The schedule will stop after **300** seconds.
|
||||
--
|
||||
-- @field #SCHEDULER
|
||||
SCHEDULER = {
|
||||
ClassName = "SCHEDULER",
|
||||
Schedules = {},
|
||||
|
||||
@@ -66,8 +66,7 @@
|
||||
-- @module Zone
|
||||
|
||||
|
||||
--- The ZONE_BASE class
|
||||
-- @type ZONE_BASE
|
||||
--- @type ZONE_BASE
|
||||
-- @field #string ZoneName Name of the zone.
|
||||
-- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
||||
-- @extends Core.Base#BASE
|
||||
@@ -83,19 +82,26 @@
|
||||
--
|
||||
-- ## Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}:
|
||||
--
|
||||
-- * @{#ZONE_BASE.IsVec2InZone}(): Returns if a Vec2 is within the zone.
|
||||
-- * @{#ZONE_BASE.IsVec3InZone}(): Returns if a Vec3 is within the zone.
|
||||
-- * @{#ZONE_BASE.IsVec2InZone}(): Returns if a 2D vector is within the zone.
|
||||
-- * @{#ZONE_BASE.IsVec3InZone}(): Returns if a 3D vector is within the zone.
|
||||
-- * @{#ZONE_BASE.IsPointVec2InZone}(): Returns if a 2D point vector is within the zone.
|
||||
-- * @{#ZONE_BASE.IsPointVec3InZone}(): Returns if a 3D point vector is within the zone.
|
||||
--
|
||||
-- ## A zone has a probability factor that can be set to randomize a selection between zones:
|
||||
--
|
||||
-- * @{#ZONE_BASE.SetRandomizeProbability}(): Set the randomization probability of a zone to be selected, taking a value between 0 and 1 ( 0 = 0%, 1 = 100% )
|
||||
-- * @{#ZONE_BASE.GetRandomizeProbability}(): Get the randomization probability of a zone to be selected, passing a value between 0 and 1 ( 0 = 0%, 1 = 100% )
|
||||
-- * @{#ZONE_BASE.SetZoneProbability}(): Set the randomization probability of a zone to be selected, taking a value between 0 and 1 ( 0 = 0%, 1 = 100% )
|
||||
-- * @{#ZONE_BASE.GetZoneProbability}(): Get the randomization probability of a zone to be selected, passing a value between 0 and 1 ( 0 = 0%, 1 = 100% )
|
||||
-- * @{#ZONE_BASE.GetZoneMaybe}(): Get the zone taking into account the randomization probability. nil is returned if this zone is not a candidate.
|
||||
--
|
||||
-- ## A zone manages Vectors:
|
||||
-- ## A zone manages vectors:
|
||||
--
|
||||
-- * @{#ZONE_BASE.GetVec2}(): Returns the @{DCSTypes#Vec2} coordinate of the zone.
|
||||
-- * @{#ZONE_BASE.GetRandomVec2}(): Define a random @{DCSTypes#Vec2} within the zone.
|
||||
-- * @{#ZONE_BASE.GetVec2}(): Returns the 2D vector coordinate of the zone.
|
||||
-- * @{#ZONE_BASE.GetVec3}(): Returns the 3D vector coordinate of the zone.
|
||||
-- * @{#ZONE_BASE.GetPointVec2}(): Returns the 2D point vector coordinate of the zone.
|
||||
-- * @{#ZONE_BASE.GetPointVec3}(): Returns the 3D point vector coordinate of the zone.
|
||||
-- * @{#ZONE_BASE.GetRandomVec2}(): Define a random 2D vector within the zone.
|
||||
-- * @{#ZONE_BASE.GetRandomPointVec2}(): Define a random 2D point vector within the zone.
|
||||
-- * @{#ZONE_BASE.GetRandomPointVec3}(): Define a random 3D point vector within the zone.
|
||||
--
|
||||
-- ## A zone has a bounding square:
|
||||
--
|
||||
@@ -106,8 +112,7 @@
|
||||
-- * @{#ZONE_BASE.SmokeZone}(): Smokes the zone boundaries in a color.
|
||||
-- * @{#ZONE_BASE.FlareZone}(): Flares the zone boundaries in a color.
|
||||
--
|
||||
-- @field #ZONE_BASE ZONE_BASE
|
||||
--
|
||||
-- @field #ZONE_BASE
|
||||
ZONE_BASE = {
|
||||
ClassName = "ZONE_BASE",
|
||||
ZoneName = "",
|
||||
@@ -366,8 +371,7 @@ end
|
||||
-- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Point#POINT_VEC2} object representing a random 2D point in the zone.
|
||||
-- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Point#POINT_VEC3} object representing a random 3D point in the zone. Note that the height of the point is at landheight.
|
||||
--
|
||||
-- @field #ZONE_RADIUS ZONE_RADIUS
|
||||
--
|
||||
-- @field #ZONE_RADIUS
|
||||
ZONE_RADIUS = {
|
||||
ClassName="ZONE_RADIUS",
|
||||
}
|
||||
@@ -648,8 +652,7 @@ end
|
||||
-- The ZONE class, defined by the zone name as defined within the Mission Editor.
|
||||
-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--
|
||||
-- @field #ZONE ZONE
|
||||
--
|
||||
-- @field #ZONE
|
||||
ZONE = {
|
||||
ClassName="ZONE",
|
||||
}
|
||||
@@ -686,8 +689,7 @@ end
|
||||
-- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius.
|
||||
-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--
|
||||
-- @field #ZONE_UNIT ZONE_UNIT
|
||||
--
|
||||
-- @field #ZONE_UNIT
|
||||
ZONE_UNIT = {
|
||||
ClassName="ZONE_UNIT",
|
||||
}
|
||||
@@ -769,7 +771,6 @@ function ZONE_UNIT:GetVec3( Height )
|
||||
end
|
||||
|
||||
--- @type ZONE_GROUP
|
||||
-- @field Wrapper.Group#GROUP ZoneGROUP
|
||||
-- @extends #ZONE_RADIUS
|
||||
|
||||
|
||||
@@ -778,8 +779,7 @@ end
|
||||
-- The ZONE_GROUP class defines by a zone around a @{Group#GROUP} with a radius. The current leader of the group defines the center of the zone.
|
||||
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--
|
||||
-- @field #ZONE_GROUP ZONE_GROUP
|
||||
--
|
||||
-- @field #ZONE_GROUP
|
||||
ZONE_GROUP = {
|
||||
ClassName="ZONE_GROUP",
|
||||
}
|
||||
@@ -794,7 +794,7 @@ function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius )
|
||||
local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius ) )
|
||||
self:F( { ZoneName, ZoneGROUP:GetVec2(), Radius } )
|
||||
|
||||
self.ZoneGROUP = ZoneGROUP
|
||||
self._.ZoneGROUP = ZoneGROUP
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -806,7 +806,7 @@ end
|
||||
function ZONE_GROUP:GetVec2()
|
||||
self:F( self.ZoneName )
|
||||
|
||||
local ZoneVec2 = self.ZoneGROUP:GetVec2()
|
||||
local ZoneVec2 = self._.ZoneGROUP:GetVec2()
|
||||
|
||||
self:T( { ZoneVec2 } )
|
||||
|
||||
@@ -820,7 +820,7 @@ function ZONE_GROUP:GetRandomVec2()
|
||||
self:F( self.ZoneName )
|
||||
|
||||
local Point = {}
|
||||
local Vec2 = self.ZoneGROUP:GetVec2()
|
||||
local Vec2 = self._.ZoneGROUP:GetVec2()
|
||||
|
||||
local angle = math.random() * math.pi*2;
|
||||
Point.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius();
|
||||
@@ -834,7 +834,7 @@ end
|
||||
|
||||
|
||||
--- @type ZONE_POLYGON_BASE
|
||||
-- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCSTypes#Vec2}.
|
||||
-- --@field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCSTypes#Vec2}.
|
||||
-- @extends #ZONE_BASE
|
||||
|
||||
|
||||
@@ -852,8 +852,7 @@ end
|
||||
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Point#POINT_VEC2} object representing a random 2D point within the zone.
|
||||
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Point#POINT_VEC3} object representing a random 3D point at landheight within the zone.
|
||||
--
|
||||
-- @field #ZONE_POLYGON_BASE ZONE_POLYGON_BASE
|
||||
--
|
||||
-- @field #ZONE_POLYGON_BASE
|
||||
ZONE_POLYGON_BASE = {
|
||||
ClassName="ZONE_POLYGON_BASE",
|
||||
}
|
||||
@@ -874,12 +873,12 @@ function ZONE_POLYGON_BASE:New( ZoneName, PointsArray )
|
||||
|
||||
local i = 0
|
||||
|
||||
self.Polygon = {}
|
||||
self._.Polygon = {}
|
||||
|
||||
for i = 1, #PointsArray do
|
||||
self.Polygon[i] = {}
|
||||
self.Polygon[i].x = PointsArray[i].x
|
||||
self.Polygon[i].y = PointsArray[i].y
|
||||
self._.Polygon[i] = {}
|
||||
self._.Polygon[i].x = PointsArray[i].x
|
||||
self._.Polygon[i].y = PointsArray[i].y
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -902,7 +901,7 @@ end
|
||||
function ZONE_POLYGON_BASE:Flush()
|
||||
self:F2()
|
||||
|
||||
self:E( { Polygon = self.ZoneName, Coordinates = self.Polygon } )
|
||||
self:E( { Polygon = self.ZoneName, Coordinates = self._.Polygon } )
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -918,17 +917,17 @@ function ZONE_POLYGON_BASE:BoundZone( UnBound )
|
||||
local Segments = 10
|
||||
|
||||
i = 1
|
||||
j = #self.Polygon
|
||||
j = #self._.Polygon
|
||||
|
||||
while i <= #self.Polygon do
|
||||
self:T( { i, j, self.Polygon[i], self.Polygon[j] } )
|
||||
while i <= #self._.Polygon do
|
||||
self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } )
|
||||
|
||||
local DeltaX = self.Polygon[j].x - self.Polygon[i].x
|
||||
local DeltaY = self.Polygon[j].y - self.Polygon[i].y
|
||||
local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x
|
||||
local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y
|
||||
|
||||
for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line.
|
||||
local PointX = self.Polygon[i].x + ( Segment * DeltaX / Segments )
|
||||
local PointY = self.Polygon[i].y + ( Segment * DeltaY / Segments )
|
||||
local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments )
|
||||
local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments )
|
||||
local Tire = {
|
||||
["country"] = "USA",
|
||||
["category"] = "Fortifications",
|
||||
@@ -968,17 +967,17 @@ function ZONE_POLYGON_BASE:SmokeZone( SmokeColor )
|
||||
local Segments = 10
|
||||
|
||||
i = 1
|
||||
j = #self.Polygon
|
||||
j = #self._.Polygon
|
||||
|
||||
while i <= #self.Polygon do
|
||||
self:T( { i, j, self.Polygon[i], self.Polygon[j] } )
|
||||
while i <= #self._.Polygon do
|
||||
self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } )
|
||||
|
||||
local DeltaX = self.Polygon[j].x - self.Polygon[i].x
|
||||
local DeltaY = self.Polygon[j].y - self.Polygon[i].y
|
||||
local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x
|
||||
local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y
|
||||
|
||||
for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line.
|
||||
local PointX = self.Polygon[i].x + ( Segment * DeltaX / Segments )
|
||||
local PointY = self.Polygon[i].y + ( Segment * DeltaY / Segments )
|
||||
local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments )
|
||||
local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments )
|
||||
POINT_VEC2:New( PointX, PointY ):Smoke( SmokeColor )
|
||||
end
|
||||
j = i
|
||||
@@ -1004,12 +1003,12 @@ function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 )
|
||||
local InPolygon = false
|
||||
|
||||
Next = 1
|
||||
Prev = #self.Polygon
|
||||
Prev = #self._.Polygon
|
||||
|
||||
while Next <= #self.Polygon do
|
||||
self:T( { Next, Prev, self.Polygon[Next], self.Polygon[Prev] } )
|
||||
if ( ( ( self.Polygon[Next].y > Vec2.y ) ~= ( self.Polygon[Prev].y > Vec2.y ) ) and
|
||||
( Vec2.x < ( self.Polygon[Prev].x - self.Polygon[Next].x ) * ( Vec2.y - self.Polygon[Next].y ) / ( self.Polygon[Prev].y - self.Polygon[Next].y ) + self.Polygon[Next].x )
|
||||
while Next <= #self._.Polygon do
|
||||
self:T( { Next, Prev, self._.Polygon[Next], self._.Polygon[Prev] } )
|
||||
if ( ( ( self._.Polygon[Next].y > Vec2.y ) ~= ( self._.Polygon[Prev].y > Vec2.y ) ) and
|
||||
( Vec2.x < ( self._.Polygon[Prev].x - self._.Polygon[Next].x ) * ( Vec2.y - self._.Polygon[Next].y ) / ( self._.Polygon[Prev].y - self._.Polygon[Next].y ) + self._.Polygon[Next].x )
|
||||
) then
|
||||
InPolygon = not InPolygon
|
||||
end
|
||||
@@ -1080,17 +1079,17 @@ end
|
||||
-- @return #ZONE_POLYGON_BASE.BoundingSquare The bounding square.
|
||||
function ZONE_POLYGON_BASE:GetBoundingSquare()
|
||||
|
||||
local x1 = self.Polygon[1].x
|
||||
local y1 = self.Polygon[1].y
|
||||
local x2 = self.Polygon[1].x
|
||||
local y2 = self.Polygon[1].y
|
||||
local x1 = self._.Polygon[1].x
|
||||
local y1 = self._.Polygon[1].y
|
||||
local x2 = self._.Polygon[1].x
|
||||
local y2 = self._.Polygon[1].y
|
||||
|
||||
for i = 2, #self.Polygon do
|
||||
self:T2( { self.Polygon[i], x1, y1, x2, y2 } )
|
||||
x1 = ( x1 > self.Polygon[i].x ) and self.Polygon[i].x or x1
|
||||
x2 = ( x2 < self.Polygon[i].x ) and self.Polygon[i].x or x2
|
||||
y1 = ( y1 > self.Polygon[i].y ) and self.Polygon[i].y or y1
|
||||
y2 = ( y2 < self.Polygon[i].y ) and self.Polygon[i].y or y2
|
||||
for i = 2, #self._.Polygon do
|
||||
self:T2( { self._.Polygon[i], x1, y1, x2, y2 } )
|
||||
x1 = ( x1 > self._.Polygon[i].x ) and self._.Polygon[i].x or x1
|
||||
x2 = ( x2 < self._.Polygon[i].x ) and self._.Polygon[i].x or x2
|
||||
y1 = ( y1 > self._.Polygon[i].y ) and self._.Polygon[i].y or y1
|
||||
y2 = ( y2 < self._.Polygon[i].y ) and self._.Polygon[i].y or y2
|
||||
|
||||
end
|
||||
|
||||
@@ -1107,8 +1106,7 @@ end
|
||||
-- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
|
||||
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--
|
||||
-- @field #ZONE_POLYGON ZONE_POLYGON
|
||||
--
|
||||
-- @field #ZONE_POLYGON
|
||||
ZONE_POLYGON = {
|
||||
ClassName="ZONE_POLYGON",
|
||||
}
|
||||
@@ -1124,7 +1122,7 @@ function ZONE_POLYGON:New( ZoneName, ZoneGroup )
|
||||
local GroupPoints = ZoneGroup:GetTaskRoute()
|
||||
|
||||
local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( ZoneName, GroupPoints ) )
|
||||
self:F( { ZoneName, ZoneGroup, self.Polygon } )
|
||||
self:F( { ZoneName, ZoneGroup, self._.Polygon } )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user