Untitled
unknown
lua
3 years ago
24 kB
7
Indexable
function widget:GetInfo()
return {
name = "AA Controller3",
desc = "target bombers",
author = "ABC",
version = "v3",
date = "July, 2021",
layer = 4588,
enabled = true,
}
end
local spEcho = Spring.Echo
local spGetUnitPosition = Spring.GetUnitPosition
local spGetUnitIsCloaked = Spring.GetUnitIsCloaked
local spGetUnitWeaponCanFire = Spring.GetUnitWeaponCanFire
local spGetUnitWeaponState = Spring.GetUnitWeaponState
local spGetUnitStates = Spring.GetUnitStates
local spGetUnitHeading = Spring.GetUnitHeading
local spGetUnitHealth = Spring.GetUnitHealth
local spGetUnitIsStunned = Spring.GetUnitIsStunned
local spGetUnitWeaponTestTarget = Spring.GetUnitWeaponTestTarget
local spGetUnitWeaponTryTarget = Spring.GetUnitWeaponTryTarget
local spSetUnitRotation = Spring.SetUnitRotation
local spGetUnitDefID = Spring.GetUnitDefID
local spGetMyPlayerID = Spring.GetMyPlayerID
local spGetPlayerInfo = Spring.GetPlayerInfo
local spGetUnitSeparation = Spring.GetUnitSeparation
local spGiveOrderToUnit = Spring.GiveOrderToUnit
local spGetUnitWeaponDamages = Spring.GetUnitWeaponDamages
local spGetUnitRulesParam = Spring.GetUnitRulesParam
local spGetUnitMaxRange = Spring.GetUnitMaxRange
local spGetUnitCurrentCommand = Spring.GetUnitCurrentCommand
local spGetUnitIsDead = Spring.GetUnitIsDead
local spGetUnitWeaponTestTarget = Spring.GetUnitWeaponTestTarget
local spGetUnitWeaponTestRange = Spring.GetUnitWeaponTestRange
local spGetUnitWeaponTarget = Spring.GetUnitWeaponTarget
local spGetUnitWeaponVectors = Spring.GetUnitWeaponVectors
local spGetProjectileOwnerID = Spring.GetProjectileOwnerID
local spGetProjectileTarget = Spring.GetProjectileTarget
local ENEMY_UNITS = Spring.ENEMY_UNITS
local spGetTeamUnits = Spring.GetTeamUnits
local CMD_UNIT_SET_TARGET = 34923
local myPlayerID = spGetMyPlayerID()
local myTeamID = Spring.GetMyTeamID()
local myAllyTeamID = Spring.GetMyAllyTeamID()
-- tables for anti air
local antiAirUnitList = {}
local antiAirLastReloadFrame = {}
-- tables for target monitoring
local scoutList = {}
local fighterList = {}
local bomberList = {}
local targetFutureDMG = {}
local targetInitialHP = {}
local projectileList = {}
local projectileTargetsList = {} -- projectileID : {targetID, dmg}
-- For Debugging
function dump(o)
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end
local PI = math.pi;
local TWOPI = PI * 2;
local PIDIV2 = PI * 0.5;
local GL_TRIANGLE_STRIP = GL.TRIANGLE_STRIP
local GL_QUADS = GL.QUADS
local glBeginEnd = gl.BeginEnd
local glNormal = gl.Normal
local glTexCoord = gl.TexCoord
local glVertex = gl.Vertex
local glColor = gl.Color
local sin = math.sin
local cos = math.cos
function DrawSphere( cx, cy, cz, r, p, color)
local theta1,theta2,theta3 = 0,0,0;
local ex,ey,ez = 0,0,0;
local px,py,pz = 0,0,0;
--// Disallow a negative number for radius.
if ( r < 0 ) then r = -r; end
--// Disallow a negative number for precision.
if ( p < 0 ) then p = -p; end
for i = 0,p*0.5-1 do
theta1 = i * TWOPI / p - PIDIV2;
theta2 = (i + 1) * TWOPI / p - PIDIV2;
glColor(color[1], color[2], color[3], 0.2)
glBeginEnd( GL_TRIANGLE_STRIP , function()
for j = 0,p do
theta3 = j * TWOPI / p;
ex = cos(theta2) * cos(theta3);
ey = sin(theta2);
ez = cos(theta2) * sin(theta3);
px = cx + r * ex;
py = cy + r * ey;
pz = cz + r * ez;
glNormal( ex, ey, ez );
glTexCoord( -(j/p) , 2*(i+1)/p );
glVertex( px, py, pz );
ex = cos(theta1) * cos(theta3);
ey = sin(theta1);
ez = cos(theta1) * sin(theta3);
px = cx + r * ex;
py = cy + r * ey;
pz = cz + r * ez;
glNormal( ex, ey, ez );
glTexCoord( -(j/p), 2*i/p );
glVertex( px, py, pz );
end
end)
end
end
function addAntiAir(unitID)
antiAirLastReloadFrame[unitID] = spGetUnitWeaponState(unitID, 1, "reloadFrame");
AddUnitsToList({unitID}, antiAirUnitList)
end
function removeBomber(unitID)
bomberList = removeUnitFromList(unitID, bomberList)
-- targetFutureDMG[unitID] = nil;
-- targetInitialHP[unitID] = nil;
end
function AddUnitsToList(UnitsIds, unitlistName)
for i = 1, #UnitsIds do
local unitID = UnitsIds[i]
local unitExist = false
for o = 1, #unitlistName do
local uid = unitlistName[o]
if unitID == uid then
unitExist = true
end
end
if not unitExist then
unitlistName[#unitlistName + 1] = unitID
end
end
end
function removeUnitsFromList(UnitsIds, unitlistName)
if #UnitsIds > 0 then
local newUnitList = {}
for p = 1, #unitlistName do
local unitID = unitlistName[p]
local unitExist = false
for q = 1, #UnitsIds do
local uid = UnitsIds[q]
if unitID == uid then
unitExist = true
end
end
if not unitExist then
newUnitList[#newUnitList + 1] = unitID
end
end
return newUnitList
else
return unitlistName
end
end
function valueInList(unitID, unitList)
for p = 1, #unitList do
local storedUnitID = unitList[p];
if storedUnitID == unitID then
return true
end
end
return false
end
function removeUnitFromList(unitID, unitList)
if valueInList(unitID, unitList) then
local newUnitList = {}
for p = 1, #unitList do
local storedUnitID = unitList[p]
if storedUnitID ~= unitID then
newUnitList[#newUnitList] = storedUnitID;
end
end
return newUnitList
end
return unitList
end
function checkIsAntiAir(unitID)
local ud = getUnitDef(unitID)
if #ud.weapons >= 1 then
if not ud.canMove and not ud.isFactory then
if ud.weapons[1]["onlyTargets"]["vtol"] == true then
return true
end
else
exclusiveAA = true;
for i = 1, #ud.weapons do
if ud.weapons[i]["onlyTargets"]["vtol"] == nil or ud.weapons[i]["onlyTargets"]["vtol"] == false then
exclusiveAA = false;
end
end
if exclusiveAA then
return true
end
end
end
return false
end
function getUnitDef(unitID)
if unitID == nil then
return nil
end
local unitDefID = spGetUnitDefID(unitID)
if unitDefID == nil then return nil end
return UnitDefs[ unitDefID ]
end
function checkForTargetsInList(unitID, list)
local maxRange = spGetUnitMaxRange(unitID);
local minDist = maxRange;
local longestTime = nil;
local target = nil;
local removeList = {}
for j = 1, #list do
local targetUnitID = list[j];
Spring.Echo(targetUnitID, Spring.ValidUnitID(targetUnitID), 'a', spGetUnitIsDead(targetUnitID))
local overDamaged = targetFutureDMG[targetUnitID] > targetInitialHP[targetUnitID]
local dist = spGetUnitSeparation(unitID, targetUnitID, true)
if dist == nil then
removeList[#removeList+1] = targetUnitID
else
local canHit = spGetUnitWeaponTestTarget(unitID, 1, targetUnitID);
local canHit = canHit and spGetUnitWeaponTestRange(unitID, 1, targetUnitID);
if overDamaged then
if target == nil and dist < maxRange and canHit then
target = targetUnitID;
end
else
if minDist ~= nil and dist < minDist and canHit then
target = targetUnitID
minDist = dist
end
end
end
end
return target, removeList
end
function checkTargets(f)
if #antiAirUnitList > 0 then
deadAA = {}
local split = 3
local iteration = (f%split)
for i = 1, #antiAirUnitList do
if i%split == iteration or true then
local unitID = antiAirUnitList[i];
if spGetUnitIsDead(unitID) then
deadAA[#deadAA+1] = unitID
else
local unitDef = getUnitDef(unitID)
local _, isUser, currentTargetID = spGetUnitWeaponTarget(unitID, 1)
if antiAirLastReloadFrame[unitID] ~= spGetUnitWeaponState(unitID, 1, "reloadFrame") then
antiAirLastReloadFrame[unitID] = spGetUnitWeaponState(unitID, 1, "reloadFrame")
if currentTargetID == nil then
--Spring.Echo("WTF HOW DOES THIS HAPPEN" )
else
local estimatedDmg = 0
ud = getUnitDef(currentTargetID)
if targetFutureDMG[currentTargetID] ~= nil and ud then
estimatedDmg = 0.9 * spGetUnitWeaponDamages(unitID, 1, ud.armorType)
targetFutureDMG[currentTargetID] = targetFutureDMG[currentTargetID] + estimatedDmg
end
local x, y, z, _, _, _ = spGetUnitWeaponVectors( unitID, 1 ) --spGetUnitPosition(unitID, true, false)
if x ~= nil then
--local x, y, z= spGetUnitPosition(unitID, true, false)
local searchSize = 200;
projectiles = Spring.GetProjectilesInRectangle(x-searchSize, z-searchSize, x+searchSize, z+searchSize)
for j = 1, #projectiles do
local projectileID = projectiles[j]
local projectileOwner = spGetProjectileOwnerID(projectileID)
if not valueInList(projectileID, projectileList) and projectileOwner == unitID then
local pTargetType, pTarget = spGetProjectileTarget(projectileID)
projectileList[#projectileList+1] = projectileID
projectileTargetsList[projectileID] = {currentTargetID, estimatedDmg}
--Spring.Echo("fired", projectileOwner, projectileID, pTarget, currentTargetID)
end
end
end
end
end
--
--
-- Don't set priority target if manual attack command is already issued
local ccmdID, _, ctag, targetID = spGetUnitCurrentCommand(unitID)
if ccmdID ~= CMD.ATTACK then
currentTargetPriority = 0;
-- if we are already targeting a bomber then no need set new target
if valueInList(currentTargetID, bomberList) and isUser and targetFutureDMG[currentTargetID] < targetInitialHP[currentTargetID] then
currentTargetPriority = 3;
else --Lets check for bomber targets in range
local target, removeList = checkForTargetsInList(unitID, bomberList);
bomberList = removeUnitsFromList(removeList, bomberList);
if target ~= nil then -- and target ~= spGetUnitRulesParam(unitID, "targetID") then
spGiveOrderToUnit(unitID, 34923, { target }, {"alt"})
currentTargetPriority = 3;
end
end
if currentTargetPriority < 3 then
if valueInList(currentTargetID, scoutList) and targetFutureDMG[currentTargetID] < targetInitialHP[currentTargetID] then
currentTargetPriority = 2;
else --Lets check for bomber targets in range
local target, removeList = checkForTargetsInList(unitID, scoutList);
scoutList = removeUnitsFromList(removeList, scoutList);
if target ~= nil then -- and target ~= spGetUnitRulesParam(unitID, "targetID") then
spGiveOrderToUnit(unitID, 34923, { target }, {"alt"})
currentTargetPriority = 2;
end
end
end
if currentTargetPriority < 2 then
if valueInList(currentTargetID, fighterList) and targetFutureDMG[currentTargetID] < targetInitialHP[currentTargetID] then
currentTargetPriority = 1;
else --Lets check for bomber targets in range
local target, removeList = checkForTargetsInList(unitID, fighterList);
fighterList = removeUnitsFromList(removeList, fighterList);
if target ~= nil then -- and target ~= spGetUnitRulesParam(unitID, "targetID") then
spGiveOrderToUnit(unitID, 34923, { target }, {"alt"})
currentTargetPriority = 1;
end
end
end
end
end
end
end
antiAirUnitList = removeUnitsFromList(deadAA, antiAirUnitList);
-- loop projectiles
projToRemove = {}
needRecalculate = {}
for j = 1, #projectileList do
local projectileID = projectileList[j]
local initTarget, dmg = projectileTargetsList[projectileID][1], projectileTargetsList[projectileID][2];
if spGetProjectileOwnerID(projectileID) ~= nil and spGetProjectileTarget(projectileID) ~= nil then
local pTargetType, pTarget = spGetProjectileTarget(projectileID)
if initTarget ~= pTarget then
if targetInitialHP[initTarget] ~= nil then
local health, _, _, _ = spGetUnitHealth(initTarget);
if health ~= nil then
targetInitialHP[initTarget] = health;
if not valueInList(initTarget, needRecalculate) then
needRecalculate[#needRecalculate+1] = initTarget
end
targetFutureDMG[initTarget] = 0;
end
projToRemove[#projToRemove+1] = projectileID
end
else
if dmg == 0 and initTarget ~= nil and getUnitDef(initTarget) then
dmg = 0.9 * spGetUnitWeaponDamages(spGetProjectileOwnerID(projectileID), 1, getUnitDef(initTarget).armorType)
projectileTargetsList[projectileID][2] = dmg
end
end
--Spring.Echo("proj", projectileID, initTarget, pTarget, dmg)
--Spring.Echo("proj",projectileID, Spring.GetProjectileOwnerID(projectileID), Spring.GetProjectileTarget(projectileID))
else
--Spring.Echo("proj died", projectileID, initTarget, targetInitialHP[initTarget], targetFutureDMG[initTarget])
if targetInitialHP[initTarget] ~= nil then
local health, _, _, _ = spGetUnitHealth(initTarget);
if health ~= nil then
targetInitialHP[initTarget] = health;
if not valueInList(initTarget, needRecalculate) then
needRecalculate[#needRecalculate+1] = initTarget
end
targetFutureDMG[initTarget] = 0;
end
projToRemove[#projToRemove+1] = projectileID
end
end
end
projectileList = removeUnitsFromList(projToRemove, projectileList)
for j = 1, #projToRemove do
projectileTargetsList[projToRemove[j]] = nil;
end
if #needRecalculate > 0 then
for j = 1, #projectileList do
local projectileID = projectileList[j]
local initTarget, dmg = projectileTargetsList[projectileID][1], projectileTargetsList[projectileID][2];
if valueInList(initTarget, needRecalculate) then
targetFutureDMG[initTarget] = targetFutureDMG[initTarget] + dmg;
end
end
end
end
end
function widget:UnitEnteredLos(unitID, unitTeam, allyTeam, unitDefID)
if not valueInList(unitID, bomberList) then
local ud = getUnitDef(unitID)
if ud.modCategories.scout then
scoutList[#scoutList + 1] = unitID;
targetFutureDMG[unitID] = 0;
local health, _, _, _ = spGetUnitHealth(unitID);
targetInitialHP[unitID] = health;
elseif ud.modCategories.fighter then
fighterList[#fighterList + 1] = unitID;
targetFutureDMG[unitID] = 0;
local health, _, _, _ = spGetUnitHealth(unitID);
targetInitialHP[unitID] = health;
elseif #ud.weapons >= 1 then
if unitTeam ~= myTeamID and WeaponDefs[ud.weapons[1].weaponDef].type == "AircraftBomb" then
bomberList[#bomberList + 1] = unitID;
targetFutureDMG[unitID] = 0;
local health, _, _, _ = spGetUnitHealth(unitID);
targetInitialHP[unitID] = health;
end
end
end
end
function widget:DrawWorldPreUnit()
for j = 1, #bomberList do
local targetUnitID = bomberList[j];
local overDamaged = targetFutureDMG[targetUnitID] > targetInitialHP[targetUnitID]
if overDamaged or true then
local x, y, z = spGetUnitPosition(targetUnitID)
if x ~= nil then
local color = {1, 0, 0}
if not overDamaged then
sHP = targetInitialHP[targetUnitID]
fHP = targetFutureDMG[targetUnitID]
color = {0, 1-(fHP/sHP), (fHP/sHP) }
end
DrawSphere(x, y, z, 40, 20, color)
end
end
end
--drawCircle(uID, pos.coverageRange, pos.x, pos.y, pos.z, pos.circleColor)
--DrawSphere(3600, 20, 7300, 1000, 100)
end
bomberWeaponDefs = {}
bomberUnitDefs = {}
function widget:Initialize()
local _, _, spectator = spGetPlayerInfo(myPlayerID)
if spectator then
widgetHandler:RemoveWidget()
end
for i = 1,#WeaponDefs do
if WeaponDefs[i].type == "AircraftBomb" then
--spEcho(i,dump(WeaponDefs[i].type))
bomberWeaponDefs[#bomberWeaponDefs+1] = i
end
end
for i = 1,#UnitDefs do
if #UnitDefs[i].weapons >= 1 and valueInList(UnitDefs[i].weapons[1].weaponDef, bomberWeaponDefs) then
--if true then
--spEcho(i, dump(UnitDefs[i].name))
bomberUnitDefs[#bomberUnitDefs+1] = i
end
end
local allBombers = Spring.GetTeamUnitsByDefs( 0, bomberUnitDefs )
spEcho("mybombers", dump(allBombers))
-- WeaponDefs[ud.weapons[1].weaponDef].type == "AircraftBomb"
if false then
for k, unitID in pairs(Spring.GetAllUnits()) do
teamID = Spring.GetUnitTeam(unitID);
if teamID == myTeamID then
if checkIsAntiAir(unitID) then
addAntiAir(unitID)
end
elseif myAllyTeamID == Spring.GetUnitAllyTeam(unitID) then
else
if not valueInList(unitID, bomberList) then
local ud = getUnitDef(unitID)
if ud then
if ud.modCategories.scout then
scoutList[#scoutList + 1] = unitID;
targetFutureDMG[unitID] = 0;
local health, _, _, _ = spGetUnitHealth(unitID);
targetInitialHP[unitID] = health;
elseif ud.modCategories.fighter then
fighterList[#fighterList + 1] = unitID;
targetFutureDMG[unitID] = 0;
local health, _, _, _ = spGetUnitHealth(unitID);
targetInitialHP[unitID] = health;
elseif #ud.weapons >= 1 then
if unitTeam ~= myTeamID and WeaponDefs[ud.weapons[1].weaponDef].type == "AircraftBomb" then
bomberList[#bomberList + 1] = unitID;
targetFutureDMG[unitID] = 0;
local health, _, _, _ = spGetUnitHealth(unitID);
targetInitialHP[unitID] = health;
end
end
end
end
end
end
end
end
function widget:GameFrame(f)
checkTargets(f)
end
function widget:UnitLeftRadar(unitID, unitTeam, allyTeam, unitDefID)
spEcho("left radar")
if unitTeam ~= myTeamID then
--removeBomber(unitID)
end
end
function widget:UnitLeftLos(unitID, unitTeam, allyTeam, unitDefID)
Spring.Echo("left los")
end
function widget:UnitCreated(unitID, unitDefID, unitTeam)
if unitTeam == myTeamID then
if checkIsAntiAir(unitID) then
addAntiAir(unitID)
end
end
end
function widget:UnitGiven(unitID, unitDefID, oldTeam, newTeam)
if unitTeam == myTeamID then
if checkIsAntiAir(unitID) then
addAntiAir(unitID)
end
end
end
function widget:RenderUnitDestroyed(unitID, unitDefID, unitTeam)
spEcho("renderdestroyed")
end
function widget:UnitDestroyed(unitID, unitDefID, unitTeam, attackerID, attackerDefID, attackerTeam)
spEcho("blabla")
if unitTeam ~= myTeamID then
bomberList = removeUnitFromList(unitID, bomberList)
targetFutureDMG[unitID] = nil;
targetInitialHP[unitID] = nil;
end
local destrUnit = { unitID }
if unitTeam == myTeamID then
antiAirUnitList = removeUnitFromList(destrUnit, antiAirUnitList)
end
endEditor is loading...