TARGET Scenery & PyBridge

This commit is contained in:
Frank
2026-08-20 18:45:48 +02:00
parent 51bd6150e8
commit f5aef8edb9
4 changed files with 136 additions and 5 deletions
+14 -3
View File
@@ -952,9 +952,19 @@ end
function TARGET:OnEventUnitDeadOrLost(EventData)
local Name=EventData and EventData.IniUnitName or nil
local isElement=false
local isCasualty=nil
if Name then
isElement=self:IsElement(Name)
isCasualty=self:IsCasualty(Name)
printf("Dead/unit lost event for %s: isElement=%s, isCascualty=%s", tostring(Name), tostring(isElement), tostring(isCasualty))
else
self:E(self.lid..string.format("ERROR: Could not get name of Dead Unit"))
end
-- Check that this is the right group.
if self:IsElement(Name) and not self:IsCasualty(Name) then
if isElement and not isCasualty then
-- Debug info.
self:T(self.lid..string.format("EVENT ID=%d: Unit %s dead or lost!", EventData.id, tostring(Name)))
@@ -1081,6 +1091,7 @@ function TARGET:_AddObject(Object)
target.N0=target.N0+1
printf("FF target adding element %s", tostring(target.Name))
table.insert(self.elements, target.Name)
elseif Object:IsInstanceOf("AIRBASE") then
@@ -1957,7 +1968,7 @@ function TARGET:GetTargetByName(ObjectName)
for _,_target in pairs(self.targets) do
local target=_target --#TARGET.Object
if ObjectName==target.Name then
if tostring(ObjectName)==tostring(target.Name) then
return target
end
end
@@ -2165,7 +2176,7 @@ function TARGET:IsElement(Name)
end
for _,name in pairs(self.elements) do
if name==Name then
if tostring(name)==tostring(Name) then
return true
end
end
@@ -309,7 +309,7 @@ function MOOSE_BRIDGE:_ResolveCoordinateFromInputs(inputs)
local longitude = inputs.longitude ~= nil and tonumber(inputs.longitude) or nil
if latitude and longitude then
if not coord or not coord.LLtoLO then return nil, "coord.LLtoLO is not available" end
local point = coord.LLtoLO({lat=latitude, lon=longitude, alt=0})
local point = coord.LLtoLO(latitude, longitude, 0)
if point then
x = tonumber(point.x)
z = tonumber(point.z)
@@ -441,6 +441,47 @@ function MOOSE_BRIDGE:_ResolveCoordinateAuftragTarget(inputs)
return self:_ResolveCoordinateFromInputs(inputs)
end
function MOOSE_BRIDGE:_ResolveSceneryAuftragTarget(inputs)
local prefix, name = bridge_split_object_id(inputs.target_id)
if prefix ~= "SCENERY" or not name then return nil, "Invalid SCENERY target id" end
if not SCENERY or not SCENERY.Register then return nil, "MOOSE SCENERY wrapper is not available" end
local scenery_id = tonumber(name) or name
if SCENERY.FindByID then
local existing = SCENERY:FindByID(scenery_id)
local dcs_object = existing and existing.GetDCSObject and existing:GetDCSObject() or nil
if dcs_object then return existing, nil end
end
local coordinate, coordinate_err = self:_ResolveCoordinateFromInputs(inputs)
if not coordinate then return nil, coordinate_err end
if not world or not world.searchObjects or not world.VolumeType then
return nil, "DCS world.searchObjects is not available"
end
if not Object or not Object.Category or Object.Category.SCENERY == nil then
return nil, "DCS scenery object category is not available"
end
local center = coordinate.GetVec3 and coordinate:GetVec3() or nil
if not center then return nil, "SCENERY target coordinate is unavailable" end
local found = nil
local volume = {id=world.VolumeType.SPHERE, params={point=center, radius=150}}
world.searchObjects(Object.Category.SCENERY, volume, function(object)
local object_name = self:_DcsCall(object, "getName")
if object_name ~= nil and bridge_safe_tostring(object_name) == name then
found = object
return false
end
return true
end)
if not found then return nil, "SCENERY target is not live-queryable: " .. name end
local scenery = SCENERY:Register(name, found)
local dcs_object = scenery and scenery.GetDCSObject and scenery:GetDCSObject() or nil
if not dcs_object then return nil, "SCENERY wrapper has no DCS object: " .. name end
return scenery, nil
end
function MOOSE_BRIDGE:_CommonAuftragCommandInputs(cmd)
local p = self:_CommandParams(cmd)
local legacy_params = type(p.params) == "table" and p.params or {}
@@ -644,6 +685,22 @@ function MOOSE_BRIDGE:_ResolveArtyTarget(inputs)
end
function MOOSE_BRIDGE:_ResolveStrikeTarget(inputs)
local prefix = inputs.target_id and bridge_split_object_id(inputs.target_id) or nil
if prefix == "SCENERY" then
local scenery, scenery_err = self:_ResolveSceneryAuftragTarget(inputs)
if scenery then
inputs.target_resolution = "scenery_object"
return scenery, nil
end
local coordinate, coordinate_err = self:_ResolveCoordinateFromInputs(inputs)
if coordinate then
inputs.target_resolution = "coordinate_fallback"
inputs.target_resolution_error = scenery_err
return coordinate, nil
end
return nil, scenery_err or coordinate_err
end
inputs.target_resolution = "coordinate"
return self:_ResolveCoordinateAuftragTarget(inputs)
end
@@ -1053,6 +1110,8 @@ function MOOSE_BRIDGE:_BuildAuftragCommandResult(action, auftrag, inputs)
required_assets_max=inputs.required_assets_max,
weapon_type=inputs.weapon_type,
target=inputs.target_id,
target_resolution=inputs.target_resolution,
target_resolution_error=inputs.target_resolution_error,
opszone=inputs.opszone_id,
capture_coalition=inputs.capture_coalition,
stay_in_zone_time_s=inputs.stay_in_zone_time_s,
@@ -85,6 +85,21 @@ function MOOSE_BRIDGE:_StartDcsEventForwarding()
self.DcsRegisteredEvents[#self.DcsRegisteredEvents + 1] = EVENTS.Kill
self:_Log("DCS Kill event forwarding enabled")
end
if bridge_event_available(EVENTS.MarkAdded) then
self:HandleEvent(EVENTS.MarkAdded)
self.DcsRegisteredEvents[#self.DcsRegisteredEvents + 1] = EVENTS.MarkAdded
self:_Log("DCS MarkAdded event forwarding enabled")
end
if bridge_event_available(EVENTS.MarkChange) then
self:HandleEvent(EVENTS.MarkChange)
self.DcsRegisteredEvents[#self.DcsRegisteredEvents + 1] = EVENTS.MarkChange
self:_Log("DCS MarkChange event forwarding enabled")
end
if bridge_event_available(EVENTS.MarkRemoved) then
self:HandleEvent(EVENTS.MarkRemoved)
self.DcsRegisteredEvents[#self.DcsRegisteredEvents + 1] = EVENTS.MarkRemoved
self:_Log("DCS MarkRemoved event forwarding enabled")
end
if bridge_event_available(EVENTS.MissionEnd) then
self:HandleEvent(EVENTS.MissionEnd)
self.DcsRegisteredEvents[#self.DcsRegisteredEvents + 1] = EVENTS.MissionEnd
@@ -297,6 +312,49 @@ function MOOSE_BRIDGE:OnEventKill(EventData)
end
end
--- Forward one DCS F10 map-marker event without interpreting its text.
-- Marker commands remain a Python concern so the Lua bridge stays semantic
-- and does not couple mission scripts to verification workflows.
function MOOSE_BRIDGE:_ForwardMapMarker(EventData, event_name, dcs_event_name)
local ok, err = pcall(function()
if type(EventData) ~= "table" then error("Map marker event data is missing") end
local marker_id = EventData.MarkID or EventData.idx
if marker_id == nil then error("Map marker event has no marker ID") end
local point = EventData.MarkVec3 or EventData.pos
local coordinates = point and self:_CoordinatesForPoint(point, "ll") or {}
self:SendEvent(event_name, {
dcs_event_id=EventData.id,
dcs_event_name=dcs_event_name,
dcs_event_time=EventData.time,
marker_id=marker_id,
text=EventData.MarkText or EventData.text,
coalition=self:_CoalitionToName(EventData.MarkCoalition or EventData.coalition),
group_id=EventData.MarkGroupID or EventData.groupID,
player_name=EventData.PlayerName,
x=coordinates.x,
y=coordinates.y,
z=coordinates.z,
latitude=coordinates.latitude,
longitude=coordinates.longitude,
})
end)
if not ok then
self:_Log("Failed to forward " .. tostring(dcs_event_name) .. " event: " .. tostring(err))
end
end
function MOOSE_BRIDGE:OnEventMarkAdded(EventData)
self:_ForwardMapMarker(EventData, "map.marker.added", "S_EVENT_MARK_ADDED")
end
function MOOSE_BRIDGE:OnEventMarkChange(EventData)
self:_ForwardMapMarker(EventData, "map.marker.changed", "S_EVENT_MARK_CHANGE")
end
function MOOSE_BRIDGE:OnEventMarkRemoved(EventData)
self:_ForwardMapMarker(EventData, "map.marker.removed", "S_EVENT_MARK_REMOVED")
end
--- Forward DCS S_EVENT_MISSION_END as the authoritative Python session boundary.
-- Flush immediately because normal bridge scheduling stops with the mission.
-- @param Core.Event#EVENTDATA EventData MOOSE-normalized DCS event data.
+4 -1
View File
@@ -60,7 +60,10 @@ function SCENERY:Register( SceneryName, SceneryObject, SceneryZone )
end
if _SCENERY[ID] then return _SCENERY[ID] end
if _SCENERY[ID] then
BASE:I("Returning DCS scenery object found in _SCENERY table with ID")
return _SCENERY[ID]
end
local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) )