237 lines
9.0 KiB
Lua

-- ====================================================================================
-- TUM.OBJECTIVES - HANDLES THE MISSION OBJECTIVES
-- ====================================================================================
-- ====================================================================================
TUM.objectives = {}
do
local objectives = {}
local function updateObjectiveText(index)
if index < 1 or index > #objectives then return end
local taskDB = Library.tasks[objectives[index].taskID]
local suffix = ""
if DCSEx.table.contains(taskDB.flags, DCSEx.enums.taskFlag.MOVING) then
suffix = "\n(last position known to intel, target is moving)"
end
local text = "Objective "..objectives[index].name..":\n"..taskDB.description.short.." ("..TUM.objectives.getObjectiveProgress(index)..")"..suffix
trigger.action.setMarkupText(objectives[index].markerTextID, text)
end
function TUM.objectives.add()
local objective = TUM.objectivesMaker.create()
if not objective then
TUM.log("Failed to spawn a group for objective #"..tostring(#objectives + 1)..".", TUM.logger.logLevel.WARNING)
return false
end
table.insert(objectives, objective)
updateObjectiveText(#objectives)
return true
end
function TUM.objectives.getCount()
return #objectives
end
function TUM.objectives.getCompletedCount()
if #objectives == 0 then return 0 end
local count = 0
for i=1,#objectives do
if objectives[i].completed then count = count + 1 end
end
return count
end
function TUM.objectives.getCenter()
local point2 = { x = 0, y = 0 }
if #objectives == 0 then return point2 end
for _,o in ipairs(objectives) do
point2.x = point2.x + o.point2.x
point2.y = point2.y + o.point2.y
end
point2.x = point2.x / #objectives
point2.y = point2.y / #objectives
return point2
end
function TUM.objectives.getRadius()
if #objectives < 2 then return 10000 end -- Default to a 10km radius if no objectives or a single objective
local center = TUM.objectives.getCenter()
local radius = 0
for _,o in ipairs(objectives) do
local dist = DCSEx.math.getDistance2D(center, o.point2)
if dist > radius then radius = dist end
end
return radius
end
function TUM.objectives.getObjective(index)
if index < 1 or index > #objectives then return nil end
return DCSEx.table.deepCopy(objectives[index])
end
function TUM.objectives.getObjectiveProgress(index, doublePercentage)
doublePercentage = doublePercentage or false
if index < 1 or index > #objectives then return "" end
if TUM.DEBUG_MODE then
return tostring(#objectives[index].completedUnitsID).."/"..tostring(math.max(1, #objectives[index].unitsID))
else
local percentage = 0
if #objectives[index].unitsID > 0 then
percentage = math.floor((#objectives[index].completedUnitsID / math.max(1, #objectives[index].unitsID)) * 100.0)
end
if doublePercentage then
return tostring(percentage).."%%"
else
return tostring(percentage).."%"
end
end
end
function TUM.objectives.removeAll()
TUM.log("Removing all objectives...")
for _,o in ipairs(objectives) do
if o.groupID then
local g = DCSEx.world.getGroupByID(o.groupID)
if g then g:destroy() end
elseif o.unitsID then -- Some objects (such as static object) do not belong to a group, must be removed one by one
for _,id in ipairs(o.unitsID) do
local u = DCSEx.world.getUnitByID(id)
if u then
u:destroy()
else
local s = DCSEx.world.getStaticObjectByID(id)
if s then s:destroy() end
end
end
end
trigger.action.removeMark(o.markerID)
trigger.action.removeMark(o.markerTextID)
end
objectives = {}
end
function TUM.objectives.areAllCompleted()
if #objectives == 0 then return false end
return TUM.objectives.getCompletedCount() == TUM.objectives.getCount()
end
function TUM.objectives.getSceneryObjectObjective(sceneryObject)
if #objectives == 0 then return nil end
if not sceneryObject then return nil end
if Object.getCategory(sceneryObject) ~= Object.Category.SCENERY then return nil end
for i=1,#objectives do
if DCSEx.math.isSamePoint(sceneryObject:getPoint(), objectives[i].point3) then
return i
end
end
return nil
end
local function markObjectiveAsComplete(index)
if index < 1 or index > #objectives then return end -- Out of bounds
if objectives[index].completed then return end -- Objective already completed
objectives[index].completed = true
TUM.playerScore.awardCompletedObjective()
if TUM.objectives.areAllCompleted() then
TUM.mission.checkMissionStatus()
else
TUM.radio.playForCoalition(TUM.settings.getPlayerCoalition(), "commandObjectiveComplete", { objectives[index].name }, "Command", true)
end
DCSEx.dcs.outPicture("Pic-ObjectiveComplete.png", 5, true, 0, 1, 1, 25, 1)
trigger.action.outSound("UI-MissionEnd.ogg")
end
local function onObjectiveEvent(index, event)
if not event.initiator then return end
if index < 1 or index > #objectives then return end -- Out of bounds
if objectives[index].completed then return end -- Objective already completed
local completionEvent = Library.tasks[objectives[index].taskID].completionEvent
if completionEvent == DCSEx.enums.taskEvent.DAMAGE then
if event.id ~= world.event.S_EVENT_DEAD and event.id ~= world.event.S_EVENT_HIT and event.id ~= world.event.S_EVENT_UNIT_LOST then return end
elseif completionEvent == DCSEx.enums.taskEvent.DESTROY then
if event.id ~= world.event.S_EVENT_DEAD and event.id ~= world.event.S_EVENT_UNIT_LOST then return end
elseif completionEvent == DCSEx.enums.taskEvent.LAND then
if event.id ~= world.event.S_EVENT_LAND then return end
if Object.getCategory(event.initiator) ~= Object.Category.UNIT then return end
if event.initiator:getDesc().category ~= Unit.Category.HELICOPTER then return end
if event.initiator:getCoalition() ~= TUM.settings.getPlayerCoalition() then return end
if DCSEx.math.getDistance2D(DCSEx.math.vec3ToVec2(event.initiator:getPoint()), objectives[index].point2) > 500 then return end -- Too far from objective
-- Remove target group if it exists (to simulate it was picked up/captured)
if objectives[index].groupID then
local targetGroup = DCSEx.world.getGroupByID(objectives[index].groupID)
if targetGroup then
targetGroup:destroy()
end
end
timer.scheduleFunction(markObjectiveAsComplete, index, timer.getTime() + 3)
updateObjectiveText(index)
return
end
if objectives[index].isAirbaseTarget then
if Object.getCategory(event.initiator) == Object.Category.BASE then
if DCSEx.math.isSamePoint(event.initiator:getPoint(), objectives[index].point3) then
timer.scheduleFunction(markObjectiveAsComplete, index, timer.getTime() + 3)
end
end
elseif objectives[index].isSceneryTarget then
if Object.getCategory(event.initiator) == Object.Category.SCENERY then
if DCSEx.math.isSamePoint(event.initiator:getPoint(), objectives[index].point3) then
timer.scheduleFunction(markObjectiveAsComplete, index, timer.getTime() + 3)
end
end
else
if Object.getCategory(event.initiator) == Object.Category.UNIT or Object.getCategory(event.initiator) == Object.Category.STATIC then
local unitID = DCSEx.dcs.getObjectIDAsNumber(event.initiator)
if DCSEx.table.contains(objectives[index].completedUnitsID, unitID) then return end
if not DCSEx.table.contains(objectives[index].unitsID, unitID) then return end
table.insert(objectives[index].completedUnitsID, unitID)
if #objectives[index].completedUnitsID == #objectives[index].unitsID then
timer.scheduleFunction(markObjectiveAsComplete, index, timer.getTime() + 3)
end
end
end
updateObjectiveText(index)
end
function TUM.objectives.onEvent(event)
for i,_ in ipairs(objectives) do
onObjectiveEvent(i, event)
end
end
end