mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
referencing the original upload in Discord here: https://discord.com/channels/595702951800995872/768226890158702654/809571449979142174 and wheelyjoe's github repository here: https://github.com/wheelyjoe/DCS-Scripts "Improves splash damage modelling by pulling weapon warhead info (where available) and using this to create explosions (only way to apply damage) to units in more sensible range." Makes using non-precision weaponry actually viable for ground targets.
229 lines
7.3 KiB
Lua
229 lines
7.3 KiB
Lua
--[[
|
|
|
|
2 October 2020
|
|
FrozenDroid:
|
|
- Added error handling to all event handler and scheduled functions. Lua script errors can no longer bring the server down.
|
|
- Added some extra checks to which weapons to handle, make sure they actually have a warhead (how come S-8KOM's don't have a warhead field...?)
|
|
28 October 2020
|
|
FrozenDroid:
|
|
- Uncommented error logging, actually made it an error log which shows a message box on error.
|
|
- Fixed the too restrictive weapon filter (took out the HE warhead requirement)
|
|
--]]
|
|
|
|
|
|
local weaponDamageEnable = 1
|
|
local killRangeMultiplier = 0.3
|
|
local staticDamageRangeMultiplier = 0.1
|
|
local stunRangeMultiplier = 1.0
|
|
|
|
local suppressedGroups = {}
|
|
local tracked_weapons = {}
|
|
local USearchArray = {}
|
|
WpnHandler = {}
|
|
|
|
local function getDistance(point1, point2)
|
|
|
|
local x1 = point1.x
|
|
local y1 = point1.y
|
|
local z1 = point1.z
|
|
local x2 = point2.x
|
|
local y2 = point2.y
|
|
local z2 = point2.z
|
|
local dX = math.abs(x1-x2)
|
|
local dZ = math.abs(z1-z2)
|
|
local distance = math.sqrt(dX*dX + dZ*dZ)
|
|
|
|
return distance
|
|
|
|
end
|
|
|
|
local function getDistance3D(point1, point2)
|
|
|
|
local x1 = point1.x
|
|
local y1 = point1.y
|
|
local z1 = point1.z
|
|
local x2 = point2.x
|
|
local y2 = point2.y
|
|
local z2 = point2.z
|
|
|
|
local dX = math.abs(x1-x2)
|
|
local dY = math.abs(y1-y2)
|
|
local dZ = math.abs(z1-z2)
|
|
local distance = math.sqrt(dX*dX + dZ*dZ + dY*dY)
|
|
|
|
return distance
|
|
|
|
end
|
|
|
|
local function suppress(suppArray)
|
|
|
|
suppressedGroups[suppArray[1]:getName()] = {["SuppGroup"] = suppArray[1], ["SuppTime"] = suppArray[2]}
|
|
if suppArray[1]:getController() then
|
|
suppArray[1]:getController():setOnOff(false)
|
|
-- env.info("Group: "..suppArray[1]:getName().." suppressed")
|
|
end
|
|
|
|
end
|
|
|
|
local function unSuppress(unSuppGroup)
|
|
-- env.info("In unSuppress")
|
|
if unSuppGroup:isExist() and unSuppGroup:getController() then
|
|
unSuppGroup:getController():setOnOff(true)
|
|
-- env.info("Got controller")
|
|
-- env.info("Suppressed group removed from table")
|
|
suppressedGroups[unSuppGroup:getName()] = nil
|
|
end
|
|
end
|
|
|
|
local function ifFoundS(foundItem, impactPoint)
|
|
-- trigger.action.outText("Found Static", 10)
|
|
-- env.info("Found static in kill range")
|
|
local point1 = foundItem:getPoint()
|
|
point1.y = point1.y + 2
|
|
local point2 = impactPoint
|
|
point2.y = point2.y + 2
|
|
if land.isVisible(point1, point2) == true then
|
|
-- env.info("Static"..foundItem:getID().. "Destroyed by script")
|
|
trigger.action.explosion(point1, 5)
|
|
end
|
|
end
|
|
|
|
local function ifFoundU(foundItem, USearchArray)
|
|
|
|
-- env.info("Found Unit")
|
|
local point1 = foundItem:getPoint()
|
|
-- env.info("Got point")
|
|
point1.y = point1.y + 5
|
|
local point2 = USearchArray.point
|
|
point2.y = point2.y + 5
|
|
if land.isVisible(point1, point2) == true then
|
|
-- env.info("is visible LOS")
|
|
local distanceFrom = getDistance(point1, point2)
|
|
-- env.info("got distance: "..distanceFrom)
|
|
if distanceFrom < USearchArray.exMass*killRangeMultiplier then
|
|
trigger.action.explosion(foundItem:getPoint(), 1)
|
|
-- env.info("Unit: "..foundItem:getName().." was destroyed by script")
|
|
-- else
|
|
-- local suppTimer = math.random(30,100)
|
|
-- local suppArray = {foundItem:getGroup(), suppTimer}
|
|
-- suppress(suppArray)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
local function track_wpns()
|
|
-- env.info("Weapon Track Start")
|
|
for wpn_id_, wpnData in pairs(tracked_weapons) do
|
|
|
|
if wpnData.wpn:isExist() then -- just update position and direction.
|
|
wpnData.pos = wpnData.wpn:getPosition().p
|
|
wpnData.dir = wpnData.wpn:getPosition().x
|
|
wpnData.exMass = wpnData.wpn:getDesc().warhead.explosiveMass
|
|
--wpnData.lastIP = land.getIP(wpnData.pos, wpnData.dir, 50)
|
|
else -- wpn no longer exists, must be dead.
|
|
-- trigger.action.outText("Weapon impacted, mass of weapon warhead is " .. wpnData.exMass, 2)
|
|
local ip = land.getIP(wpnData.pos, wpnData.dir, 20) -- terrain intersection point with weapon's nose. Only search out 20 meters though.
|
|
local impactPoint
|
|
if not ip then -- use last calculated IP
|
|
impactPoint = wpnData.pos
|
|
-- trigger.action.outText("Impact Point:\nPos X: " .. impactPoint.x .. "\nPos Z: " .. impactPoint.z, 2)
|
|
else -- use intersection point
|
|
impactPoint = ip
|
|
-- trigger.action.outText("Impact Point:\nPos X: " .. impactPoint.x .. "\nPos Z: " .. impactPoint.z, 2)
|
|
end
|
|
local staticRadius = wpnData.exMass*staticDamageRangeMultiplier
|
|
-- trigger.action.outText("Static Radius :"..staticRadius, 10)
|
|
local VolS =
|
|
{
|
|
id = world.VolumeType.SPHERE,
|
|
params =
|
|
{
|
|
point = impactPoint,
|
|
radius = staticRadius
|
|
}
|
|
}
|
|
local VolU =
|
|
{
|
|
id = world.VolumeType.SPHERE,
|
|
params =
|
|
{
|
|
point = impactPoint,
|
|
radius = wpnData.exMass*stunRangeMultiplier
|
|
}
|
|
}
|
|
-- env.info("Static search radius: " ..wpnData.exMass*staticDamageRangeMultiplier)
|
|
-- env.warning("Begin Search")
|
|
-- trigger.action.outText("Beginning Searches", 10)
|
|
world.searchObjects(Object.Category.STATIC, VolS, ifFoundS,impactPoint)
|
|
USearchArray = {["point"] = impactPoint, ["exMass"] = wpnData.exMass}
|
|
world.searchObjects(Object.Category.UNIT, VolU, ifFoundU, USearchArray)
|
|
-- env.warning("Finished Search")
|
|
tracked_weapons[wpn_id_] = nil -- remove from tracked weapons first.
|
|
end
|
|
end
|
|
-- env.info("Weapon Track End")
|
|
end
|
|
|
|
local function checkSuppression()
|
|
-- env.info("Checking suppression")
|
|
for i, group in pairs(suppressedGroups) do
|
|
-- env.info("Check group exists, #".. i)
|
|
if group.SuppGroup:isExist() then
|
|
-- env.info("It does")
|
|
group.SuppTime = group.SuppTime - 10
|
|
if group.SuppTime < 1 then
|
|
-- env.info("SuppTime < 1")
|
|
unSuppress(group.SuppGroup)
|
|
end
|
|
else
|
|
suppressedGroups[group.SuppGroup:getName()] = nil
|
|
end
|
|
end
|
|
-- env.info("Ending suppression check")
|
|
end
|
|
|
|
function onWpnEvent(event)
|
|
if event.id == world.event.S_EVENT_SHOT then
|
|
if event.weapon then
|
|
local ordnance = event.weapon
|
|
local weapon_desc = ordnance:getDesc()
|
|
if (weapon_desc.category == 3 or weapon_desc.category == 2 or weapon_desc.category == 1) and not (weapon_desc.missileCategory == 1 or weapon_desc.missileCategory == 2 or weapon_desc.missileCategory == 3) and weapon_desc.warhead and weapon_desc.warhead.explosiveMass and event.initiator then
|
|
tracked_weapons[event.weapon.id_] = { wpn = ordnance, init = event.initiator:getName(), pos = ordnance:getPoint(), dir = ordnance:getPosition().x, exMass = weapon_desc.warhead.explosiveMass }
|
|
-- env.info("Tracking " .. event.initiator:getName())
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function WpnHandler:onEvent(event)
|
|
protectedCall(onWpnEvent, event)
|
|
end
|
|
|
|
function protectedCall(...)
|
|
local status, retval = pcall(...)
|
|
if not status then
|
|
env.error("Splash damage script error... gracefully caught! " .. retval, true)
|
|
end
|
|
end
|
|
|
|
if (weaponDamageEnable == 1) then
|
|
timer.scheduleFunction(function()
|
|
protectedCall(track_wpns)
|
|
return timer.getTime() + 1
|
|
end,
|
|
{},
|
|
timer.getTime() + 0.5
|
|
)
|
|
|
|
timer.scheduleFunction(function()
|
|
protectedCall(checkSuppression)
|
|
return timer.getTime() + 1
|
|
end,
|
|
{},
|
|
timer.getTime() + 10
|
|
)
|
|
|
|
world.addEventHandler(WpnHandler)
|
|
end
|