local SpearheadEvents = require("classes.spearhead_events") local Util = require("classes.util.Util") ---@class RunwayBombingTracker : OnWeaponFiredListener ---@field trackedRunways table ---@field private _logger Logger local RunwayBombingTracker = {} RunwayBombingTracker.__index = RunwayBombingTracker --- Constructor --- @param logger Logger --- @return RunwayBombingTracker function RunwayBombingTracker.new(logger) local self = setmetatable({}, RunwayBombingTracker) self._logger = logger SpearheadEvents.AddWeaponFiredListener(self) return self end ---comment ---@param weapon Weapon function RunwayBombingTracker:OnWeaponFired(_, weapon, _) if weapon == nil then return end local desc = weapon:getDesc() local isTrackable = desc.category == Weapon.Category.BOMB or (desc.category == Weapon.Category.MISSILE and desc.missileCategory == Weapon.MissileCategory.CRUISE) if isTrackable == true then ---@type WeaponTrackingArgs local weaponTrackingArgs = { weapon = weapon, self = self } timer.scheduleFunction(RunwayBombingTracker.trackWeaponTask, weaponTrackingArgs, timer.getTime() + 1) end end function RunwayBombingTracker:RegisterRunway(runway, strikeMission) if not self.trackedRunways then self.trackedRunways = {} end if not self.trackedRunways[runway] then self.trackedRunways[runway] = strikeMission end end ---@class WeaponTrackingArgs ---@field weapon Weapon ---@field self RunwayBombingTracker ---@private ---@param time number ---@param weaponTrackingArgs WeaponTrackingArgs ---@return number? function RunwayBombingTracker.trackWeaponTask(weaponTrackingArgs, time) local weapon = weaponTrackingArgs.weapon local self = weaponTrackingArgs.self if not weapon or weapon:isExist() == false then return nil end local pos = weapon:getPoint() local velocity = weapon:getVelocity() local ground = land.getHeight({ x = pos.x, y = pos.z }) local MpS = velocity.y -- increase the speed to make sure you don't miss it. if MpS > 0 then return time + 3 end local nextInterval = (pos.y - ground) / math.abs(MpS) if nextInterval < 1 then -- Calculate the impact point of the weapon ---@type Vec2 local impactPoint = { x = pos.x + velocity.x * nextInterval, y = pos.z + velocity.z * nextInterval } self:OnWeaponImpact(weapon:getDesc(), impactPoint) return nil end if nextInterval > 5 then nextInterval = 5 end return time + (nextInterval /2) end ---comment ---@param weaponDesc table ---@param impactPoint Vec2 function RunwayBombingTracker:OnWeaponImpact(weaponDesc, impactPoint) self._logger:debug("RunwayBombingTracker:OnWeaponImpact") local warhead = weaponDesc.warhead --[[@as table]] local explosiveMass = (warhead.explosiveMass or warhead.shapedExplosiveMass) --[[@as number]] for _, strikeMission in pairs(self.trackedRunways) do local zone= strikeMission:GetRunwayZone() if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then strikeMission:RunwayHit(impactPoint, explosiveMass) end end end return RunwayBombingTracker