Untitled
unknown
lua
2 years ago
24 kB
6
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 end
Editor is loading...