mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Merge remote-tracking branch 'refs/remotes/origin/master' into MissileTrainer
This commit is contained in:
commit
5990650529
@ -5,12 +5,13 @@ echo env.info( 'Moose Embedded' ) > Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Routines.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Base.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Event.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Menu.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Group.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Unit.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Zone.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Database.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Moose.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\TimeTrigger.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Scheduler.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Scoring.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Cargo.lua Moose_Embedded.lua
|
||||
copy /b Moose_Embedded.lua + ..\Moose\Client.lua Moose_Embedded.lua
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -353,6 +353,7 @@ end
|
||||
-- @param #number Level
|
||||
function BASE:TraceLevel( Level )
|
||||
_TraceLevel = Level
|
||||
self:E( "Tracing level " .. Level )
|
||||
end
|
||||
|
||||
--- Set tracing for a class
|
||||
@ -361,6 +362,7 @@ end
|
||||
function BASE:TraceClass( Class )
|
||||
_TraceClass[Class] = true
|
||||
_TraceClassMethod[Class] = {}
|
||||
self:E( "Tracing class " .. Class )
|
||||
end
|
||||
|
||||
--- Set tracing for a specific method of class
|
||||
@ -373,6 +375,7 @@ function BASE:TraceClassMethod( Class, Method )
|
||||
_TraceClassMethod[Class].Method = {}
|
||||
end
|
||||
_TraceClassMethod[Class].Method[Method] = true
|
||||
self:E( "Tracing method " .. Method .. " of class " .. Class )
|
||||
end
|
||||
|
||||
--- Trace a function call. Must be at the beginning of the function logic.
|
||||
|
||||
245
Moose/Cargo.lua
245
Moose/Cargo.lua
@ -31,18 +31,31 @@ CARGO_ZONE = {
|
||||
}
|
||||
}
|
||||
|
||||
function CARGO_ZONE:New( CargoZoneName, CargoHostName ) local self = BASE:Inherit( self, BASE:New() )
|
||||
--- Creates a new zone where cargo can be collected or deployed.
|
||||
-- The zone functionality is useful to smoke or indicate routes for cargo pickups or deployments.
|
||||
-- Provide the zone name as declared in the mission file into the CargoZoneName in the :New method.
|
||||
-- An optional parameter is the CargoHostName, which is a Group declared with Late Activation switched on in the mission file.
|
||||
-- The CargoHostName is the "host" of the cargo zone:
|
||||
--
|
||||
-- * It will smoke the zone position when a client is approaching the zone.
|
||||
-- * Depending on the cargo type, it will assist in the delivery of the cargo by driving to and from the client.
|
||||
--
|
||||
-- @param #CARGO_ZONE self
|
||||
-- @param #string CargoZoneName The name of the zone as declared within the mission editor.
|
||||
-- @param #string CargoHostName The name of the Group "hosting" the zone. The Group MUST NOT be a static, and must be a "mobile" unit.
|
||||
function CARGO_ZONE:New( CargoZoneName, CargoHostName ) local self = BASE:Inherit( self, ZONE:New( CargoZoneName ) )
|
||||
self:F( { CargoZoneName, CargoHostName } )
|
||||
|
||||
self.CargoZoneName = CargoZoneName
|
||||
self.CargoZone = trigger.misc.getZone( CargoZoneName )
|
||||
self.SignalHeight = 2
|
||||
--self.CargoZone = trigger.misc.getZone( CargoZoneName )
|
||||
|
||||
|
||||
if CargoHostName then
|
||||
self.CargoHostName = CargoHostName
|
||||
end
|
||||
|
||||
self:T( self.CargoZone )
|
||||
self:T( self.CargoZoneName )
|
||||
|
||||
return self
|
||||
end
|
||||
@ -50,17 +63,19 @@ end
|
||||
function CARGO_ZONE:Spawn()
|
||||
self:F( self.CargoHostName )
|
||||
|
||||
if self.CargoHostSpawn then
|
||||
local CargoHostGroup = self.CargoHostSpawn:GetGroupFromIndex()
|
||||
if CargoHostGroup and CargoHostGroup:IsAlive() then
|
||||
else
|
||||
self.CargoHostSpawn:ReSpawn( 1 )
|
||||
end
|
||||
else
|
||||
self:T( "Initialize CargoHostSpawn" )
|
||||
self.CargoHostSpawn = SPAWN:New( self.CargoHostName ):Limit( 1, 1 )
|
||||
self.CargoHostSpawn:ReSpawn( 1 )
|
||||
end
|
||||
if self.CargoHostName then -- Only spawn a host in the zone when there is one given as a parameter in the New function.
|
||||
if self.CargoHostSpawn then
|
||||
local CargoHostGroup = self.CargoHostSpawn:GetGroupFromIndex()
|
||||
if CargoHostGroup and CargoHostGroup:IsAlive() then
|
||||
else
|
||||
self.CargoHostSpawn:ReSpawn( 1 )
|
||||
end
|
||||
else
|
||||
self:T( "Initialize CargoHostSpawn" )
|
||||
self.CargoHostSpawn = SPAWN:New( self.CargoHostName ):Limit( 1, 1 )
|
||||
self.CargoHostSpawn:ReSpawn( 1 )
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
@ -114,6 +129,7 @@ function CARGO_ZONE:ReportCargosToClient( Client, CargoType )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function CARGO_ZONE:Signal()
|
||||
self:F()
|
||||
|
||||
@ -148,16 +164,15 @@ function CARGO_ZONE:Signal()
|
||||
|
||||
else
|
||||
|
||||
local CurrentPosition = { x = self.CargoZone.point.x, y = self.CargoZone.point.z }
|
||||
self.CargoZone.point.y = land.getHeight( CurrentPosition ) + 2
|
||||
local ZonePointVec3 = self:GetPointVec3( self.SignalHeight ) -- Get the zone position + the landheight + 2 meters
|
||||
|
||||
if self.SignalType.ID == CARGO_ZONE.SIGNAL.TYPE.SMOKE.ID then
|
||||
|
||||
trigger.action.smoke( self.CargoZone.point, self.SignalColor.TRIGGERCOLOR )
|
||||
trigger.action.smoke( ZonePointVec3, self.SignalColor.TRIGGERCOLOR )
|
||||
Signalled = true
|
||||
|
||||
elseif self.SignalType.ID == CARGO_ZONE.SIGNAL.TYPE.FLARE.ID then
|
||||
trigger.action.signalFlare( self.CargoZone.point, self.SignalColor.TRIGGERCOLOR, 0 )
|
||||
trigger.action.signalFlare( ZonePointVec3, self.SignalColor.TRIGGERCOLOR, 0 )
|
||||
Signalled = false
|
||||
|
||||
end
|
||||
@ -168,85 +183,121 @@ function CARGO_ZONE:Signal()
|
||||
|
||||
end
|
||||
|
||||
function CARGO_ZONE:WhiteSmoke()
|
||||
function CARGO_ZONE:WhiteSmoke( SignalHeight )
|
||||
self:F()
|
||||
|
||||
self.SignalType = CARGO_ZONE.SIGNAL.TYPE.SMOKE
|
||||
self.SignalColor = CARGO_ZONE.SIGNAL.COLOR.WHITE
|
||||
|
||||
if SignalHeight then
|
||||
self.SignalHeight = SignalHeight
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function CARGO_ZONE:BlueSmoke()
|
||||
function CARGO_ZONE:BlueSmoke( SignalHeight )
|
||||
self:F()
|
||||
|
||||
self.SignalType = CARGO_ZONE.SIGNAL.TYPE.SMOKE
|
||||
self.SignalColor = CARGO_ZONE.SIGNAL.COLOR.BLUE
|
||||
|
||||
if SignalHeight then
|
||||
self.SignalHeight = SignalHeight
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function CARGO_ZONE:RedSmoke()
|
||||
function CARGO_ZONE:RedSmoke( SignalHeight )
|
||||
self:F()
|
||||
|
||||
self.SignalType = CARGO_ZONE.SIGNAL.TYPE.SMOKE
|
||||
self.SignalColor = CARGO_ZONE.SIGNAL.COLOR.RED
|
||||
|
||||
if SignalHeight then
|
||||
self.SignalHeight = SignalHeight
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function CARGO_ZONE:OrangeSmoke()
|
||||
function CARGO_ZONE:OrangeSmoke( SignalHeight )
|
||||
self:F()
|
||||
|
||||
self.SignalType = CARGO_ZONE.SIGNAL.TYPE.SMOKE
|
||||
self.SignalColor = CARGO_ZONE.SIGNAL.COLOR.ORANGE
|
||||
|
||||
if SignalHeight then
|
||||
self.SignalHeight = SignalHeight
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function CARGO_ZONE:GreenSmoke()
|
||||
function CARGO_ZONE:GreenSmoke( SignalHeight )
|
||||
self:F()
|
||||
|
||||
self.SignalType = CARGO_ZONE.SIGNAL.TYPE.SMOKE
|
||||
self.SignalColor = CARGO_ZONE.SIGNAL.COLOR.GREEN
|
||||
|
||||
if SignalHeight then
|
||||
self.SignalHeight = SignalHeight
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function CARGO_ZONE:WhiteFlare()
|
||||
function CARGO_ZONE:WhiteFlare( SignalHeight )
|
||||
self:F()
|
||||
|
||||
self.SignalType = CARGO_ZONE.SIGNAL.TYPE.FLARE
|
||||
self.SignalColor = CARGO_ZONE.SIGNAL.COLOR.WHITE
|
||||
|
||||
if SignalHeight then
|
||||
self.SignalHeight = SignalHeight
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function CARGO_ZONE:RedFlare()
|
||||
function CARGO_ZONE:RedFlare( SignalHeight )
|
||||
self:F()
|
||||
|
||||
self.SignalType = CARGO_ZONE.SIGNAL.TYPE.FLARE
|
||||
self.SignalColor = CARGO_ZONE.SIGNAL.COLOR.RED
|
||||
|
||||
if SignalHeight then
|
||||
self.SignalHeight = SignalHeight
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function CARGO_ZONE:GreenFlare()
|
||||
function CARGO_ZONE:GreenFlare( SignalHeight )
|
||||
self:F()
|
||||
|
||||
self.SignalType = CARGO_ZONE.SIGNAL.TYPE.FLARE
|
||||
self.SignalColor = CARGO_ZONE.SIGNAL.COLOR.GREEN
|
||||
|
||||
if SignalHeight then
|
||||
self.SignalHeight = SignalHeight
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function CARGO_ZONE:YellowFlare()
|
||||
function CARGO_ZONE:YellowFlare( SignalHeight )
|
||||
self:F()
|
||||
|
||||
self.SignalType = CARGO_ZONE.SIGNAL.TYPE.FLARE
|
||||
self.SignalColor = CARGO_ZONE.SIGNAL.COLOR.YELLOW
|
||||
|
||||
if SignalHeight then
|
||||
self.SignalHeight = SignalHeight
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -517,6 +568,7 @@ function CARGO_GROUP:Spawn( Client )
|
||||
self.CargoGroupName = self.CargoSpawn:SpawnFromUnit( self.CargoZone:GetCargoHostUnit(), 60, 30, 1 ):GetName()
|
||||
else
|
||||
--- ReSpawn the Cargo in the CargoZone without a host ...
|
||||
self:T( self.CargoZone )
|
||||
self.CargoGroupName = self.CargoSpawn:SpawnInZone( self.CargoZone, true, 1 ):GetName()
|
||||
end
|
||||
self:StatusNone()
|
||||
@ -557,64 +609,72 @@ function CARGO_GROUP:OnBoard( Client, LandingZone, OnBoardSide )
|
||||
|
||||
local CargoGroup = Group.getByName( self.CargoGroupName )
|
||||
|
||||
local CargoUnits = CargoGroup:getUnits()
|
||||
local CargoPos = CargoUnits[1]:getPoint()
|
||||
local CargoUnit = CargoGroup:getUnit(1)
|
||||
local CargoPos = CargoUnit:getPoint()
|
||||
|
||||
self.CargoInAir = CargoUnit:inAir()
|
||||
|
||||
self:T( self.CargoInAir )
|
||||
|
||||
-- Only move the group to the carrier when the cargo is not in the air
|
||||
-- (eg. cargo can be on a oil derrick, moving the cargo on the oil derrick will drop the cargo on the sea).
|
||||
if not self.CargoInAir then
|
||||
|
||||
local Points = {}
|
||||
|
||||
self:T( 'CargoPos x = ' .. CargoPos.x .. " z = " .. CargoPos.z )
|
||||
self:T( 'CarrierPosMove x = ' .. CarrierPosMove.x .. " z = " .. CarrierPosMove.z )
|
||||
|
||||
Points[#Points+1] = routines.ground.buildWP( CargoPos, "Cone", 10 )
|
||||
|
||||
self:T( 'Points[1] x = ' .. Points[1].x .. " y = " .. Points[1].y )
|
||||
|
||||
if OnBoardSide == nil then
|
||||
OnBoardSide = CLIENT.ONBOARDSIDE.NONE
|
||||
end
|
||||
|
||||
if OnBoardSide == CLIENT.ONBOARDSIDE.LEFT then
|
||||
|
||||
self:T( "TransportCargoOnBoard: Onboarding LEFT" )
|
||||
CarrierPosMove.z = CarrierPosMove.z - 25
|
||||
CarrierPosOnBoard.z = CarrierPosOnBoard.z - 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 )
|
||||
|
||||
elseif OnBoardSide == CLIENT.ONBOARDSIDE.RIGHT then
|
||||
|
||||
self:T( "TransportCargoOnBoard: Onboarding RIGHT" )
|
||||
CarrierPosMove.z = CarrierPosMove.z + 25
|
||||
CarrierPosOnBoard.z = CarrierPosOnBoard.z + 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 )
|
||||
|
||||
elseif OnBoardSide == CLIENT.ONBOARDSIDE.BACK then
|
||||
|
||||
self:T( "TransportCargoOnBoard: Onboarding BACK" )
|
||||
CarrierPosMove.x = CarrierPosMove.x - 25
|
||||
CarrierPosOnBoard.x = CarrierPosOnBoard.x - 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 )
|
||||
|
||||
elseif OnBoardSide == CLIENT.ONBOARDSIDE.FRONT then
|
||||
|
||||
self:T( "TransportCargoOnBoard: Onboarding FRONT" )
|
||||
CarrierPosMove.x = CarrierPosMove.x + 25
|
||||
CarrierPosOnBoard.x = CarrierPosOnBoard.x + 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 )
|
||||
|
||||
elseif OnBoardSide == CLIENT.ONBOARDSIDE.NONE then
|
||||
|
||||
self:T( "TransportCargoOnBoard: Onboarding CENTRAL" )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPos, "Cone", 10 )
|
||||
|
||||
end
|
||||
self:T( "TransportCargoOnBoard: Routing " .. self.CargoGroupName )
|
||||
|
||||
routines.scheduleFunction( routines.goRoute, { self.CargoGroupName, Points}, timer.getTime() + 4 )
|
||||
local Points = {}
|
||||
|
||||
self:T( 'CargoPos x = ' .. CargoPos.x .. " z = " .. CargoPos.z )
|
||||
self:T( 'CarrierPosMove x = ' .. CarrierPosMove.x .. " z = " .. CarrierPosMove.z )
|
||||
|
||||
Points[#Points+1] = routines.ground.buildWP( CargoPos, "Cone", 10 )
|
||||
|
||||
self:T( 'Points[1] x = ' .. Points[1].x .. " y = " .. Points[1].y )
|
||||
|
||||
if OnBoardSide == nil then
|
||||
OnBoardSide = CLIENT.ONBOARDSIDE.NONE
|
||||
end
|
||||
|
||||
if OnBoardSide == CLIENT.ONBOARDSIDE.LEFT then
|
||||
|
||||
self:T( "TransportCargoOnBoard: Onboarding LEFT" )
|
||||
CarrierPosMove.z = CarrierPosMove.z - 25
|
||||
CarrierPosOnBoard.z = CarrierPosOnBoard.z - 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 )
|
||||
|
||||
elseif OnBoardSide == CLIENT.ONBOARDSIDE.RIGHT then
|
||||
|
||||
self:T( "TransportCargoOnBoard: Onboarding RIGHT" )
|
||||
CarrierPosMove.z = CarrierPosMove.z + 25
|
||||
CarrierPosOnBoard.z = CarrierPosOnBoard.z + 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 )
|
||||
|
||||
elseif OnBoardSide == CLIENT.ONBOARDSIDE.BACK then
|
||||
|
||||
self:T( "TransportCargoOnBoard: Onboarding BACK" )
|
||||
CarrierPosMove.x = CarrierPosMove.x - 25
|
||||
CarrierPosOnBoard.x = CarrierPosOnBoard.x - 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 )
|
||||
|
||||
elseif OnBoardSide == CLIENT.ONBOARDSIDE.FRONT then
|
||||
|
||||
self:T( "TransportCargoOnBoard: Onboarding FRONT" )
|
||||
CarrierPosMove.x = CarrierPosMove.x + 25
|
||||
CarrierPosOnBoard.x = CarrierPosOnBoard.x + 5
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 )
|
||||
|
||||
elseif OnBoardSide == CLIENT.ONBOARDSIDE.NONE then
|
||||
|
||||
self:T( "TransportCargoOnBoard: Onboarding CENTRAL" )
|
||||
Points[#Points+1] = routines.ground.buildWP( CarrierPos, "Cone", 10 )
|
||||
|
||||
end
|
||||
self:T( "TransportCargoOnBoard: Routing " .. self.CargoGroupName )
|
||||
|
||||
routines.scheduleFunction( routines.goRoute, { self.CargoGroupName, Points}, timer.getTime() + 4 )
|
||||
end
|
||||
|
||||
self:StatusLoading( Client )
|
||||
|
||||
@ -628,12 +688,19 @@ function CARGO_GROUP:OnBoarded( Client, LandingZone )
|
||||
|
||||
local OnBoarded = false
|
||||
|
||||
local CargoGroup = Group.getByName( self.CargoGroupName )
|
||||
if routines.IsPartOfGroupInRadius( CargoGroup, Client:ClientPosition(), 25 ) then
|
||||
CargoGroup:destroy()
|
||||
self:StatusLoaded( Client )
|
||||
OnBoarded = true
|
||||
end
|
||||
local CargoGroup = Group.getByName( self.CargoGroupName )
|
||||
|
||||
if not self.CargoInAir then
|
||||
if routines.IsPartOfGroupInRadius( CargoGroup, Client:ClientPosition(), 25 ) then
|
||||
CargoGroup:destroy()
|
||||
self:StatusLoaded( Client )
|
||||
OnBoarded = true
|
||||
end
|
||||
else
|
||||
CargoGroup:destroy()
|
||||
self:StatusLoaded( Client )
|
||||
OnBoarded = true
|
||||
end
|
||||
|
||||
return OnBoarded
|
||||
end
|
||||
|
||||
@ -282,6 +282,9 @@ end
|
||||
-- This method expects EXACTLY the same structure as a structure within the ME, and needs 2 additional fields defined:
|
||||
-- SpawnCountryID, SpawnCategoryID
|
||||
-- This method is used by the SPAWN class.
|
||||
-- @param #DATABASE self
|
||||
-- @param #table SpawnTemplate
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:Spawn( SpawnTemplate )
|
||||
self:F( SpawnTemplate.name )
|
||||
|
||||
@ -330,7 +333,10 @@ function DATABASE:GetStatusGroup( GroupName )
|
||||
end
|
||||
end
|
||||
|
||||
--- Registers new Group Templates within the DATABASE Object.
|
||||
--- Private method that registers new Group Templates within the DATABASE Object.
|
||||
-- @param #DATABASE self
|
||||
-- @param #table GroupTemplate
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:_RegisterGroup( GroupTemplate )
|
||||
|
||||
local GroupTemplateName = env.getValueDictByKey(GroupTemplate.name)
|
||||
@ -339,6 +345,12 @@ function DATABASE:_RegisterGroup( GroupTemplate )
|
||||
self.Groups[GroupTemplateName] = {}
|
||||
self.Groups[GroupTemplateName].Status = nil
|
||||
end
|
||||
|
||||
-- Delete the spans from the route, it is not needed and takes memory.
|
||||
if GroupTemplate.route and GroupTemplate.route.spans then
|
||||
GroupTemplate.route.spans = nil
|
||||
end
|
||||
|
||||
self.Groups[GroupTemplateName].GroupName = GroupTemplateName
|
||||
self.Groups[GroupTemplateName].Template = GroupTemplate
|
||||
self.Groups[GroupTemplateName].groupId = GroupTemplate.groupId
|
||||
|
||||
@ -92,6 +92,18 @@ function GROUP:NewFromDCSUnit( DCSUnit )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns the name of the Group.
|
||||
-- @param #GROUP self
|
||||
-- @return #string GroupName
|
||||
function GROUP:GetName()
|
||||
|
||||
local GroupName = self.DCSGroup:getName()
|
||||
|
||||
return GroupName
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Retrieve the group mission and allow to place function hooks within the mission waypoint plan.
|
||||
-- Use the method @{Group#GROUP:WayPointFunction} to define the hook functions for specific waypoints.
|
||||
-- Use the method @{Group@GROUP:WayPointExecute) to start the execution of the new mission plan.
|
||||
@ -128,7 +140,12 @@ function GROUP:TaskFunction( WayPoint, WayPointIndex, FunctionString, FunctionAr
|
||||
|
||||
local DCSScript = {}
|
||||
DCSScript[#DCSScript+1] = "local MissionGroup = GROUP.FindGroup( ... ) "
|
||||
DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup, " .. table.concat( FunctionArguments, "," ) .. ")"
|
||||
|
||||
if FunctionArguments.n > 0 then
|
||||
DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup, " .. table.concat( FunctionArguments, "," ) .. ")"
|
||||
else
|
||||
DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup )"
|
||||
end
|
||||
|
||||
DCSTask = self:TaskWrappedAction(
|
||||
self:CommandDoScript(
|
||||
@ -594,6 +611,41 @@ function GROUP:TaskWrappedAction( DCSCommand, Index )
|
||||
return DCSTaskWrappedAction
|
||||
end
|
||||
|
||||
--- Executes a command action
|
||||
-- @param #GROUP self
|
||||
-- @param DCSCommand#Command DCSCommand
|
||||
-- @return #GROUP self
|
||||
function GROUP:SetCommand( DCSCommand )
|
||||
self:F( DCSCommand )
|
||||
|
||||
local Controller = self:_GetController()
|
||||
|
||||
Controller:setCommand( DCSCommand )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Perform a switch waypoint command
|
||||
-- @param #GROUP self
|
||||
-- @param #number FromWayPoint
|
||||
-- @param #number ToWayPoint
|
||||
-- @return DCSTask#Task
|
||||
function GROUP:CommandSwitchWayPoint( FromWayPoint, ToWayPoint, Index )
|
||||
self:F( { FromWayPoint, ToWayPoint, Index } )
|
||||
|
||||
local CommandSwitchWayPoint = {
|
||||
id = 'SwitchWaypoint',
|
||||
params = {
|
||||
fromWaypointIndex = FromWayPoint,
|
||||
goToWaypointIndex = ToWayPoint,
|
||||
},
|
||||
}
|
||||
|
||||
self:T( { CommandSwitchWayPoint } )
|
||||
return CommandSwitchWayPoint
|
||||
end
|
||||
|
||||
|
||||
--- Orbit at a specified position at a specified alititude during a specified duration with a specified speed.
|
||||
-- @param #GROUP self
|
||||
-- @param #Vec2 Point The point to hold the position.
|
||||
@ -601,7 +653,7 @@ end
|
||||
-- @param #number Speed The speed flying when holding the position.
|
||||
-- @return #GROUP self
|
||||
function GROUP:TaskOrbitCircleAtVec2( Point, Altitude, Speed )
|
||||
self:F( { self.GroupName, Point, Altitude, Speed } )
|
||||
self:F( { self.GroupName, Point, Altitude, Speed } )
|
||||
|
||||
-- pattern = enum AI.Task.OribtPattern,
|
||||
-- point = Vec2,
|
||||
@ -732,8 +784,41 @@ function GROUP:TaskAttackUnit( AttackUnit )
|
||||
params = { unitId = AttackUnit:GetID(),
|
||||
expend = AI.Task.WeaponExpend.TWO,
|
||||
groupAttack = true,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
self:T( { DCSTask } )
|
||||
return DCSTask
|
||||
end
|
||||
|
||||
--- Attack a Group.
|
||||
-- @param #GROUP self
|
||||
-- @param Group#GROUP AttackGroup The Group to be attacked.
|
||||
-- @return DCSTask#Task The DCS task structure.
|
||||
function GROUP:TaskAttackGroup( AttackGroup )
|
||||
self:F( { self.GroupName, AttackGroup } )
|
||||
|
||||
-- AttackGroup = {
|
||||
-- id = 'AttackGroup',
|
||||
-- params = {
|
||||
-- groupId = Group.ID,
|
||||
-- weaponType = number,
|
||||
-- expend = enum AI.Task.WeaponExpend,
|
||||
-- attackQty = number,
|
||||
-- directionEnabled = boolean,
|
||||
-- direction = Azimuth,
|
||||
-- altitudeEnabled = boolean,
|
||||
-- altitude = Distance,
|
||||
-- attackQtyLimit = boolean,
|
||||
-- }
|
||||
-- }
|
||||
|
||||
local DCSTask
|
||||
DCSTask = { id = 'AttackGroup',
|
||||
params = { groupId = AttackGroup:GetID(),
|
||||
expend = AI.Task.WeaponExpend.TWO,
|
||||
},
|
||||
},
|
||||
|
||||
self:T( { DCSTask } )
|
||||
return DCSTask
|
||||
|
||||
124
Moose/Menu.lua
124
Moose/Menu.lua
@ -245,3 +245,127 @@ function MENU_CLIENT_COMMAND:Remove()
|
||||
self.ParentMenu.Menus[self.MenuPath] = nil
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- The MENU_COALITION class
|
||||
-- @type MENU_COALITION
|
||||
-- @extends Menu#MENU
|
||||
MENU_COALITION = {
|
||||
ClassName = "MENU_COALITION"
|
||||
}
|
||||
|
||||
--- Creates a new coalition menu item
|
||||
-- @param #MENU_COALITION self
|
||||
-- @param DCSCoalition#coalition.side MenuCoalition The coalition owning the menu.
|
||||
-- @param #string MenuText The text for the menu.
|
||||
-- @param #table ParentMenu The parent menu.
|
||||
-- @return #MENU_COALITION self
|
||||
function MENU_COALITION:New( MenuCoalition, MenuText, ParentMenu )
|
||||
|
||||
-- Arrange meta tables
|
||||
local MenuParentPath = {}
|
||||
if ParentMenu ~= nil then
|
||||
MenuParentPath = ParentMenu.MenuPath
|
||||
end
|
||||
|
||||
local self = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) )
|
||||
self:F( { MenuCoalition, MenuText, ParentMenu } )
|
||||
|
||||
self.MenuCoalition = MenuCoalition
|
||||
self.MenuParentPath = MenuParentPath
|
||||
self.MenuText = MenuText
|
||||
self.ParentMenu = ParentMenu
|
||||
|
||||
self.Menus = {}
|
||||
|
||||
self:T( { MenuParentPath, MenuText } )
|
||||
|
||||
self.MenuPath = missionCommands.addSubMenuForCoalition( self.MenuCoalition, MenuText, MenuParentPath )
|
||||
|
||||
self:T( { self.MenuPath } )
|
||||
|
||||
if ParentMenu and ParentMenu.Menus then
|
||||
ParentMenu.Menus[self.MenuPath] = self
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes the sub menus recursively of this MENU_COALITION.
|
||||
-- @param #MENU_COALITION self
|
||||
-- @return #MENU_COALITION self
|
||||
function MENU_COALITION:RemoveSubMenus()
|
||||
self:F( self.MenuPath )
|
||||
|
||||
for MenuID, Menu in pairs( self.Menus ) do
|
||||
Menu:Remove()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Removes the sub menus recursively of this MENU_COALITION.
|
||||
-- @param #MENU_COALITION self
|
||||
-- @return #MENU_COALITION self
|
||||
function MENU_COALITION:Remove()
|
||||
self:F( self.MenuPath )
|
||||
|
||||
self:RemoveSubMenus()
|
||||
missionCommands.removeItemForCoalition( self.MenuCoalition, self.MenuPath )
|
||||
self.ParentMenu.Menus[self.MenuPath] = nil
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- The MENU_COALITION_COMMAND class
|
||||
-- @type MENU_COALITION_COMMAND
|
||||
-- @extends Menu#MENU
|
||||
MENU_COALITION_COMMAND = {
|
||||
ClassName = "MENU_COALITION_COMMAND"
|
||||
}
|
||||
|
||||
--- Creates a new radio command item for a group
|
||||
-- @param #MENU_COALITION_COMMAND self
|
||||
-- @param DCSCoalition#coalition.side MenuCoalition The coalition owning the menu.
|
||||
-- @param MenuText The text for the menu.
|
||||
-- @param ParentMenu The parent menu.
|
||||
-- @param CommandMenuFunction A function that is called when the menu key is pressed.
|
||||
-- @param CommandMenuArgument An argument for the function.
|
||||
-- @return #MENU_COALITION_COMMAND self
|
||||
function MENU_COALITION_COMMAND:New( MenuCoalition, MenuText, ParentMenu, CommandMenuFunction, CommandMenuArgument )
|
||||
|
||||
-- Arrange meta tables
|
||||
|
||||
local MenuParentPath = {}
|
||||
if ParentMenu ~= nil then
|
||||
MenuParentPath = ParentMenu.MenuPath
|
||||
end
|
||||
|
||||
local self = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) )
|
||||
|
||||
self.MenuCoalition = MenuCoalition
|
||||
self.MenuParentPath = MenuParentPath
|
||||
self.MenuText = MenuText
|
||||
self.ParentMenu = ParentMenu
|
||||
|
||||
self:T( { MenuParentPath, MenuText, CommandMenuFunction, CommandMenuArgument } )
|
||||
|
||||
self.MenuPath = missionCommands.addCommandForCoalition( self.MenuCoalition, MenuText, MenuParentPath, CommandMenuFunction, CommandMenuArgument )
|
||||
|
||||
self.CommandMenuFunction = CommandMenuFunction
|
||||
self.CommandMenuArgument = CommandMenuArgument
|
||||
|
||||
ParentMenu.Menus[self.MenuPath] = self
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes a radio command item for a coalition
|
||||
-- @param #MENU_COALITION_COMMAND self
|
||||
-- @return #MENU_COALITION_COMMAND self
|
||||
function MENU_COALITION_COMMAND:Remove()
|
||||
self:F( self.MenuPath )
|
||||
|
||||
missionCommands.removeItemForCoalition( self.MenuCoalition, self.MenuPath )
|
||||
self.ParentMenu.Menus[self.MenuPath] = nil
|
||||
return nil
|
||||
end
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
-- @author FlightControl
|
||||
|
||||
Include.File( "Client" )
|
||||
Include.File( "TimeTrigger" )
|
||||
Include.File( "Scheduler" )
|
||||
|
||||
--- The MISSILETRAINER class
|
||||
-- @type MISSILETRAINER
|
||||
@ -13,7 +13,7 @@ MISSILETRAINER = {
|
||||
}
|
||||
|
||||
--- Creates the main object which is handling missile tracking.
|
||||
-- When a missile is fired a TIMETRIGGER is set off that follows the missile. When near a certain a client player, the missile will be destroyed.
|
||||
-- When a missile is fired a SCHEDULER is set off that follows the missile. When near a certain a client player, the missile will be destroyed.
|
||||
-- @param #MISSILETRAINER
|
||||
-- @param #number Distance The distance in meters when a tracked missile needs to be destroyed when close to a player.
|
||||
-- @return #MISSILETRAINER
|
||||
@ -21,8 +21,8 @@ function MISSILETRAINER:New( Distance )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:F( Distance )
|
||||
|
||||
self.TimeTriggers = {}
|
||||
self.TimeTriggerID = 0
|
||||
self.Schedulers = {}
|
||||
self.SchedulerID = 0
|
||||
|
||||
self.Distance = Distance
|
||||
|
||||
@ -52,7 +52,7 @@ function MISSILETRAINER:_EventShot( Event )
|
||||
self:T( TrainerTargetSkill )
|
||||
|
||||
if TrainerTargetSkill == "Client" or TrainerTargetSkill == "Player" then
|
||||
self.TimeTriggers[#self.TimeTriggers+1] = TIMETRIGGER:New( self, self._FollowMissile, { TrainerSourceDCSUnit, TrainerWeapon, TrainerTargetDCSUnit }, 0.5, 0.05, 0 )
|
||||
self.Schedulers[#self.Schedulers+1] = SCHEDULER:New( self, self._FollowMissile, { TrainerSourceDCSUnit, TrainerWeapon, TrainerTargetDCSUnit }, 0.5, 0.05, 0 )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -474,7 +474,9 @@ function MISSIONSCHEDULER.Scheduler()
|
||||
if Mission.GoalFunction ~= nil then
|
||||
Mission.GoalFunction( Mission, Client )
|
||||
end
|
||||
_DATABASE:_AddMissionTaskScore( Client:GetClientGroupDCSUnit(), Mission.Name, 25 )
|
||||
if MISSIONSCHEDULER.Scoring then
|
||||
MISSIONSCHEDULER.Scoring:_AddMissionTaskScore( Client:GetClientGroupDCSUnit(), Mission.Name, 25 )
|
||||
end
|
||||
|
||||
-- if not Mission:IsCompleted() then
|
||||
-- end
|
||||
|
||||
@ -31,7 +31,7 @@ function PICKUPTASK:New( CargoType, OnBoardSide )
|
||||
self.CargoType = CargoType
|
||||
self.GoalVerb = CargoType .. " " .. self.GoalVerb
|
||||
self.OnBoardSide = OnBoardSide
|
||||
self.IsLandingRequired = false -- required to decide whether the client needs to land or not
|
||||
self.IsLandingRequired = true -- required to decide whether the client needs to land or not
|
||||
self.IsSlingLoad = false -- Indicates whether the cargo is a sling load cargo
|
||||
self.Stages = { STAGE_CARGO_INIT:New(), STAGE_CARGO_LOAD:New(), STAGEBRIEF:New(), STAGESTART:New(), STAGEROUTE:New(), STAGELANDING:New(), STAGELANDED:New(), STAGELOAD:New(), STAGEDONE:New() }
|
||||
self.SetStage( self, 1 )
|
||||
|
||||
@ -1524,6 +1524,47 @@ function routines.IsUnitInZones( TransportUnit, LandingZones )
|
||||
end
|
||||
end
|
||||
|
||||
function routines.IsUnitNearZonesRadius( TransportUnit, LandingZones, ZoneRadius )
|
||||
--trace.f("", "routines.IsUnitInZones" )
|
||||
|
||||
local TransportZoneResult = nil
|
||||
local TransportZonePos = nil
|
||||
local TransportZone = nil
|
||||
|
||||
-- fill-up some local variables to support further calculations to determine location of units within the zone.
|
||||
if TransportUnit then
|
||||
local TransportUnitPos = TransportUnit:getPosition().p
|
||||
if type( LandingZones ) == "table" then
|
||||
for LandingZoneID, LandingZoneName in pairs( LandingZones ) do
|
||||
TransportZone = trigger.misc.getZone( LandingZoneName )
|
||||
if TransportZone then
|
||||
TransportZonePos = {radius = TransportZone.radius, x = TransportZone.point.x, y = TransportZone.point.y, z = TransportZone.point.z}
|
||||
if ((( TransportUnitPos.x - TransportZonePos.x)^2 + (TransportUnitPos.z - TransportZonePos.z)^2)^0.5 <= ZoneRadius ) then
|
||||
TransportZoneResult = LandingZoneID
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
TransportZone = trigger.misc.getZone( LandingZones )
|
||||
TransportZonePos = {radius = TransportZone.radius, x = TransportZone.point.x, y = TransportZone.point.y, z = TransportZone.point.z}
|
||||
if ((( TransportUnitPos.x - TransportZonePos.x)^2 + (TransportUnitPos.z - TransportZonePos.z)^2)^0.5 <= ZoneRadius ) then
|
||||
TransportZoneResult = 1
|
||||
end
|
||||
end
|
||||
if TransportZoneResult then
|
||||
--trace.i( "routines", "TransportZone:" .. TransportZoneResult )
|
||||
else
|
||||
--trace.i( "routines", "TransportZone:nil logic" )
|
||||
end
|
||||
return TransportZoneResult
|
||||
else
|
||||
--trace.i( "routines", "TransportZone:nil hard" )
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function routines.IsStaticInZones( TransportStatic, LandingZones )
|
||||
--trace.f()
|
||||
|
||||
|
||||
114
Moose/Scheduler.lua
Normal file
114
Moose/Scheduler.lua
Normal file
@ -0,0 +1,114 @@
|
||||
--- Models time events calling event handing functions.
|
||||
-- @module Scheduler
|
||||
-- @author FlightControl
|
||||
|
||||
Include.File( "Routines" )
|
||||
Include.File( "Base" )
|
||||
Include.File( "Cargo" )
|
||||
Include.File( "Message" )
|
||||
|
||||
|
||||
--- The SCHEDULER class
|
||||
-- @type SCHEDULER
|
||||
-- @extends Base#BASE
|
||||
SCHEDULER = {
|
||||
ClassName = "SCHEDULER",
|
||||
}
|
||||
|
||||
|
||||
--- SCHEDULER constructor.
|
||||
-- @param #SCHEDULER self
|
||||
-- @param #table TimeEventObject
|
||||
-- @param #function TimeEventFunction
|
||||
-- @param #table TimeEventFunctionArguments
|
||||
-- @param #number StartSeconds
|
||||
-- @param #number RepeatSecondsInterval
|
||||
-- @param #number RandomizationFactor
|
||||
-- @param #number StopSeconds
|
||||
-- @return #SCHEDULER
|
||||
function SCHEDULER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:F( { TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds } )
|
||||
|
||||
self.TimeEventObject = TimeEventObject
|
||||
self.TimeEventFunction = TimeEventFunction
|
||||
self.TimeEventFunctionArguments = TimeEventFunctionArguments
|
||||
self.StartSeconds = StartSeconds
|
||||
|
||||
if RepeatSecondsInterval then
|
||||
self.RepeatSecondsInterval = RepeatSecondsInterval
|
||||
else
|
||||
self.RepeatSecondsInterval = 0
|
||||
end
|
||||
|
||||
if RandomizationFactor then
|
||||
self.RandomizationFactor = RandomizationFactor
|
||||
else
|
||||
self.RandomizationFactor = 0
|
||||
end
|
||||
|
||||
if StopSeconds then
|
||||
self.StopSeconds = StopSeconds
|
||||
end
|
||||
|
||||
self.Repeat = false
|
||||
|
||||
self.StartTime = timer.getTime()
|
||||
|
||||
self:Start()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function SCHEDULER:Scheduler()
|
||||
self:F( self.TimeEventFunctionArguments )
|
||||
|
||||
local ErrorHandler = function( errmsg )
|
||||
|
||||
env.info( "Error in SCHEDULER function:" .. errmsg )
|
||||
env.info( debug.traceback() )
|
||||
|
||||
return errmsg
|
||||
end
|
||||
|
||||
local Status, Result
|
||||
if self.TimeEventObject then
|
||||
Status, Result = xpcall( function() return self.TimeEventFunction( self.TimeEventObject, unpack( self.TimeEventFunctionArguments ) ) end, ErrorHandler )
|
||||
else
|
||||
Status, Result = xpcall( function() return self.TimeEventFunction( unpack( self.TimeEventFunctionArguments ) ) end, ErrorHandler )
|
||||
end
|
||||
|
||||
self:T( { Status, Result } )
|
||||
|
||||
if Status and Status == true and Result and Result == true then
|
||||
if self.Repeat and ( not self.StopSeconds or ( self.StopSeconds and timer.getTime() <= self.StartTime + self.StopSeconds ) ) then
|
||||
timer.scheduleFunction(
|
||||
self.Scheduler,
|
||||
self,
|
||||
timer.getTime() + self.RepeatSecondsInterval + math.random( - ( self.RandomizationFactor * self.RepeatSecondsInterval / 2 ), ( self.RandomizationFactor * self.RepeatSecondsInterval / 2 ) ) + 0.01
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SCHEDULER:Start()
|
||||
self:F( self.TimeEventObject )
|
||||
|
||||
self.Repeat = true
|
||||
timer.scheduleFunction( self.Scheduler, self, timer.getTime() + self.StartSeconds + .01 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function SCHEDULER:Stop()
|
||||
self:F( self.TimeEventObject )
|
||||
|
||||
self.Repeat = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -197,7 +197,7 @@ end
|
||||
function SCORING:_AddPlayerFromUnit( UnitData )
|
||||
self:F( UnitData )
|
||||
|
||||
if UnitData:isExist() then
|
||||
if UnitData and UnitData:isExist() then
|
||||
local UnitName = UnitData:getName()
|
||||
local PlayerName = UnitData:getPlayerName()
|
||||
local UnitDesc = UnitData:getDesc()
|
||||
@ -324,7 +324,7 @@ function SCORING:_EventOnHit( Event )
|
||||
local InitUnitName = ""
|
||||
local InitGroup = nil
|
||||
local InitGroupName = ""
|
||||
local InitPlayerName = "dummy"
|
||||
local InitPlayerName = nil
|
||||
|
||||
local InitCoalition = nil
|
||||
local InitCategory = nil
|
||||
|
||||
106
Moose/Spawn.lua
106
Moose/Spawn.lua
@ -80,6 +80,7 @@ Include.File( "Database" )
|
||||
Include.File( "Group" )
|
||||
Include.File( "Zone" )
|
||||
Include.File( "Event" )
|
||||
Include.File( "Scheduler" )
|
||||
|
||||
--- SPAWN Class
|
||||
-- @type SPAWN
|
||||
@ -323,8 +324,8 @@ function SPAWN:CleanUp( SpawnCleanUpInterval )
|
||||
|
||||
self.SpawnCleanUpInterval = SpawnCleanUpInterval
|
||||
self.SpawnCleanUpTimeStamps = {}
|
||||
self.CleanUpFunction = routines.scheduleFunction( self._SpawnCleanUpScheduler, { self }, timer.getTime() + 1, SpawnCleanUpInterval )
|
||||
|
||||
--self.CleanUpFunction = routines.scheduleFunction( self._SpawnCleanUpScheduler, { self }, timer.getTime() + 1, SpawnCleanUpInterval )
|
||||
self.CleanUpScheduler = SCHEDULER:New( self, self._SpawnCleanUpScheduler, {}, 1, SpawnCleanUpInterval, 0.2 )
|
||||
return self
|
||||
end
|
||||
|
||||
@ -456,6 +457,8 @@ function SPAWN:SpawnWithIndex( SpawnIndex )
|
||||
if self.RepeatOnEngineShutDown then
|
||||
_EVENTDISPATCHER:OnEngineShutDownForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnEngineShutDown, self )
|
||||
end
|
||||
|
||||
self:T( self.SpawnGroups[self.SpawnIndex].SpawnTemplate )
|
||||
|
||||
self.SpawnGroups[self.SpawnIndex].Group = _DATABASE:Spawn( self.SpawnGroups[self.SpawnIndex].SpawnTemplate )
|
||||
|
||||
@ -497,23 +500,29 @@ end
|
||||
function SPAWN:SpawnScheduled( SpawnTime, SpawnTimeVariation )
|
||||
self:F( { SpawnTime, SpawnTimeVariation } )
|
||||
|
||||
self.SpawnCurrentTimer = 0 -- The internal timer counter to trigger a scheduled spawning of SpawnTemplatePrefix.
|
||||
self.SpawnSetTimer = 0 -- The internal timer value when a scheduled spawning of SpawnTemplatePrefix occurs.
|
||||
self.AliveFactor = 1 --
|
||||
self.SpawnLowTimer = 0
|
||||
self.SpawnHighTimer = 0
|
||||
|
||||
if SpawnTime ~= nil and SpawnTimeVariation ~= nil then
|
||||
self.SpawnLowTimer = SpawnTime - SpawnTime / 2 * SpawnTimeVariation
|
||||
self.SpawnHighTimer = SpawnTime + SpawnTime / 2 * SpawnTimeVariation
|
||||
self:SpawnScheduleStart()
|
||||
self.SpawnScheduler = SCHEDULER:New( self, self._Scheduler, {}, 1, SpawnTime, SpawnTimeVariation )
|
||||
end
|
||||
|
||||
self:T( { self.SpawnLowTimer, self.SpawnHighTimer } )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Will re-start the spawning scheduler.
|
||||
-- Note: This function is only required to be called when the schedule was stopped.
|
||||
function SPAWN:SpawnScheduleStart()
|
||||
self:F( { self.SpawnTemplatePrefix } )
|
||||
|
||||
self.SpawnScheduler:Start()
|
||||
end
|
||||
|
||||
--- Will stop the scheduled spawning scheduler.
|
||||
function SPAWN:SpawnScheduleStop()
|
||||
self:F( { self.SpawnTemplatePrefix } )
|
||||
|
||||
self.SpawnScheduler:Stop()
|
||||
end
|
||||
|
||||
|
||||
--- Allows to place a CallFunction hook when a new group spawns.
|
||||
-- The provided function will be called when a new group is spawned, including its given parameters.
|
||||
-- The first parameter of the SpawnFunction is the @{Group#GROUP} that was spawned.
|
||||
@ -535,30 +544,6 @@ end
|
||||
|
||||
|
||||
|
||||
--- Will start the spawning scheduler.
|
||||
-- Note: This function is called automatically when @{#SPAWN.Scheduled} is called.
|
||||
function SPAWN:SpawnScheduleStart()
|
||||
self:F( { self.SpawnTemplatePrefix } )
|
||||
|
||||
--local ClientUnit = #AlivePlayerUnits()
|
||||
|
||||
self.AliveFactor = 10 -- ( 10 - ClientUnit ) / 10
|
||||
|
||||
if self.SpawnIsScheduled == false then
|
||||
self.SpawnIsScheduled = true
|
||||
self.SpawnInit = true
|
||||
self.SpawnSetTimer = math.random( self.SpawnLowTimer * self.AliveFactor / 10 , self.SpawnHighTimer * self.AliveFactor / 10 )
|
||||
|
||||
self.SpawnFunction = routines.scheduleFunction( self._Scheduler, { self }, timer.getTime() + 1, 1 )
|
||||
end
|
||||
end
|
||||
|
||||
--- Will stop the scheduled spawning scheduler.
|
||||
function SPAWN:SpawnScheduleStop()
|
||||
self:F( { self.SpawnTemplatePrefix } )
|
||||
|
||||
self.SpawnIsScheduled = false
|
||||
end
|
||||
|
||||
--- Will spawn a group from a hosting unit. This function is mostly advisable to be used if you want to simulate spawning from air units, like helicopters, which are dropping infantry into a defined Landing Zone.
|
||||
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
|
||||
@ -587,6 +572,9 @@ function SPAWN:SpawnFromUnit( HostUnit, OuterRadius, InnerRadius, SpawnIndex )
|
||||
if SpawnTemplate then
|
||||
|
||||
local UnitPoint = HostUnit:GetPointVec2()
|
||||
|
||||
self:T( { "Current point of ", self.SpawnTemplatePrefix, UnitPoint } )
|
||||
|
||||
--for PointID, Point in pairs( SpawnTemplate.route.points ) do
|
||||
--Point.x = UnitPoint.x
|
||||
--Point.y = UnitPoint.y
|
||||
@ -594,9 +582,6 @@ function SPAWN:SpawnFromUnit( HostUnit, OuterRadius, InnerRadius, SpawnIndex )
|
||||
--Point.alt_type = nil
|
||||
--end
|
||||
|
||||
SpawnTemplate.route.points = nil
|
||||
SpawnTemplate.route.points = {}
|
||||
SpawnTemplate.route.points[1] = {}
|
||||
SpawnTemplate.route.points[1].x = UnitPoint.x
|
||||
SpawnTemplate.route.points[1].y = UnitPoint.y
|
||||
|
||||
@ -677,8 +662,9 @@ function SPAWN:SpawnInZone( Zone, ZoneRandomize, SpawnIndex )
|
||||
|
||||
-- Apply SpawnFormation
|
||||
for UnitID = 1, #SpawnTemplate.units do
|
||||
SpawnTemplate.units[UnitID].x = ZonePoint.x
|
||||
SpawnTemplate.units[UnitID].y = ZonePoint.y
|
||||
local ZonePointUnit = Zone:GetRandomPointVec2()
|
||||
SpawnTemplate.units[UnitID].x = ZonePointUnit.x
|
||||
SpawnTemplate.units[UnitID].y = ZonePointUnit.y
|
||||
self:T( 'SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y )
|
||||
end
|
||||
|
||||
@ -907,7 +893,6 @@ function SPAWN:_InitializeSpawnGroups( SpawnIndex )
|
||||
self.SpawnGroups[SpawnIndex].Visible = false
|
||||
self.SpawnGroups[SpawnIndex].Spawned = false
|
||||
self.SpawnGroups[SpawnIndex].UnControlled = false
|
||||
self.SpawnGroups[SpawnIndex].Spawned = false
|
||||
self.SpawnGroups[SpawnIndex].SpawnTime = 0
|
||||
|
||||
self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix = self.SpawnTemplatePrefix
|
||||
@ -961,6 +946,9 @@ end
|
||||
|
||||
--- Gets the Group Template from the ME environment definition.
|
||||
-- This method used the @{DATABASE} object, which contains ALL initial and new spawned object in MOOSE.
|
||||
-- @param #SPAWN self
|
||||
-- @param #string SpawnTemplatePrefix
|
||||
-- @return @SPAWN self
|
||||
function SPAWN:_GetTemplate( SpawnTemplatePrefix )
|
||||
self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, SpawnTemplatePrefix } )
|
||||
|
||||
@ -981,6 +969,10 @@ function SPAWN:_GetTemplate( SpawnTemplatePrefix )
|
||||
end
|
||||
|
||||
--- Prepares the new Group Template.
|
||||
-- @param #SPAWN self
|
||||
-- @param #string SpawnTemplatePrefix
|
||||
-- @param #number SpawnIndex
|
||||
-- @return #SPAWN self
|
||||
function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex )
|
||||
self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix } )
|
||||
|
||||
@ -991,6 +983,7 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex )
|
||||
SpawnTemplate.lateActivation = false
|
||||
|
||||
if SpawnTemplate.SpawnCategoryID == Group.Category.GROUND then
|
||||
self:T( "For ground units, visible needs to be false..." )
|
||||
SpawnTemplate.visible = false
|
||||
end
|
||||
|
||||
@ -1010,7 +1003,7 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex )
|
||||
|
||||
end
|
||||
|
||||
--- Internal function randomizing the routes.
|
||||
--- Private method randomizing the routes.
|
||||
-- @param #SPAWN self
|
||||
-- @param #number SpawnIndex The index of the group to be spawned.
|
||||
-- @return #SPAWN
|
||||
@ -1034,7 +1027,10 @@ function SPAWN:_RandomizeRoute( SpawnIndex )
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Private method that randomizes the template of the group.
|
||||
-- @param #SPAWN self
|
||||
-- @param #number SpawnIndex
|
||||
-- @return #SPAWN self
|
||||
function SPAWN:_RandomizeTemplate( SpawnIndex )
|
||||
self:F( { self.SpawnTemplatePrefix, SpawnIndex } )
|
||||
|
||||
@ -1044,6 +1040,7 @@ function SPAWN:_RandomizeTemplate( SpawnIndex )
|
||||
self.SpawnGroups[SpawnIndex].SpawnTemplate.route = routines.utils.deepCopy( self.SpawnTemplate.route )
|
||||
self.SpawnGroups[SpawnIndex].SpawnTemplate.x = self.SpawnTemplate.x
|
||||
self.SpawnGroups[SpawnIndex].SpawnTemplate.y = self.SpawnTemplate.y
|
||||
self.SpawnGroups[SpawnIndex].SpawnTemplate.start_time = self.SpawnTemplate.start_time
|
||||
for UnitID = 1, #self.SpawnGroups[SpawnIndex].SpawnTemplate.units do
|
||||
self.SpawnGroups[SpawnIndex].SpawnTemplate.units[UnitID].heading = self.SpawnTemplate.units[1].heading
|
||||
end
|
||||
@ -1226,19 +1223,10 @@ end
|
||||
function SPAWN:_Scheduler()
|
||||
self:F( { "_Scheduler", self.SpawnTemplatePrefix, self.SpawnAliasPrefix, self.SpawnIndex, self.SpawnMaxGroups, self.SpawnMaxUnitsAlive } )
|
||||
|
||||
if self.SpawnInit or self.SpawnCurrentTimer == self.SpawnSetTimer then
|
||||
-- Validate if there are still groups left in the batch...
|
||||
self:Spawn()
|
||||
self.SpawnInit = false
|
||||
if self.SpawnIsScheduled == true then
|
||||
--local ClientUnit = #AlivePlayerUnits()
|
||||
self.AliveFactor = 1 -- ( 10 - ClientUnit ) / 10
|
||||
self.SpawnCurrentTimer = 0
|
||||
self.SpawnSetTimer = math.random( self.SpawnLowTimer * self.AliveFactor , self.SpawnHighTimer * self.AliveFactor )
|
||||
end
|
||||
else
|
||||
self.SpawnCurrentTimer = self.SpawnCurrentTimer + 1
|
||||
end
|
||||
-- Validate if there are still groups left in the batch...
|
||||
self:Spawn()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function SPAWN:_SpawnCleanUpScheduler()
|
||||
@ -1270,4 +1258,6 @@ function SPAWN:_SpawnCleanUpScheduler()
|
||||
|
||||
end
|
||||
|
||||
return true -- Repeat
|
||||
|
||||
end
|
||||
|
||||
186
Moose/Stage.lua
186
Moose/Stage.lua
@ -36,7 +36,7 @@ end
|
||||
function STAGE:Execute( Mission, Client, Task )
|
||||
|
||||
local Valid = true
|
||||
|
||||
|
||||
return Valid
|
||||
end
|
||||
|
||||
@ -46,7 +46,7 @@ end
|
||||
|
||||
function STAGE:Validate( Mission, Client, Task )
|
||||
local Valid = true
|
||||
|
||||
|
||||
return Valid
|
||||
end
|
||||
|
||||
@ -255,7 +255,7 @@ function STAGEROUTE:Validate( Mission, Client, Task )
|
||||
|
||||
-- check if the Client is in the landing zone
|
||||
self:T( Task.LandingZones.LandingZoneNames )
|
||||
Task.CurrentLandingZoneName = routines.IsUnitInZones( Client:GetClientGroupDCSUnit(), Task.LandingZones.LandingZoneNames )
|
||||
Task.CurrentLandingZoneName = routines.IsUnitNearZonesRadius( Client:GetClientGroupDCSUnit(), Task.LandingZones.LandingZoneNames, 500 )
|
||||
|
||||
if Task.CurrentLandingZoneName then
|
||||
|
||||
@ -268,9 +268,11 @@ function STAGEROUTE:Validate( Mission, Client, Task )
|
||||
end
|
||||
end
|
||||
|
||||
self:T( 1 )
|
||||
return 1
|
||||
end
|
||||
|
||||
self:T( 0 )
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -345,8 +347,17 @@ function STAGELANDING:Execute( Mission, Client, Task )
|
||||
else
|
||||
HostMessage = "Use the Radio menu and F6 to find the cargo, then fly or land near the cargo and " .. Task.TEXT[1] .. " " .. Task.CargoNames .. "."
|
||||
end
|
||||
|
||||
local Host = "Command"
|
||||
if Task.HostUnitName then
|
||||
Host = Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")"
|
||||
else
|
||||
if Client:IsMultiSeated() then
|
||||
Host = "Co-Pilot"
|
||||
end
|
||||
end
|
||||
|
||||
Client:Message( HostMessage, self.MSG.TIME, Mission.Name .. "/STAGELANDING.EXEC." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")", 10 )
|
||||
Client:Message( HostMessage, self.MSG.TIME, Mission.Name .. "/STAGELANDING.EXEC." .. Host, Host, 10 )
|
||||
|
||||
end
|
||||
end
|
||||
@ -354,7 +365,7 @@ end
|
||||
function STAGELANDING:Validate( Mission, Client, Task )
|
||||
self:F()
|
||||
|
||||
Task.CurrentLandingZoneName = routines.IsUnitInZones( Client:GetClientGroupDCSUnit(), Task.LandingZones.LandingZoneNames )
|
||||
Task.CurrentLandingZoneName = routines.IsUnitNearZonesRadius( Client:GetClientGroupDCSUnit(), Task.LandingZones.LandingZoneNames, 500 )
|
||||
if Task.CurrentLandingZoneName then
|
||||
|
||||
-- Client is in de landing zone.
|
||||
@ -377,14 +388,34 @@ function STAGELANDING:Validate( Mission, Client, Task )
|
||||
end
|
||||
Task.Signalled = false
|
||||
Task:RemoveCargoMenus( Client )
|
||||
self:T( -1 )
|
||||
return -1
|
||||
end
|
||||
|
||||
if Task.IsLandingRequired and Client:GetClientGroupDCSUnit():inAir() then
|
||||
return 0
|
||||
end
|
||||
|
||||
local DCSUnitVelocityVec3 = Client:GetClientGroupDCSUnit():getVelocity()
|
||||
local DCSUnitVelocity = ( DCSUnitVelocityVec3.x ^2 + DCSUnitVelocityVec3.y ^2 + DCSUnitVelocityVec3.z ^2 ) ^ 0.5
|
||||
|
||||
local DCSUnitPointVec3 = Client:GetClientGroupDCSUnit():getPoint()
|
||||
local LandHeight = land.getHeight( { x = DCSUnitPointVec3.x, y = DCSUnitPointVec3.z } )
|
||||
local DCSUnitHeight = DCSUnitPointVec3.y - LandHeight
|
||||
|
||||
self:T( { Task.IsLandingRequired, Client:GetClientGroupDCSUnit():inAir() } )
|
||||
if Task.IsLandingRequired and not Client:GetClientGroupDCSUnit():inAir() then
|
||||
self:T( 1 )
|
||||
Task.IsInAirTestRequired = true
|
||||
return 1
|
||||
end
|
||||
|
||||
return 1
|
||||
self:T( { DCSUnitVelocity, DCSUnitHeight, LandHeight, Task.CurrentCargoZone.SignalHeight } )
|
||||
if Task.IsLandingRequired and DCSUnitVelocity <= 0.05 and DCSUnitHeight <= Task.CurrentCargoZone.SignalHeight then
|
||||
self:T( 1 )
|
||||
Task.IsInAirTestRequired = false
|
||||
return 1
|
||||
end
|
||||
|
||||
self:T( 0 )
|
||||
return 0
|
||||
end
|
||||
|
||||
STAGELANDED = {
|
||||
@ -405,9 +436,20 @@ function STAGELANDED:Execute( Mission, Client, Task )
|
||||
self:F()
|
||||
|
||||
if Task.IsLandingRequired then
|
||||
Client:Message( 'You have landed within the landing zone. Use the radio menu (F10) to ' .. Task.TEXT[1] .. ' the ' .. Task.CargoType .. '.',
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDED.EXEC." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" )
|
||||
if not self.MenusAdded then
|
||||
|
||||
local Host = "Command"
|
||||
if Task.HostUnitName then
|
||||
Host = Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")"
|
||||
else
|
||||
if Client:IsMultiSeated() then
|
||||
Host = "Co-Pilot"
|
||||
end
|
||||
end
|
||||
|
||||
Client:Message( 'You have landed within the landing zone. Use the radio menu (F10) to ' .. Task.TEXT[1] .. ' the ' .. Task.CargoType .. '.',
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDED.EXEC" .. Host, Host )
|
||||
|
||||
if not self.MenusAdded then
|
||||
Task.Cargo = nil
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task:AddCargoMenus( Client, CARGOS, 250 )
|
||||
@ -420,26 +462,44 @@ end
|
||||
function STAGELANDED:Validate( Mission, Client, Task )
|
||||
self:F()
|
||||
|
||||
if not routines.IsUnitInZones( Client:GetClientGroupDCSUnit(), Task.CurrentLandingZoneName ) then
|
||||
if not routines.IsUnitNearZonesRadius( Client:GetClientGroupDCSUnit(), Task.CurrentLandingZoneName, 500 ) then
|
||||
self:T( "Client is not anymore in the landing zone, go back to stage Route, and remove cargo menus." )
|
||||
Task.Signalled = false
|
||||
Task:RemoveCargoMenus( Client )
|
||||
self:T( -2 )
|
||||
return -2
|
||||
end
|
||||
|
||||
local DCSUnitVelocityVec3 = Client:GetClientGroupDCSUnit():getVelocity()
|
||||
local DCSUnitVelocity = ( DCSUnitVelocityVec3.x ^2 + DCSUnitVelocityVec3.y ^2 + DCSUnitVelocityVec3.z ^2 ) ^ 0.5
|
||||
|
||||
if Task.IsLandingRequired and Client:GetClientGroupDCSUnit():inAir() then
|
||||
self:T( "Client went back in the air. Go back to stage Landing." )
|
||||
Task.Signalled = false
|
||||
return -1
|
||||
end
|
||||
local DCSUnitPointVec3 = Client:GetClientGroupDCSUnit():getPoint()
|
||||
local LandHeight = land.getHeight( { x = DCSUnitPointVec3.x, y = DCSUnitPointVec3.z } )
|
||||
local DCSUnitHeight = DCSUnitPointVec3.y - LandHeight
|
||||
|
||||
self:T( { Task.IsLandingRequired, Client:GetClientGroupDCSUnit():inAir() } )
|
||||
if Task.IsLandingRequired and Task.IsInAirTestRequired == true and Client:GetClientGroupDCSUnit():inAir() then
|
||||
self:T( "Client went back in the air. Go back to stage Landing." )
|
||||
self:T( -1 )
|
||||
return -1
|
||||
end
|
||||
|
||||
self:T( { DCSUnitVelocity, DCSUnitHeight, LandHeight, Task.CurrentCargoZone.SignalHeight } )
|
||||
if Task.IsLandingRequired and Task.IsInAirTestRequired == false and DCSUnitVelocity >= 2 and DCSUnitHeight >= Task.CurrentCargoZone.SignalHeight then
|
||||
self:T( "It seems the Client went back in the air and over the boundary limits. Go back to stage Landing." )
|
||||
self:T( -1 )
|
||||
return -1
|
||||
end
|
||||
|
||||
-- Wait until cargo is selected from the menu.
|
||||
if Task.IsLandingRequired then
|
||||
if not Task.Cargo then
|
||||
self:T( 0 )
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
self:T( 1 )
|
||||
return 1
|
||||
end
|
||||
|
||||
@ -503,7 +563,7 @@ function STAGEUNLOAD:Validate( Mission, Client, Task )
|
||||
self:F()
|
||||
env.info( 'STAGEUNLOAD:Validate()' )
|
||||
|
||||
if routines.IsUnitInZones( Client:GetClientGroupDCSUnit(), Task.CurrentLandingZoneName ) then
|
||||
if routines.IsUnitNearZonesRadius( Client:GetClientGroupDCSUnit(), Task.CurrentLandingZoneName, 500 ) then
|
||||
else
|
||||
Task.ExecuteStage = _TransportExecuteStage.FAILED
|
||||
Task:RemoveCargoMenus( Client )
|
||||
@ -562,10 +622,21 @@ function STAGELOAD:Execute( Mission, Client, Task )
|
||||
self:F()
|
||||
|
||||
if not Task.IsSlingLoad then
|
||||
|
||||
local Host = "Command"
|
||||
if Task.HostUnitName then
|
||||
Host = Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")"
|
||||
else
|
||||
if Client:IsMultiSeated() then
|
||||
Host = "Co-Pilot"
|
||||
end
|
||||
end
|
||||
|
||||
Client:Message( 'The ' .. Task.CargoType .. ' are being ' .. Task.TEXT[2] .. ' within the landing zone. Wait until the helicopter is ' .. Task.TEXT[3] .. '.',
|
||||
_TransportStageMsgTime.EXECUTING, Mission.Name .. "/STAGELOAD.EXEC." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" )
|
||||
_TransportStageMsgTime.EXECUTING, Mission.Name .. "/STAGELOAD.EXEC." .. Host, Host )
|
||||
|
||||
-- Route the cargo to the Carrier
|
||||
|
||||
Task.Cargo:OnBoard( Client, Task.CurrentCargoZone, Task.OnBoardSide )
|
||||
Task.ExecuteStage = _TransportExecuteStage.EXECUTING
|
||||
else
|
||||
@ -578,6 +649,14 @@ function STAGELOAD:Executing( Mission, Client, Task )
|
||||
|
||||
-- If the Cargo is ready to be loaded, load it into the Client.
|
||||
|
||||
local Host = "Command"
|
||||
if Task.HostUnitName then
|
||||
Host = Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")"
|
||||
else
|
||||
if Client:IsMultiSeated() then
|
||||
Host = "Co-Pilot"
|
||||
end
|
||||
end
|
||||
|
||||
if not Task.IsSlingLoad then
|
||||
self:T( Task.Cargo.CargoName)
|
||||
@ -589,14 +668,14 @@ function STAGELOAD:Executing( Mission, Client, Task )
|
||||
|
||||
-- Message to the pilot that cargo has been loaded.
|
||||
Client:Message( "The cargo " .. Task.Cargo.CargoName .. " has been loaded in our helicopter.",
|
||||
20, Mission.Name .. "/STAGELANDING.LOADING1." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" )
|
||||
20, Mission.Name .. "/STAGELANDING.LOADING1." .. Host, Host )
|
||||
Task.ExecuteStage = _TransportExecuteStage.SUCCESS
|
||||
|
||||
Client:ShowCargo()
|
||||
end
|
||||
else
|
||||
Client:Message( "Hook the " .. Task.CargoNames .. " onto the helicopter " .. Task.TEXT[3] .. " within the landing zone.",
|
||||
_TransportStageMsgTime.EXECUTING, Mission.Name .. "/STAGELOAD.LOADING.1." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")", 10 )
|
||||
_TransportStageMsgTime.EXECUTING, Mission.Name .. "/STAGELOAD.LOADING.1." .. Host, Host , 10 )
|
||||
for CargoID, Cargo in pairs( CARGOS ) do
|
||||
self:T( "Cargo.CargoName = " .. Cargo.CargoName )
|
||||
|
||||
@ -612,7 +691,7 @@ function STAGELOAD:Executing( Mission, Client, Task )
|
||||
Cargo:StatusLoaded()
|
||||
Task.Cargo = Cargo
|
||||
Client:Message( 'The Cargo has been successfully hooked onto the helicopter and is now being sling loaded. Fly outside the landing zone.',
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.LOADING.2." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" )
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.LOADING.2." .. Host, Host )
|
||||
Task.ExecuteStage = _TransportExecuteStage.SUCCESS
|
||||
break
|
||||
end
|
||||
@ -630,32 +709,61 @@ function STAGELOAD:Validate( Mission, Client, Task )
|
||||
|
||||
self:T( "Task.CurrentLandingZoneName = " .. Task.CurrentLandingZoneName )
|
||||
|
||||
local Host = "Command"
|
||||
if Task.HostUnitName then
|
||||
Host = Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")"
|
||||
else
|
||||
if Client:IsMultiSeated() then
|
||||
Host = "Co-Pilot"
|
||||
end
|
||||
end
|
||||
|
||||
if not Task.IsSlingLoad then
|
||||
if not routines.IsUnitInZones( Client:GetClientGroupDCSUnit(), Task.CurrentLandingZoneName ) then
|
||||
if not routines.IsUnitNearZonesRadius( Client:GetClientGroupDCSUnit(), Task.CurrentLandingZoneName, 500 ) then
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task.ExecuteStage = _TransportExecuteStage.FAILED
|
||||
Task.CargoName = nil
|
||||
Client:Message( "The " .. Task.CargoType .. " loading has been aborted. You flew outside the pick-up zone while loading. ",
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.1." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" )
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.1." .. Host, Host )
|
||||
self:T( -1 )
|
||||
return -1
|
||||
end
|
||||
|
||||
if not Client:GetClientGroupDCSUnit():inAir() then
|
||||
else
|
||||
-- The carrier is back in the air, undo the loading process.
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task.ExecuteStage = _TransportExecuteStage.NONE
|
||||
Task.CargoName = nil
|
||||
Client:Message( "The " .. Task.CargoType .. " loading has been aborted. Re-start the " .. Task.TEXT[3] .. " process. Don't fly outside the pick-up zone.",
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.2." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" )
|
||||
return -1
|
||||
end
|
||||
local DCSUnitVelocityVec3 = Client:GetClientGroupDCSUnit():getVelocity()
|
||||
local DCSUnitVelocity = ( DCSUnitVelocityVec3.x ^2 + DCSUnitVelocityVec3.y ^2 + DCSUnitVelocityVec3.z ^2 ) ^ 0.5
|
||||
|
||||
local DCSUnitPointVec3 = Client:GetClientGroupDCSUnit():getPoint()
|
||||
local LandHeight = land.getHeight( { x = DCSUnitPointVec3.x, y = DCSUnitPointVec3.z } )
|
||||
local DCSUnitHeight = DCSUnitPointVec3.y - LandHeight
|
||||
|
||||
self:T( { Task.IsLandingRequired, Client:GetClientGroupDCSUnit():inAir() } )
|
||||
if Task.IsLandingRequired and Task.IsInAirTestRequired == true and Client:GetClientGroupDCSUnit():inAir() then
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task.ExecuteStage = _TransportExecuteStage.FAILED
|
||||
Task.CargoName = nil
|
||||
Client:Message( "The " .. Task.CargoType .. " loading has been aborted. Re-start the " .. Task.TEXT[3] .. " process. Don't fly outside the pick-up zone.",
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.1." .. Host, Host )
|
||||
self:T( -1 )
|
||||
return -1
|
||||
end
|
||||
|
||||
self:T( { DCSUnitVelocity, DCSUnitHeight, LandHeight, Task.CurrentCargoZone.SignalHeight } )
|
||||
if Task.IsLandingRequired and Task.IsInAirTestRequired == false and DCSUnitVelocity >= 2 and DCSUnitHeight >= Task.CurrentCargoZone.SignalHeight then
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Task.ExecuteStage = _TransportExecuteStage.FAILED
|
||||
Task.CargoName = nil
|
||||
Client:Message( "The " .. Task.CargoType .. " loading has been aborted. Re-start the " .. Task.TEXT[3] .. " process. Don't fly outside the pick-up zone.",
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.1." .. Host, Host )
|
||||
self:T( -1 )
|
||||
return -1
|
||||
end
|
||||
|
||||
if Task.ExecuteStage == _TransportExecuteStage.SUCCESS then
|
||||
Task:RemoveCargoMenus( Client )
|
||||
Client:Message( "Good Job. The " .. Task.CargoType .. " has been sucessfully " .. Task.TEXT[3] .. " within the landing zone.",
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.3." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" )
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.3." .. Host, Host )
|
||||
Task.MissionTask:AddGoalCompletion( Task.MissionTask.GoalVerb, Task.CargoName, 1 )
|
||||
self:T( 1 )
|
||||
return 1
|
||||
end
|
||||
|
||||
@ -664,8 +772,9 @@ function STAGELOAD:Validate( Mission, Client, Task )
|
||||
CargoStatic = StaticObject.getByName( Task.Cargo.CargoStaticName )
|
||||
if CargoStatic and not routines.IsStaticInZones( CargoStatic, Task.CurrentLandingZoneName ) then
|
||||
Client:Message( "Good Job. The " .. Task.CargoType .. " has been sucessfully " .. Task.TEXT[3] .. " and flown outside of the landing zone.",
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.4." .. Task.HostUnitName, Task.HostUnitName .. " (" .. Task.HostUnitTypeName .. ")" )
|
||||
self.MSG.TIME, Mission.Name .. "/STAGELANDING.VALIDATE.4." .. Host, Host )
|
||||
Task.MissionTask:AddGoalCompletion( Task.MissionTask.GoalVerb, Task.Cargo.CargoName, 1 )
|
||||
self:T( 1 )
|
||||
return 1
|
||||
end
|
||||
end
|
||||
@ -673,6 +782,7 @@ function STAGELOAD:Validate( Mission, Client, Task )
|
||||
end
|
||||
|
||||
|
||||
self:T( 0 )
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
--- Models time events calling event handing functions.
|
||||
-- @module TimeTrigger
|
||||
-- @author FlightControl
|
||||
|
||||
Include.File( "Routines" )
|
||||
Include.File( "Base" )
|
||||
Include.File( "Cargo" )
|
||||
Include.File( "Message" )
|
||||
|
||||
|
||||
--- The TIMETRIGGER class
|
||||
-- @type TIMETRIGGER
|
||||
-- @extends Base#BASE
|
||||
TIMETRIGGER = {
|
||||
ClassName = "TIMETRIGGER",
|
||||
}
|
||||
|
||||
|
||||
--- TIMETRIGGER constructor.
|
||||
-- @param #TIMETRIGGER self
|
||||
-- @param #function TimeEventFunction
|
||||
-- @param #table TimeEventFunctionArguments
|
||||
-- @param #number StartSeconds
|
||||
-- @param #number RepeatSecondsInterval
|
||||
-- @param #number RandomizationFactor
|
||||
-- @param #number StopSeconds
|
||||
-- @return #TIMETRIGGER
|
||||
function TIMETRIGGER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:F( { TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds } )
|
||||
|
||||
self.TimeEventObject = TimeEventObject
|
||||
self.TimeEventFunction = TimeEventFunction
|
||||
self.TimeEventFunctionArguments = TimeEventFunctionArguments
|
||||
self.StartSeconds = StartSeconds
|
||||
|
||||
if RepeatSecondsInterval then
|
||||
self.RepeatSecondsInterval = RepeatSecondsInterval
|
||||
else
|
||||
self.RepeatSecondsInterval = 0
|
||||
end
|
||||
|
||||
if RandomizationFactor then
|
||||
self.RandomizationFactor = RandomizationFactor
|
||||
else
|
||||
self.RandomizationFactor = 0
|
||||
end
|
||||
|
||||
if StopSeconds then
|
||||
self.StopSeconds = StopSeconds
|
||||
end
|
||||
|
||||
self.StartTime = timer.getTime()
|
||||
|
||||
self:T("Calling function" .. timer.getTime() + self.StartSeconds )
|
||||
|
||||
timer.scheduleFunction( self.Scheduler, self, timer.getTime() + self.StartSeconds + .01 )
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function TIMETRIGGER:Scheduler()
|
||||
self:F( self.TimeEventFunctionArguments )
|
||||
|
||||
local Result = self.TimeEventFunction( self.TimeEventObject, unpack( self.TimeEventFunctionArguments ) )
|
||||
|
||||
if Result and Result == true then
|
||||
if not self.StopSeconds or ( self.StopSeconds and timer.getTime() <= self.StartTime + self.StopSeconds ) then
|
||||
timer.scheduleFunction(
|
||||
self.Scheduler,
|
||||
self,
|
||||
timer.getTime() + self.RepeatSecondsInterval * math.random( self.RandomizationFactor * self.RepeatSecondsInterval ) + 0.01
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -40,6 +40,17 @@ function ZONE:GetPointVec2()
|
||||
return Point
|
||||
end
|
||||
|
||||
function ZONE:GetPointVec3( Height )
|
||||
self:F( self.ZoneName )
|
||||
|
||||
local Zone = trigger.misc.getZone( self.ZoneName )
|
||||
local Point = { x = Zone.point.x, y = land.getHeight( self:GetPointVec2() ) + Height, z = Zone.point.z }
|
||||
|
||||
self:T( { Zone, Point } )
|
||||
|
||||
return Point
|
||||
end
|
||||
|
||||
function ZONE:GetRandomPointVec2()
|
||||
self:F( self.ZoneName )
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB |
60
index.html
60
index.html
@ -1,60 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Moose by FlightControl-Master</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/normalize.css" media="screen">
|
||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/github-light.css" media="screen">
|
||||
</head>
|
||||
<body>
|
||||
<section class="page-header">
|
||||
<h1 class="project-name">Moose</h1>
|
||||
<h2 class="project-tagline">Mission Object Oriented Scripting Environment (MOOSE) for lua mission scripting design in DCS World</h2>
|
||||
<a href="https://github.com/FlightControl-Master/MOOSE" class="btn">View on GitHub</a>
|
||||
<a href="https://github.com/FlightControl-Master/MOOSE/zipball/master" class="btn">Download .zip</a>
|
||||
<a href="https://github.com/FlightControl-Master/MOOSE/tarball/master" class="btn">Download .tar.gz</a>
|
||||
</section>
|
||||
|
||||
<section class="main-content">
|
||||
<h1>
|
||||
<a id="context" class="anchor" href="#context" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Context</h1>
|
||||
|
||||
<p>A development has been ongoing for a while now, which allows to create missions quickly using an Object Oriented Framework developed in lua.
|
||||
MOOSE is currently still in alpha version, but will evolve over time. Right now, it has been updated to work with DCS world 1.5.</p>
|
||||
|
||||
<p>MOOSE is a <strong>M</strong>ission <strong>O</strong>bject <strong>O</strong>riented <strong>S</strong>cripting <strong>E</strong>nvironment, and is meant for mission designers and mission hosters. It allows to quickly setup complex missions using pre-scripted scenarios using the available classes within the framework.</p>
|
||||
|
||||
<p>You can find the source of MOOSE here on GITHUB. It is free for download:
|
||||
<a href="https://github.com/FlightControl-Master/MOOSE/">https://github.com/FlightControl-Master/MOOSE/</a></p>
|
||||
|
||||
<h1>
|
||||
<a id="goals" class="anchor" href="#goals" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Goals</h1>
|
||||
|
||||
<p>The goal of MOOSE is to allow mission designers to enhance their scripting with mission orchestration objects, which can be instantiated from defined classes within the framework. This will allow to write mission scripts with minimal code embedded. Of course, the richness of the framework will determine the richness of the misson scenarios. We can expect that MOOSE will evolve over time, as more missions will be designed within the framework.</p>
|
||||
|
||||
<h1>
|
||||
<a id="classes" class="anchor" href="#classes" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Classes</h1>
|
||||
|
||||
<p>The following classes are currently embedded within MOOSE:</p>
|
||||
|
||||
<ul>
|
||||
<li><p><a href="Documentation/Base.html">BASE</a>: The main class from which all MOOSE classes are derived from. The BASE class contains essential functions to support inheritance and MOOSE object execution tracing (logging within the DCS.log file in the saved games folder of the user).</p></li>
|
||||
<li><p><a href="Documentation/DATABASE.html">DATABASE</a>: Create sets of units (and groups) upon defined filter criteria. These sets can be used to iterate the DATABASE calling a defined function for each unit (or group).</p></li>
|
||||
<li><p><a href="Documentation/Spawn.html">SPAWN</a>: Spawn new groups (and units) during mission execution.</p></li>
|
||||
<li><p><a href="Documentation/Escort.html">ESCORT</a>: Makes groups consisting of helicopters, airplanes, ground troops or ships within a mission joining your flight. You can control these groups through the ratio menu during your flight. Available commands are around: Navigation, Position Hold, Reporting (Target Detection), Attacking, Assisted Attacks, ROE, Evasion, Mission Execution and more ...</p></li>
|
||||
</ul>
|
||||
|
||||
<footer class="site-footer">
|
||||
<span class="site-footer-owner"><a href="https://github.com/FlightControl-Master/MOOSE">Moose</a> is maintained by <a href="https://github.com/FlightControl-Master">FlightControl-Master</a>.</span>
|
||||
|
||||
<span class="site-footer-credits">This page was generated by <a href="https://pages.github.com">GitHub Pages</a> using the <a href="https://github.com/jasonlong/cayman-theme">Cayman theme</a> by <a href="https://twitter.com/jasonlong">Jason Long</a>.</span>
|
||||
</footer>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -1 +0,0 @@
|
||||
console.log('This would be the main JS file.');
|
||||
@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "Moose",
|
||||
"tagline": "Mission Object Oriented Scripting Environment (MOOSE) for lua mission scripting design in DCS World",
|
||||
"body": "# Context\r\n\r\nA development has been ongoing for a while now, which allows to create missions quickly using an Object Oriented Framework developed in lua.\r\nMOOSE is currently still in alpha version, but will evolve over time. Right now, it has been updated to work with DCS world 1.5.\r\n\r\nMOOSE is a **M**ission **O**bject **O**riented **S**cripting **E**nvironment, and is meant for mission designers and mission hosters. It allows to quickly setup complex missions using pre-scripted scenarios using the available classes within the framework.\r\n\r\nYou can find the source of MOOSE here on GITHUB. It is free for download: \r\nhttps://github.com/FlightControl-Master/MOOSE/\r\n\r\n# Goals\r\n\r\nThe goal of MOOSE is to allow mission designers to enhance their scripting with mission orchestration objects, which can be instantiated from defined classes within the framework. This will allow to write mission scripts with minimal code embedded. Of course, the richness of the framework will determine the richness of the misson scenarios. We can expect that MOOSE will evolve over time, as more missions will be designed within the framework.\r\n\r\n# Classes\r\n\r\nThe following classes are currently embedded within MOOSE:\r\n\r\n* [BASE](Documentation/Base.html): The main class from which all MOOSE classes are derived from. The BASE class contains essential functions to support inheritance and MOOSE object execution tracing (logging within the DCS.log file in the saved games folder of the user).\r\n\r\n* [DATABASE](Documentation/DATABASE.html): Create sets of units (and groups) upon defined filter criteria. These sets can be used to iterate the DATABASE calling a defined function for each unit (or group).\r\n\r\n* [SPAWN](Documentation/Spawn.html): Spawn new groups (and units) during mission execution.\r\n\r\n* [ESCORT](Documentation/Escort.html): Makes groups consisting of helicopters, airplanes, ground troops or ships within a mission joining your flight. You can control these groups through the ratio menu during your flight. Available commands are around: Navigation, Position Hold, Reporting (Target Detection), Attacking, Assisted Attacks, ROE, Evasion, Mission Execution and more ...\r\n\r\n",
|
||||
"note": "Don't delete this file! It's used internally to help with page regeneration."
|
||||
}
|
||||
@ -1,124 +0,0 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 GitHub, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
.pl-c /* comment */ {
|
||||
color: #969896;
|
||||
}
|
||||
|
||||
.pl-c1 /* constant, markup.raw, meta.diff.header, meta.module-reference, meta.property-name, support, support.constant, support.variable, variable.other.constant */,
|
||||
.pl-s .pl-v /* string variable */ {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.pl-e /* entity */,
|
||||
.pl-en /* entity.name */ {
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.pl-s .pl-s1 /* string source */,
|
||||
.pl-smi /* storage.modifier.import, storage.modifier.package, storage.type.java, variable.other, variable.parameter.function */ {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.pl-ent /* entity.name.tag */ {
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.pl-k /* keyword, storage, storage.type */ {
|
||||
color: #a71d5d;
|
||||
}
|
||||
|
||||
.pl-pds /* punctuation.definition.string, string.regexp.character-class */,
|
||||
.pl-s /* string */,
|
||||
.pl-s .pl-pse .pl-s1 /* string punctuation.section.embedded source */,
|
||||
.pl-sr /* string.regexp */,
|
||||
.pl-sr .pl-cce /* string.regexp constant.character.escape */,
|
||||
.pl-sr .pl-sra /* string.regexp string.regexp.arbitrary-repitition */,
|
||||
.pl-sr .pl-sre /* string.regexp source.ruby.embedded */ {
|
||||
color: #183691;
|
||||
}
|
||||
|
||||
.pl-v /* variable */ {
|
||||
color: #ed6a43;
|
||||
}
|
||||
|
||||
.pl-id /* invalid.deprecated */ {
|
||||
color: #b52a1d;
|
||||
}
|
||||
|
||||
.pl-ii /* invalid.illegal */ {
|
||||
background-color: #b52a1d;
|
||||
color: #f8f8f8;
|
||||
}
|
||||
|
||||
.pl-sr .pl-cce /* string.regexp constant.character.escape */ {
|
||||
color: #63a35c;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pl-ml /* markup.list */ {
|
||||
color: #693a17;
|
||||
}
|
||||
|
||||
.pl-mh /* markup.heading */,
|
||||
.pl-mh .pl-en /* markup.heading entity.name */,
|
||||
.pl-ms /* meta.separator */ {
|
||||
color: #1d3e81;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pl-mq /* markup.quote */ {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.pl-mi /* markup.italic */ {
|
||||
color: #333;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.pl-mb /* markup.bold */ {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pl-md /* markup.deleted, meta.diff.header.from-file */ {
|
||||
background-color: #ffecec;
|
||||
color: #bd2c00;
|
||||
}
|
||||
|
||||
.pl-mi1 /* markup.inserted, meta.diff.header.to-file */ {
|
||||
background-color: #eaffea;
|
||||
color: #55a532;
|
||||
}
|
||||
|
||||
.pl-mdr /* meta.diff.range */ {
|
||||
color: #795da3;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pl-mo /* meta.output */ {
|
||||
color: #1d3e81;
|
||||
}
|
||||
|
||||
424
stylesheets/normalize.css
vendored
424
stylesheets/normalize.css
vendored
@ -1,424 +0,0 @@
|
||||
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
|
||||
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Correct `block` display not defined for any HTML5 element in IE 8/9.
|
||||
* Correct `block` display not defined for `details` or `summary` in IE 10/11
|
||||
* and Firefox.
|
||||
* Correct `block` display not defined for `main` in IE 11.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `inline-block` display not defined in IE 8/9.
|
||||
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `[hidden]` styling not present in IE 8/9/10.
|
||||
* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
|
||||
*/
|
||||
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background color from active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability when focused and also mouse hovered in all browsers.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9/10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow not hidden in IE 9/10/11.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contain overflow in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address odd `em`-unit font size rendering in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Known limitation: by default, Chrome and Safari on OS X allow very limited
|
||||
* styling of `select`, unless a `border` property is set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. Correct color not being inherited.
|
||||
* Known issue: affects color of disabled elements.
|
||||
* 2. Correct font properties not being inherited.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
color: inherit; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `overflow` set to `hidden` in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
button {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
|
||||
* Correct `select` style inheritance in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's recommended that you don't attempt to style these elements.
|
||||
* Firefox's implementation doesn't respect box-sizing, padding, or width.
|
||||
*
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||
* 2. Remove excess padding in IE 8/9/10.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
|
||||
* `font-size` values of the `input`, it causes the cursor style of the
|
||||
* decrement button to change from `default` to `text`.
|
||||
*/
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome
|
||||
* (include `-moz` to future-proof).
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */ /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
|
||||
* Safari (but not Chrome) clips the cancel button when the search input has
|
||||
* padding (and `textfield` appearance).
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9/10/11.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default vertical scrollbar in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't inherit the `font-weight` (applied by a rule above).
|
||||
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
|
||||
*/
|
||||
|
||||
optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Tables
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
||||
@ -1,228 +0,0 @@
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font: inherit;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
border: 0;
|
||||
}
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
body {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, serif;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: bold;
|
||||
color: #d5000d;
|
||||
}
|
||||
|
||||
header {
|
||||
padding-top: 35px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 48px;
|
||||
font-weight: bold;
|
||||
line-height: 1.2;
|
||||
color: #303030;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
|
||||
header h2 {
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
line-height: 1.3;
|
||||
color: #aaa;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
#downloads {
|
||||
display: none;
|
||||
}
|
||||
#main_content {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
margin-bottom: 30px;
|
||||
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal;
|
||||
font-size: 12px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
border: solid 1px #ddd;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul, ol, dl {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
/* COMMON STYLES */
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border: 1px solid #ebebeb;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
td {
|
||||
font-weight: 300;
|
||||
text-align: center;
|
||||
border: 1px solid #ebebeb;
|
||||
}
|
||||
|
||||
form {
|
||||
padding: 20px;
|
||||
background: #f2f2f2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* GENERAL ELEMENT TYPE STYLES */
|
||||
|
||||
h1 {
|
||||
font-size: 2.8em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 8px;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
color: #303030;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #d5000d;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #303030;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1em;
|
||||
color: #303030;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: .8em;
|
||||
color: #303030;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 20px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
p a {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: 0 0 0 30px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 1.6em;
|
||||
border-left: 10px solid #e9e9e9;
|
||||
}
|
||||
|
||||
ul li {
|
||||
padding-left: 20px;
|
||||
list-style-position: inside;
|
||||
list-style: disc;
|
||||
}
|
||||
|
||||
ol li {
|
||||
padding-left: 3px;
|
||||
list-style-position: inside;
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
dl dd {
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 30px;
|
||||
margin-top: 40px;
|
||||
font-size: 13px;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* MISC */
|
||||
.clearfix:after {
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
content: '.';
|
||||
}
|
||||
|
||||
.clearfix {display: inline-block;}
|
||||
* html .clearfix {height: 1%;}
|
||||
.clearfix {display: block;}
|
||||
@ -1,245 +0,0 @@
|
||||
* {
|
||||
box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #606c71; }
|
||||
|
||||
a {
|
||||
color: #1e6bb8;
|
||||
text-decoration: none; }
|
||||
a:hover {
|
||||
text-decoration: underline; }
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
margin-bottom: 1rem;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: 0.3rem;
|
||||
transition: color 0.2s, background-color 0.2s, border-color 0.2s; }
|
||||
.btn + .btn {
|
||||
margin-left: 1rem; }
|
||||
|
||||
.btn:hover {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
text-decoration: none;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
border-color: rgba(255, 255, 255, 0.3); }
|
||||
|
||||
@media screen and (min-width: 64em) {
|
||||
.btn {
|
||||
padding: 0.75rem 1rem; } }
|
||||
|
||||
@media screen and (min-width: 42em) and (max-width: 64em) {
|
||||
.btn {
|
||||
padding: 0.6rem 0.9rem;
|
||||
font-size: 0.9rem; } }
|
||||
|
||||
@media screen and (max-width: 42em) {
|
||||
.btn {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
font-size: 0.9rem; }
|
||||
.btn + .btn {
|
||||
margin-top: 1rem;
|
||||
margin-left: 0; } }
|
||||
|
||||
.page-header {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
background-color: #159957;
|
||||
background-image: linear-gradient(120deg, #155799, #159957); }
|
||||
|
||||
@media screen and (min-width: 64em) {
|
||||
.page-header {
|
||||
padding: 5rem 6rem; } }
|
||||
|
||||
@media screen and (min-width: 42em) and (max-width: 64em) {
|
||||
.page-header {
|
||||
padding: 3rem 4rem; } }
|
||||
|
||||
@media screen and (max-width: 42em) {
|
||||
.page-header {
|
||||
padding: 2rem 1rem; } }
|
||||
|
||||
.project-name {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.1rem; }
|
||||
|
||||
@media screen and (min-width: 64em) {
|
||||
.project-name {
|
||||
font-size: 3.25rem; } }
|
||||
|
||||
@media screen and (min-width: 42em) and (max-width: 64em) {
|
||||
.project-name {
|
||||
font-size: 2.25rem; } }
|
||||
|
||||
@media screen and (max-width: 42em) {
|
||||
.project-name {
|
||||
font-size: 1.75rem; } }
|
||||
|
||||
.project-tagline {
|
||||
margin-bottom: 2rem;
|
||||
font-weight: normal;
|
||||
opacity: 0.7; }
|
||||
|
||||
@media screen and (min-width: 64em) {
|
||||
.project-tagline {
|
||||
font-size: 1.25rem; } }
|
||||
|
||||
@media screen and (min-width: 42em) and (max-width: 64em) {
|
||||
.project-tagline {
|
||||
font-size: 1.15rem; } }
|
||||
|
||||
@media screen and (max-width: 42em) {
|
||||
.project-tagline {
|
||||
font-size: 1rem; } }
|
||||
|
||||
.main-content :first-child {
|
||||
margin-top: 0; }
|
||||
.main-content img {
|
||||
max-width: 100%; }
|
||||
.main-content h1, .main-content h2, .main-content h3, .main-content h4, .main-content h5, .main-content h6 {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: normal;
|
||||
color: #159957; }
|
||||
.main-content p {
|
||||
margin-bottom: 1em; }
|
||||
.main-content code {
|
||||
padding: 2px 4px;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
font-size: 0.9rem;
|
||||
color: #383e41;
|
||||
background-color: #f3f6fa;
|
||||
border-radius: 0.3rem; }
|
||||
.main-content pre {
|
||||
padding: 0.8rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
font: 1rem Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
color: #567482;
|
||||
word-wrap: normal;
|
||||
background-color: #f3f6fa;
|
||||
border: solid 1px #dce6f0;
|
||||
border-radius: 0.3rem; }
|
||||
.main-content pre > code {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
color: #567482;
|
||||
word-break: normal;
|
||||
white-space: pre;
|
||||
background: transparent;
|
||||
border: 0; }
|
||||
.main-content .highlight {
|
||||
margin-bottom: 1rem; }
|
||||
.main-content .highlight pre {
|
||||
margin-bottom: 0;
|
||||
word-break: normal; }
|
||||
.main-content .highlight pre, .main-content pre {
|
||||
padding: 0.8rem;
|
||||
overflow: auto;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.45;
|
||||
border-radius: 0.3rem; }
|
||||
.main-content pre code, .main-content pre tt {
|
||||
display: inline;
|
||||
max-width: initial;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: initial;
|
||||
line-height: inherit;
|
||||
word-wrap: normal;
|
||||
background-color: transparent;
|
||||
border: 0; }
|
||||
.main-content pre code:before, .main-content pre code:after, .main-content pre tt:before, .main-content pre tt:after {
|
||||
content: normal; }
|
||||
.main-content ul, .main-content ol {
|
||||
margin-top: 0; }
|
||||
.main-content blockquote {
|
||||
padding: 0 1rem;
|
||||
margin-left: 0;
|
||||
color: #819198;
|
||||
border-left: 0.3rem solid #dce6f0; }
|
||||
.main-content blockquote > :first-child {
|
||||
margin-top: 0; }
|
||||
.main-content blockquote > :last-child {
|
||||
margin-bottom: 0; }
|
||||
.main-content table {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
word-break: normal;
|
||||
word-break: keep-all; }
|
||||
.main-content table th {
|
||||
font-weight: bold; }
|
||||
.main-content table th, .main-content table td {
|
||||
padding: 0.5rem 1rem;
|
||||
border: 1px solid #e9ebec; }
|
||||
.main-content dl {
|
||||
padding: 0; }
|
||||
.main-content dl dt {
|
||||
padding: 0;
|
||||
margin-top: 1rem;
|
||||
font-size: 1rem;
|
||||
font-weight: bold; }
|
||||
.main-content dl dd {
|
||||
padding: 0;
|
||||
margin-bottom: 1rem; }
|
||||
.main-content hr {
|
||||
height: 2px;
|
||||
padding: 0;
|
||||
margin: 1rem 0;
|
||||
background-color: #eff0f1;
|
||||
border: 0; }
|
||||
|
||||
@media screen and (min-width: 64em) {
|
||||
.main-content {
|
||||
max-width: 64rem;
|
||||
padding: 2rem 6rem;
|
||||
margin: 0 auto;
|
||||
font-size: 1.1rem; } }
|
||||
|
||||
@media screen and (min-width: 42em) and (max-width: 64em) {
|
||||
.main-content {
|
||||
padding: 2rem 4rem;
|
||||
font-size: 1.1rem; } }
|
||||
|
||||
@media screen and (max-width: 42em) {
|
||||
.main-content {
|
||||
padding: 2rem 1rem;
|
||||
font-size: 1rem; } }
|
||||
|
||||
.site-footer {
|
||||
padding-top: 2rem;
|
||||
margin-top: 2rem;
|
||||
border-top: solid 1px #eff0f1; }
|
||||
|
||||
.site-footer-owner {
|
||||
display: block;
|
||||
font-weight: bold; }
|
||||
|
||||
.site-footer-credits {
|
||||
color: #819198; }
|
||||
|
||||
@media screen and (min-width: 64em) {
|
||||
.site-footer {
|
||||
font-size: 1rem; } }
|
||||
|
||||
@media screen and (min-width: 42em) and (max-width: 64em) {
|
||||
.site-footer {
|
||||
font-size: 1rem; } }
|
||||
|
||||
@media screen and (max-width: 42em) {
|
||||
.site-footer {
|
||||
font-size: 0.9rem; } }
|
||||
Loading…
x
Reference in New Issue
Block a user