diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 34ebf940f..49c33183b 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -300,6 +300,45 @@ do -- COORDINATE return { x = self.x, y = self.z } end + --- Update x,y,z coordinates from a given 3D vector. + -- @param #COORDINATE self + -- @param DCS#Vec3 Vec3 The 3D vector with x,y,z components. + -- @return #COORDINATE The modified COORDINATE itself. + function COORDINATE:UpdateFromVec3(Vec3) + + self.x=Vec3.x + self.y=Vec3.y + self.z=Vec3.z + + return self + end + + --- Update x,y,z coordinates from another given COORDINATE. + -- @param #COORDINATE self + -- @param #COORDINATE Coordinate The coordinate with the new x,y,z positions. + -- @return #COORDINATE The modified COORDINATE itself. + function COORDINATE:UpdateFromCoordinate(Coordinate) + + self.x=Coordinate.x + self.y=Coordinate.y + self.z=Coordinate.z + + return self + end + + --- Update x and z coordinates from a given 2D vector. + -- @param #COORDINATE self + -- @param DCS#Vec2 Vec2 The 2D vector with x,y components. x is overwriting COORDINATE.x while y is overwriting COORDINATE.z. + -- @return #COORDINATE The modified COORDINATE itself. + function COORDINATE:UpdateFromVec2(Vec2) + + self.x=Vec2.x + self.z=Vec2.y + + return self + end + + --- Returns the coordinate from the latitude and longitude given in decimal degrees. -- @param #COORDINATE self -- @param #number latitude Latitude in decimal degrees. @@ -503,19 +542,27 @@ do -- COORDINATE -- @param DCS#Distance Distance The Distance to be added in meters. -- @param DCS#Angle Angle The Angle in degrees. Defaults to 0 if not specified (nil). -- @param #boolean Keepalt If true, keep altitude of original coordinate. Default is that the new coordinate is created at the translated land height. - -- @return Core.Point#COORDINATE The new calculated COORDINATE. - function COORDINATE:Translate( Distance, Angle, Keepalt ) - local SX = self.x - local SY = self.z - local Radians = (Angle or 0) / 180 * math.pi - local TX = Distance * math.cos( Radians ) + SX - local TY = Distance * math.sin( Radians ) + SY - - if Keepalt then - return COORDINATE:NewFromVec3( { x = TX, y=self.y, z = TY } ) + -- @param #boolean Overwrite If true, overwrite the original COORDINATE with the translated one. Otherwise, create a new COODINATE. + -- @return #COORDINATE The new calculated COORDINATE. + function COORDINATE:Translate( Distance, Angle, Keepalt, Overwrite ) + + -- Angle in rad. + local alpha = math.rad((Angle or 0)) + + local x = Distance * math.cos(alpha) + self.x -- New x + local z = Distance * math.sin(alpha) + self.z -- New z + + local y=Keepalt and self.y or land.getHeight({x=x, y=z}) + + if Overwrite then + self.x=x + self.y=y + self.z=z + return self else - return COORDINATE:NewFromVec2( { x = TX, y = TY } ) + return COORDINATE:New(x, y, z) end + end --- Rotate coordinate in 2D (x,z) space. @@ -1356,7 +1403,7 @@ do -- COORDINATE -- @param #number Coalition (Optional) Coalition of the airbase. -- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate. -- @return #number Distance to the closest airbase in meters. - function COORDINATE:GetClosestAirbase(Category, Coalition) + function COORDINATE:GetClosestAirbase2(Category, Coalition) -- Get all airbases of the map. local airbases=AIRBASE.GetAllAirbases(Coalition) @@ -1389,6 +1436,36 @@ do -- COORDINATE return closest,distmin end + + --- Gets the nearest airbase with respect to the current coordinates. + -- @param #COORDINATE self + -- @param #number Category (Optional) Category of the airbase. Enumerator of @{Wrapper.Airbase#AIRBASE.Category}. + -- @param #number Coalition (Optional) Coalition of the airbase. + -- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate. + -- @return #number Distance to the closest airbase in meters. + function COORDINATE:GetClosestAirbase(Category, Coalition) + + local a=self:GetVec3() + + local distmin=math.huge + local airbase=nil + for DCSairbaseID, DCSairbase in pairs(world.getAirbases(Coalition)) do + local b=DCSairbase:getPoint() + + local c=UTILS.VecSubstract(a,b) + local dist=UTILS.VecNorm(c) + + --env.info(string.format("Airbase %s dist=%d category=%d", DCSairbase:getName(), dist, DCSairbase:getCategory())) + + if dist +-- @list Table of 2D vectors. + +--- A 3D points array. +-- @type ZONE_POLYGON_BASE.ListVec3 +-- @list Table of 3D vectors. --- Constructor to create a ZONE_POLYGON_BASE instance, taking the zone name and an array of @{DCS#Vec2}, forming a polygon. -- The @{Wrapper.Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected. @@ -1425,6 +1429,40 @@ function ZONE_POLYGON_BASE:New( ZoneName, PointsArray ) return self end +--- Update polygon points with an array of @{DCS#Vec2}. +-- @param #ZONE_POLYGON_BASE self +-- @param #ZONE_POLYGON_BASE.ListVec2 Vec2Array An array of @{DCS#Vec2}, forming a polygon. +-- @return #ZONE_POLYGON_BASE self +function ZONE_POLYGON_BASE:UpdateFromVec2(Vec2Array) + + self._.Polygon = {} + + for i=1,#Vec2Array do + self._.Polygon[i] = {} + self._.Polygon[i].x=Vec2Array[i].x + self._.Polygon[i].y=Vec2Array[i].y + end + + return self +end + +--- Update polygon points with an array of @{DCS#Vec3}. +-- @param #ZONE_POLYGON_BASE self +-- @param #ZONE_POLYGON_BASE.ListVec3 Vec2Array An array of @{DCS#Vec3}, forming a polygon. +-- @return #ZONE_POLYGON_BASE self +function ZONE_POLYGON_BASE:UpdateFromVec3(Vec3Array) + + self._.Polygon = {} + + for i=1,#Vec3Array do + self._.Polygon[i] = {} + self._.Polygon[i].x=Vec3Array[i].x + self._.Polygon[i].y=Vec3Array[i].z + end + + return self +end + --- Returns the center location of the polygon. -- @param #ZONE_GROUP self -- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location. diff --git a/Moose Development/Moose/DCS.lua b/Moose Development/Moose/DCS.lua index 206165bd3..15c73c29a 100644 --- a/Moose Development/Moose/DCS.lua +++ b/Moose Development/Moose/DCS.lua @@ -95,6 +95,11 @@ do -- world --- Returns a table of mark panels indexed numerically that are present within the mission. See [hoggit](https://wiki.hoggitworld.com/view/DCS_func_getMarkPanels) -- @function [parent=#world] getMarkPanels -- @return #table Table of marks. + + --- Returns a table of DCS airbase objects. + -- @function [parent=#world] getAirbases + -- @param #number coalitionId The coalition side number ID. Default is all airbases are returned. + -- @return #table Table of DCS airbase objects. end -- world @@ -360,7 +365,7 @@ do -- Types --- Time is given in seconds. -- @type Time - -- @extends #number + -- @extends #number Time in seconds. --- Model time is the time that drives the simulation. Model time may be stopped, accelerated and decelerated relative real time. -- @type ModelTime @@ -368,20 +373,20 @@ do -- Types --- Mission time is a model time plus time of the mission start. -- @type MissionTime - -- @extends #number + -- @extends #number Time in seconds. --- Distance is given in meters. -- @type Distance - -- @extends #number + -- @extends #number Distance in meters. --- Angle is given in radians. -- @type Angle - -- @extends #number + -- @extends #number Angle in radians. --- Azimuth is an angle of rotation around world axis y counter-clockwise. -- @type Azimuth - -- @extends #number + -- @extends #number Angle in radians. --- Mass is given in kilograms. -- @type Mass @@ -401,15 +406,15 @@ do -- Types --- Position is a composite structure. It consists of both coordinate vector and orientation matrix. Position3 (also known as "Pos3" for short) is a table that has following format: -- @type Position3 - -- @field #Vec3 p - -- @field #Vec3 x - -- @field #Vec3 y - -- @field #Vec3 z + -- @field #Vec3 p 3D position vector. + -- @field #Vec3 x Orientation component of vector pointing East. + -- @field #Vec3 y Orientation component of vector pointing up. + -- @field #Vec3 z Orientation component of vector pointing North. --- 3-dimensional box. -- @type Box3 - -- @field #Vec3 min - -- @field #Vec3 max + -- @field #Vec3 min Min. + -- @field #Vec3 max Max --- Each object belongs to a type. Object type is a named couple of properties those independent of mission and common for all units of the same type. Name of unit type is a string. Samples of unit type: "Su-27", "KAMAZ" and "M2 Bradley". -- @type TypeName @@ -514,7 +519,7 @@ do -- Object --- Returns object coordinates for current time. -- @function [parent=#Object] getPoint -- @param #Object self - -- @return #Vec3 + -- @return #Vec3 3D position vector with x,y,z components. --- Returns object position for current time. -- @function [parent=#Object] getPosition @@ -524,7 +529,7 @@ do -- Object --- Returns the unit's velocity vector. -- @function [parent=#Object] getVelocity -- @param #Object self - -- @return #Vec3 + -- @return #Vec3 3D velocity vector. --- Returns true if the unit is in air. -- @function [parent=#Object] inAir diff --git a/Moose Development/Moose/Ops/AirWing.lua b/Moose Development/Moose/Ops/AirWing.lua index 3169eb995..0acea986b 100644 --- a/Moose Development/Moose/Ops/AirWing.lua +++ b/Moose Development/Moose/Ops/AirWing.lua @@ -821,7 +821,7 @@ function AIRWING:onafterStatus(From, Event, To) -- Assets tot local Npq, Np, Nq=self:CountAssetsOnMission() - local assets=string.format("%d [Mission=%d (Active=%d, Queued=%d)]", self:CountAssets(), Npq, Np, Nq) + local assets=string.format("%d (OnMission: Total=%d, Active=%d, Queued=%d)", self:CountAssets(), Npq, Np, Nq) -- Output. local text=string.format("%s: Missions=%d, Payloads=%d (%d), Squads=%d, Assets=%s", fsmstate, Nmissions, Npayloads, #self.payloads, #self.squadrons, assets) @@ -836,7 +836,7 @@ function AIRWING:onafterStatus(From, Event, To) for i,_mission in pairs(self.missionqueue) do local mission=_mission --Ops.Auftrag#AUFTRAG - local prio=string.format("%d/%d", mission.prio, mission.importance) ; if mission.urgent then prio=prio.." (!)" end + local prio=string.format("%d/%s", mission.prio, tostring(mission.importance)) ; if mission.urgent then prio=prio.." (!)" end local assets=string.format("%d/%d", mission:CountOpsGroups(), mission.nassets) local target=string.format("%d/%d Damage=%.1f", mission:CountMissionTargets(), mission:GetTargetInitialNumber(), mission:GetTargetDamage()) @@ -1030,7 +1030,9 @@ function AIRWING:CheckRescuhelo() local N=self:CountMissionsInQueue({AUFTRAG.Type.RESCUEHELO}) - local carrier=UNIT:FindByName(self.airbase:GetName()) + local name=self.airbase:GetName() + + local carrier=UNIT:FindByName(name) for i=1,self.nflightsRescueHelo-N do @@ -1127,7 +1129,7 @@ function AIRWING:_GetNextMission() local vip=math.huge for _,_mission in pairs(self.missionqueue) do local mission=_mission --Ops.Auftrag#AUFTRAG - if mission.importance return") - --return - end - -- Get current time. local time=timer.getTime() -- Update marshal and pattern queue every 30 seconds. if time-self.Tqueue>self.dTqueue then - --collectgarbage() - -- Get time. local clock=UTILS.SecondsToClock(timer.getAbsTime()) local eta=UTILS.SecondsToClock(self:_GetETAatNextWP()) @@ -3414,7 +3412,7 @@ function AIRBOSS:onafterStatus(From, Event, To) local speed=self.carrier:GetVelocityKNOTS() -- Check water is ahead. - local collision=self:_CheckCollisionCoord(pos:Translate(self.collisiondist, hdg)) + local collision=false --self:_CheckCollisionCoord(pos:Translate(self.collisiondist, hdg)) local holdtime=0 if self.holdtimestamp then @@ -3470,15 +3468,9 @@ function AIRBOSS:onafterStatus(From, Event, To) -- Disable turn into the wind for this window so that we do not do this all over again. self.recoverywindow.WIND=false end - - else - - -- Find path around the obstacle. - if not self.detour then - --self:_Pathfinder() - end - + end + end @@ -10287,24 +10279,25 @@ function AIRBOSS:_GetSternCoord() local FB=self:GetFinalBearing() -- Stern coordinate (sterndist<0). Also translate 10 meters starboard wrt Final bearing. - local stern=self:GetCoordinate() + self.sterncoord:UpdateFromCoordinate(self:GetCoordinate()) + --local stern=self:GetCoordinate() -- Stern coordinate (sterndist<0). if self.carriertype==AIRBOSS.CarrierType.TARAWA then -- Tarawa: Translate 8 meters port. - stern=stern:Translate(self.carrierparam.sterndist, hdg):Translate(8, FB-90) + self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8, FB-90, true, true) elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then -- Stennis: translate 7 meters starboard wrt Final bearing. - stern=stern:Translate(self.carrierparam.sterndist, hdg):Translate(7, FB+90) + self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(7, FB+90, true, true) else -- Nimitz SC: translate 8 meters starboard wrt Final bearing. - stern=stern:Translate(self.carrierparam.sterndist, hdg):Translate(8.5, FB+90) + self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8.5, FB+90, true, true) end -- Set altitude. - stern:SetAltitude(self.carrierparam.deckheight) + self.sterncoord:SetAltitude(self.carrierparam.deckheight) - return stern + return self.sterncoord end --- Get wire from landing position. @@ -11339,9 +11332,12 @@ end -- @param #AIRBOSS self -- @return Core.Point#COORDINATE Optimal landing coordinate. function AIRBOSS:_GetOptLandingCoordinate() + + -- Start with stern coordiante. + self.landingcoord:UpdateFromCoordinate(self:_GetSternCoord()) -- Stern coordinate. - local stern=self:_GetSternCoord() + --local stern=self:_GetSternCoord() -- Final bearing. local FB=self:GetFinalBearing(false) @@ -11349,10 +11345,11 @@ function AIRBOSS:_GetOptLandingCoordinate() if self.carriertype==AIRBOSS.CarrierType.TARAWA then -- Landing 100 ft abeam, 120 ft alt. - stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90) + self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true) + --stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90) -- Alitude 120 ft. - stern:SetAltitude(UTILS.FeetToMeters(120)) + self.landingcoord:SetAltitude(UTILS.FeetToMeters(120)) else @@ -11360,15 +11357,15 @@ function AIRBOSS:_GetOptLandingCoordinate() if self.carrierparam.wire3 then -- We take the position of the 3rd wire to approximately account for the length of the aircraft. local w3=self.carrierparam.wire3 - stern=stern:Translate(w3, FB, true) + self.landingcoord:Translate(w3, FB, true, true) end -- Add 2 meters to account for aircraft height. - stern.y=stern.y+2 + self.landingcoord.y=self.landingcoord.y+2 end - return stern + return self.landingcoord end --- Get landing spot on Tarawa. @@ -11376,8 +11373,10 @@ end -- @return Core.Point#COORDINATE Primary landing spot coordinate. function AIRBOSS:_GetLandingSpotCoordinate() + self.landingspotcoord:UpdateFromCoordinate(self:_GetSternCoord()) + -- Stern coordinate. - local stern=self:_GetSternCoord() + --local stern=self:_GetSternCoord() if self.carriertype==AIRBOSS.CarrierType.TARAWA then @@ -11385,11 +11384,11 @@ function AIRBOSS:_GetLandingSpotCoordinate() local hdg=self:GetHeading() -- Primary landing spot 7.5 - stern=stern:Translate(57, hdg):SetAltitude(self.carrierparam.deckheight) + self.landingspotcoord:Translate(57, hdg, true, true):SetAltitude(self.carrierparam.deckheight) end - return stern + return self.landingspotcoord end --- Get true (or magnetic) heading of carrier. @@ -14333,7 +14332,7 @@ end -- @param #AIRBOSS self -- @return Core.Point#COORDINATE Carrier coordinate. function AIRBOSS:GetCoordinate() - return self.carrier:GetCoordinate() + return self.carrier:GetCoord() end diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 16edd0aef..ce6fda25c 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -1096,7 +1096,9 @@ function AUFTRAG:NewRESCUEHELO(Carrier) local mission=AUFTRAG:New(AUFTRAG.Type.RESCUEHELO) - self.carrier=Carrier + --mission.carrier=Carrier + + mission:_TargetFromObject(Carrier) -- Mission options: mission.missionTask=ENUMS.MissionTask.NOTHING @@ -1412,12 +1414,12 @@ end -- @param #AUFTRAG self -- @param #number Prio Priority 1=high, 100=low. Default 50. -- @param #boolean Urgent If *true*, another running mission might be cancelled if it has a lower priority. --- @param #number Importance Number 1-10. If missions with lower value are in the queue, these have to be finished first. Default is 5. +-- @param #number Importance Number 1-10. If missions with lower value are in the queue, these have to be finished first. Default is `nil`. -- @return #AUFTRAG self function AUFTRAG:SetPriority(Prio, Urgent, Importance) self.prio=Prio or 50 self.urgent=Urgent - self.importance=Importance or 5 + self.importance=Importance return self end @@ -1665,6 +1667,47 @@ function AUFTRAG:SetICLS(Channel, Morse, UnitName) return self end +--- Get mission type. +-- @param #AUFTRAG self +-- @return #string Mission type, e.g. "BAI". +function AUFTRAG:GetType() + return self.type +end + +--- Get mission name. +-- @param #AUFTRAG self +-- @return #string Mission name, e.g. "Auftrag Nr.1". +function AUFTRAG:GetName() + return self.name +end + +--- Get number of required assets. +-- @param #AUFTRAG self +-- @return #number Numer of required assets. +function AUFTRAG:GetNumberOfRequiredAssets() + return self.nassets +end + +--- Get mission priority. +-- @param #AUFTRAG self +-- @return #number Priority. Smaller is higher. +function AUFTRAG:GetPriority() + return self.prio +end + +--- Check if mission is "urgent". +-- @param #AUFTRAG self +-- @return #boolean If `true`, mission is "urgent". +function AUFTRAG:IsUrgent() + return self.urgent +end + +--- Get mission importance. +-- @param #AUFTRAG self +-- @return #number Importance. Smaller is higher. +function AUFTRAG:GetImportance() + return self.importance +end --- Add start condition. -- @param #AUFTRAG self @@ -2599,7 +2642,7 @@ function AUFTRAG:onafterSuccess(From, Event, To) self.status=AUFTRAG.Status.SUCCESS self:T(self.lid..string.format("New mission status=%s", self.status)) - local repeatme=self.repeatedFailure