Version 1.2.6

TaxiPolice 1.0.0
Small bug fixes
This commit is contained in:
Christian Franz 2023-03-30 08:20:18 +02:00
parent 1939f376c5
commit 52985a2d4c
8 changed files with 186 additions and 70 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
cfxSSBClient = {}
cfxSSBClient.version = "3.0.0"
cfxSSBClient.version = "3.0.1"
cfxSSBClient.verbose = false
cfxSSBClient.singleUse = false -- set to true to block crashed planes
-- NOTE: singleUse (true) requires SSB to disable immediate respawn after kick
@ -47,6 +47,7 @@ Version History
- open?
- close?
- also persists closed airfield list
3.0.1 - ability to detect if an airfield doesn't exist (late activate)
@ -238,38 +239,46 @@ function cfxSSBClient.setSlotAccessForGroup(theGroup)
-- and leave it as it is. Nothing to do at all now
elseif theMatchingAirfield ~= nil then
local blockState = cfxSSBClient.enabledFlagValue -- we default to ALLOW the block
local comment = "available"
-- we have found a plane that is tied to an airfield
-- so this group will receive a block/unblock
-- we always set all block/unblock every time
-- note: since caching, above guard not needed
local airFieldSide = theMatchingAirfield:getCoalition()
local groupCoalition = theGroup.coaNum
local blockState = cfxSSBClient.enabledFlagValue -- we default to ALLOW the block
local comment = "available"
-- see if airfield is closed
local afName = theMatchingAirfield:getName()
if cfxSSBClient.closedAirfields[afName] then
-- airfield is closed. no take-offs
-- see if airfield currently exist (might be dead or late activate)
if not Object.isExist(theMatchingAirfield) then
-- airfield does not exits yet/any more
blockState = cfxSSBClient.disabledFlagValue
comment = "!closed airfield!"
end
comment = "!inactive airfield!"
else
local airFieldSide = theMatchingAirfield:getCoalition()
local groupCoalition = theGroup.coaNum
-- on top of that, check coalitions
if groupCoalition ~= airFieldSide then
-- we have a problem. sides don't match
if airFieldSide == 3
or (cfxSSBClient.allowNeutralFields and airFieldSide == 0)
then
-- all is well, airfield is contested or neutral and
-- we allow this plane to spawn here
else
-- DISALLOWED!!!!
-- see if airfield is closed
local afName = theMatchingAirfield:getName()
if cfxSSBClient.closedAirfields[afName] then
-- airfield is closed. no take-offs
blockState = cfxSSBClient.disabledFlagValue
comment = "!!!BLOCKED!!!"
comment = "!closed airfield!"
end
-- on top of that, check coalitions
if groupCoalition ~= airFieldSide then
-- we have a problem. sides don't match
if airFieldSide == 3
or (cfxSSBClient.allowNeutralFields and airFieldSide == 0)
then
-- all is well, airfield is contested or neutral and
-- we allow this plane to spawn here
else
-- DISALLOWED!!!!
blockState = cfxSSBClient.disabledFlagValue
comment = "!!!BLOCKED!!!"
end
end
end
-- set the ssb flag for this group so the server can see it
-- now set the ssb flag for this group so the server can see it
if cfxSSBClient.verbose then
local lastState = trigger.misc.getUserFlag(theName)
if lastState ~= blockState then

View File

@ -1,5 +1,5 @@
csarManager = {}
csarManager.version = "2.2.3"
csarManager.version = "2.2.4"
csarManager.verbose = false
csarManager.ups = 1
@ -60,6 +60,8 @@ csarManager.ups = 1
- directions to closest safe zone
- CSARBASE attribute now carries coalition
- deprecated coalition attribute
- 2.2.4 - CSAR attribute value defaults name
- start? attribute for CSAR as startCSAR? synonym
INTEGRATES AUTOMATICALLY WITH playerScore IF INSTALLED
@ -1273,18 +1275,18 @@ end
function csarManager.readCSARZone(theZone)
-- zones have attribute "CSAR"
-- gather data, and then create a mission from this
local mName = cfxZones.getStringFromZoneProperty(theZone, "CSAR", "Lt. Unknown")
if mName == "" then mName = theZone.name end
local theSide = cfxZones.getCoalitionFromZoneProperty(theZone, "coalition", 0)
theZone.csarSide = theSide
theZone.csarName = cfxZones.getStringFromZoneProperty(theZone, "name", "<none>")
theZone.csarName = theZone.name -- default CSAR Name
if cfxZones.hasProperty(theZone, "csarName") then
theZone.csarName = mName -- now deprecating name attributes
if cfxZones.hasProperty(theZone, "name") then
theZone.csarName = cfxZones.getStringFromZoneProperty(theZone, "name", "<none>")
elseif cfxZones.hasProperty(theZone, "csarName") then
theZone.csarName = cfxZones.getStringFromZoneProperty(theZone, "csarName", "<none>")
end
if cfxZones.hasProperty(theZone, "pilotName") then
elseif cfxZones.hasProperty(theZone, "pilotName") then
theZone.csarName = cfxZones.getStringFromZoneProperty(theZone, "pilotName", "<none>")
end
if cfxZones.hasProperty(theZone, "victimName") then
elseif cfxZones.hasProperty(theZone, "victimName") then
theZone.csarName = cfxZones.getStringFromZoneProperty(theZone, "victimName", "<none>")
end
@ -1302,6 +1304,11 @@ function csarManager.readCSARZone(theZone)
theZone.lastCSARVal = cfxZones.getFlagValue(theZone.startCSAR, theZone)
end
if cfxZones.hasProperty(theZone, "start?") then
theZone.startCSAR = cfxZones.getStringFromZoneProperty(theZone, "start?", "*none")
theZone.lastCSARVal = cfxZones.getFlagValue(theZone.startCSAR, theZone)
end
if cfxZones.hasProperty(theZone, "startCSAR?") then
theZone.startCSAR = cfxZones.getStringFromZoneProperty(theZone, "startCSAR?", "*none")
theZone.lastCSARVal = cfxZones.getFlagValue(theZone.startCSAR, theZone)
@ -1479,29 +1486,18 @@ end
improvements
- need to stay on ground for x seconds to load troops
- hot lz
- hover recover
- limit on troops aboard for transport
- delay for drop-off
- csar when: always, only on eject,
- repair o'clock
- nearest csarBase
- red/blue csarbases
- weight
- compatibility: side/owner - make sure it is compatible
with FARP, and landing on a FARP with opposition ownership
will not disembark
- suppress multi smoke
- when unloading one by menu, update weight!!!
-- allow any airfied to be csarsafe by default, no longer *requires* csarbase
-- allow neutral pick-up
-- allow any airfied to be csarsafe by default, no longer requires csarbase
-- get vector to closes csarbase
-- support quad zones and optionally non-random placement
--]]--

View File

@ -1,5 +1,5 @@
delicates = {}
delicates.version = "1.1.1"
delicates.version = "1.1.2"
delicates.verbose = false
delicates.ups = 1
delicates.requiredLibs = {
@ -18,7 +18,7 @@ delicates.inventory = {}
- safetyMargin - safety margin. defaults to 10%
1.1.1 - addGroupToInventoryForZone
- verbose for zone will show update event from useDelicates
1.1.2 - fixed uncaught delayed explosion for nil object
--]]--
function delicates.adddDelicates(theZone)
table.insert(delicates.theDelicates, theZone)
@ -194,8 +194,21 @@ function delicates.scheduledBlow(args)
theObject = StaticObject.getByName(oName)
else
-- can't handle at the moment
if delicates.verbose then
trigger.action.outText("+++Deli: can't handle delicate explosion for object cat <" .. desc.cat .. ">, name <" .. desc.oName .. ">", 30)
end
return
end
-- now, the object might have been removed by now. catch this before we proceed
if not theObject then
if delicates.verbose then
trigger.action.outText("+++Deli: NIL delicate for object blow at cat <" .. desc.cat .. ">, name <" .. desc.oName .. ">", 30)
end
return
end
local theZone = desc.theZone
local p = theObject:getPoint()
local power = desc.theZone.power

View File

@ -1,5 +1,5 @@
taxiPolice = {}
taxiPolice.version = "0.0.0"
taxiPolice.version = "1.0.0"
taxiPolice.verbose = true
taxiPolice.ups = 1 -- checks per second
taxiPolice.requiredLibs = {
@ -7,32 +7,32 @@ taxiPolice.requiredLibs = {
"cfxZones", -- Zones, of course
}
--[[--
-- ensure that a player doesn't overspeed on taxiways. uses speedLimit and violateDuration to determine if to fine
-- create runway polys here: https://wiki.hoggitworld.com/view/DCS_func_getRunways
-- works as follows:
-- when a player's plane is not inAir, they are monitored.
-- when on a runway or too far from airfield (only airfields are monitored) monitoring ends
-- when monitored and overspeeding, they first receive a warning, and after n warnings they receive retribution
Version History
1.0.0 - Initial version
--]]--
taxiPolice.speedLimit = 14 -- m/s . 14 m/s = 50 km/h, 10 m/s = 36 kmh
taxiPolice.triggerTime = 3 -- seconds until we register a speeding violation
taxiPolice.rwyLeeway = 5 -- meters on each side
taxiPolice.rwyExtend = 500 -- meters in front and at end
taxiPolice.airfieldMaxDist = 3000 -- radius around airfield in which we operate
taxiPolice.runways = {} -- indexed by airbase name, then by rwName
-- if nil, that base is not policed
taxiPolice.suspects = {} -- units that are currently behaving naughty
taxiPolice.tickets = {} -- number of warnings per player
taxiPolice.maxTickets = 3 -- number of tickes without retribution
taxiPolice.lastMessageTo = {} -- used to suppress messages if too soon
function taxiPolice.buildRunways()
local bases = world.getAirbases()
local mId = 0
for idb, aBase in pairs (bases) do -- i = 1, #base do
local name = aBase:getName()
local rny = aBase:getRunways()
if rny then
-- Note that Airbase.Category values are not obtained by calling airbase:getCategory() - that calls Object.getCategory(airbase) and will always return the value Object.Category.BASE. Instead you need to use airbase:getDesc().category to obtain the Airbase.Category!
local cat = aBase:getDesc().category
if rny and (cat == 0) then
local runways = {}
for idx, rwy in pairs(rny) do -- j = 1, #rny do
-- calcualte quad that encloses taxiway
@ -71,6 +71,7 @@ function taxiPolice.buildRunways()
taxiPolice.runways[name] = runways
if taxiPolice.verbose then
-- mark center of airbase in a red 200x200 square
local points = {}
local pStart = aBase:getPoint()
local pEnd = aBase:getPoint()
@ -85,6 +86,10 @@ function taxiPolice.buildRunways()
mId = mId + 1
trigger.action.quadToAll(-1, mId, points[1], points[2], points[3], points[4], {1, 0, 0, 1}, {1, 0, 0, .5}, 3)
end
else
if taxiPolice.verbose then
trigger.action.outText("No runways proccing for base <" .. name .. ">, cat = <" .. cat .. ">", 30)
end
end
end
end
@ -108,6 +113,10 @@ end
function taxiPolice.checkUnit(theUnit, allAirfields)
if not theUnit.getPlayerName then return end
local theGroup = theUnit:getGroup()
local cat = theGroup:getCategory()
if cat ~= 0 then return end -- not a fixed wing, disregard
local player = theUnit:getPlayerName()
if not player then return end
@ -131,14 +140,13 @@ function taxiPolice.checkUnit(theUnit, allAirfields)
-- check if we are on a runway
local myRunways = taxiPolice.runways[base:getName()]
if not myRunways then
-- this base is turned off
--trigger.action.outText("unable to find raunways for <" .. base:getName() .. ">", 30)
-- this base is not policed
taxiPolice.suspects[player] = nil
return
end
for rwName, aRunway in pairs(myRunways) do
if cfxZones.isPointInsidePoly(p, aRunway) then
--trigger.action.outText("<" .. theUnit:getName() .. "> is on RWY <" .. rwName .. ">", 30)
taxiPolice.suspects[player] = nil -- remove watched status
return
end
@ -184,10 +192,29 @@ end
---
--- UPDATE
---
function taxiPolice.update() -- every second
function taxiPolice.update() -- every second/ups
-- schedule next invocation
timer.scheduleFunction(taxiPolice.update, {}, timer.getTime() + 1/taxiPolice.ups)
--trigger.action.outText("onpatrol flag is " .. taxiPolice.onPatrol .. " with val = " .. trigger.misc.getUserFlag(taxiPolice.onPatrol), 30)
-- see if this has been turned on or offDuty
if taxiPolice.onPatrol and
cfxZones.testZoneFlag(taxiPolice, taxiPolice.onPatrol, "change", "lastOnPatrol") then
taxiPolice.active = true
local knots = math.floor(taxiPolice.speedLimit * 1.94384)
local kmh = math.floor(taxiPolice.speedLimit * 3.6)
trigger.action.outText("NOTAM:\ntarmac and taxiway speed limit of " .. knots .. " knots/" .. kmh .. " km/h is enforced on all air fields!", 30)
end
if taxiPolice.offDuty and
cfxZones.testZoneFlag(taxiPolice, taxiPolice.offDuty, "change", "lastOffDuty") then
taxiPolice.active = false
trigger.action.outText("NOTAM:\ntarmac and taxiway speed limit rescinded. Taxi responsibly!", 30)
end
if not taxiPolice.active then return end
local allAirfields = dcsCommon.getAirbasesWhoseNameContains("*", 0) -- all fixed bases, no FARP nor ships. Pre-collect
-- check all player units
@ -203,6 +230,55 @@ function taxiPolice.update() -- every second
end
--
-- ONEVENT
--
function taxiPolice:onEvent(theEvent)
--trigger.action.outText("txP event: <" .. theEvent.id .. ">", 30)
if not taxiPolice.greetings then return end -- no warnings
if not taxiPolice.active then return end -- no policing active
local ID = theEvent.id
if not ID then return end
if (ID ~= 15) and (ID ~= 4) then return end -- not birth nor land
local theUnit = theEvent.initiator
if not theUnit then return end
if theUnit:inAir() then return end
-- make sure it's a plane. Helos are ignored
local theGroup = theUnit:getGroup()
local cat = theGroup:getCategory()
if cat ~= 0 then return end
if not theUnit.getPlayerName then return end
local pName = theUnit:getPlayerName()
if not pName then return end
local base, dist = dcsCommon.getClosestAirbaseTo(theUnit:getPoint(), 0)
local bName = base:getName()
if dist > taxiPolice.airfieldMaxDist then return end
local UID = theUnit:getID()
-- check if this airfield is exempt
local rwys = taxiPolice.runways[bName]
local now = timer.getTime()
local last = taxiPolice.lastMessageTo[pName] -- remember timestamp
if not last then last = 0 end
local tdiff = now - last
-- make sure palyer receives only one such notice within 15 seconds
-- but always when now = 0 (mission startup)
if (now ~= 0) and (tdiff < 15) then return end -- to soon
taxiPolice.lastMessageTo[pName] = now
if not rwys then
trigger.action.outTextForUnit(UID, "Welcome to " .. bName .. ", " .. pName .. "!\nAlthough a general taxiway speed limit is in effect, it does not apply here.", 30)
return
end
local knots = math.floor(taxiPolice.speedLimit * 1.94384)
local kmh = math.floor(taxiPolice.speedLimit * 3.6)
trigger.action.outTextForUnit(UID, "Welcome to " .. bName .. ", " .. pName .. "!\nBe advised: a speed limit of " .. knots .. " knots/" .. kmh .. " km/h is enforced on tarmac and taxiways.", 30)
end
--
-- START
--
@ -232,6 +308,8 @@ function taxiPolice.readConfigZone()
trigger.action.outText("+++txPol: no config zone!", 30)
end
end
taxiPolice.name = "taxiPoliceConfig" -- cfxZones compatibility
taxiPolice.verbose = theZone.verbose
taxiPolice.speedLimit = cfxZones.getNumberFromZoneProperty(theZone, "speedLimit", 14) -- 14 -- m/s. 14 m/s = 50 km/h, 10 m/s = 36 kmh
@ -240,7 +318,19 @@ function taxiPolice.readConfigZone()
taxiPolice.rwyExtend = cfxZones.getNumberFromZoneProperty(theZone, "extend", 500) --500 -- meters in front and at end
taxiPolice.airfieldMaxDist = cfxZones.getNumberFromZoneProperty(theZone, "radius", 3000) -- 3000 -- radius around airfield in which we operate
taxiPolice.maxTickets = cfxZones.getNumberFromZoneProperty(theZone, "maxTickets", 3) -- 3
taxiPolice.active = cfxZones.getBoolFromZoneProperty(theZone, "active", true)
taxiPolice.greetings = cfxZones.getBoolFromZoneProperty(theZone, "greetings", true)
if cfxZones.hasProperty(theZone, "onPatrol") then
taxiPolice.onPatrol = cfxZones.getStringFromZoneProperty(theZone, "onPatrol", "<none>")
taxiPolice.lastOnPatrol = cfxZones.getFlagValue(taxiPolice.onPatrol, taxiPolice)
end
if cfxZones.hasProperty(theZone, "offDuty") then
taxiPolice.offDuty = cfxZones.getStringFromZoneProperty(theZone, "offDuty", "<none>")
taxiPolice.lastOffDuty = cfxZones.getFlagValue(taxiPolice.offDuty, taxiPolice)
end
end
function taxiPolice.start()
@ -265,6 +355,9 @@ function taxiPolice.start()
-- start update
taxiPolice.update()
-- install envent handler to greet pilots on airfields
world.addEventHandler(taxiPolice)
-- say hi!
trigger.action.outText("cfx taxiPolice v" .. taxiPolice.version .. " started.", 30)
return true
@ -276,5 +369,10 @@ if not taxiPolice.start() then
taxiPolice = nil
end
--[[--
Possible improvements
- other sanctions on violations like kick, ban etc
- call nearest airfield for open rwys (needs 'commandForUnit' first
- ability to persist offenders
--]]--

Binary file not shown.