-------------------------------------------------------------------------------- function widget:GetInfo() return { name = "Anti Ranges v4", desc = "Draws circle to show anti defence ranges (options: /antiranges_glow, antiranges_fade)", author = "[teh]decay, Floris", date = "25 january 2015", license = "GNU GPL, v2 or later", version = 4, layer = 5, enabled = true -- loaded by default? } end -- project page on github: https://github.com/jamerlan/gui_mobile_anti_defence_range --Changelog -- v2 [teh]decay: Add water antinukes -- v3 Floris: added normal anti, changed widget name, optional glow, optional fadeout on closeup, changed line thickness and opacity, empty anti uses different color -- v4 Floris: fixed nil error -------------------------------------------------------------------------------- -- Console commands -------------------------------------------------------------------------------- --/antiranges_glow -- toggles a faint glow on the line --/antiranges_fade -- toggles hiding of ranges when zoomed in -------------------------------------------------------------------------------- -- Options -------------------------------------------------------------------------------- local opacityMultiplier = 0.85 local multiStockpileColor = {1,1,0} local filledStockpileColor = {1,0.75,0} local unknownStockpileColor = {1,0.54,1} local emptyStockpileColor = {1,0.33,0} local unfinishedStockpileColor = {1,0,0.75} local showLineGlow = true local fadeOnCloseup = true local fadeStartDistance = 3300 -------------------------------------------------------------------------------- -- Speedups -------------------------------------------------------------------------------- local arm_anti = UnitDefNames.armamd.id local arm_mobile_anti = UnitDefNames.armscab.id local arm_mobile_anti_water = UnitDefNames.armcarry.id local core_anti = UnitDefNames.corfmd.id local core_mobile_anti = UnitDefNames.cormabm.id local core_mobile_anti_water = UnitDefNames.corcarry.id local glColor = gl.Color local glDepthTest = gl.DepthTest local glLineWidth = gl.LineWidth local glDrawGroundCircle = gl.DrawGroundCircle local spGetMyPlayerID = Spring.GetMyPlayerID local spGetPlayerInfo = Spring.GetPlayerInfo local spGetUnitDefID = Spring.GetUnitDefID local spGetUnitPosition = Spring.GetUnitPosition local spGetPositionLosState = Spring.GetPositionLosState local spGetCameraPosition = Spring.GetCameraPosition local spGetUnitStockpile = Spring.GetUnitStockpile local spGetAllUnits = Spring.GetAllUnits local GetUnitHealth = Spring.GetUnitHealth local antiInLos = {} local antiOutLos = {} local coverageRangeArmStatic = WeaponDefs[UnitDefNames.armamd.weapons[1].weaponDef].coverageRange local coverageRangeCoreStatic = WeaponDefs[UnitDefNames.corfmd.weapons[1].weaponDef].coverageRange local coverageRangeArm = WeaponDefs[UnitDefNames.armscab.weapons[1].weaponDef].coverageRange local coverageRangeCore = WeaponDefs[UnitDefNames.cormabm.weapons[1].weaponDef].coverageRange local coverageRangeArmWater = WeaponDefs[UnitDefNames.armcarry.weapons[1].weaponDef].coverageRange local coverageRangeCoreWater = WeaponDefs[UnitDefNames.corcarry.weapons[1].weaponDef].coverageRange -------------------------------------------------------------------------------- -- Callins -------------------------------------------------------------------------------- function widget:DrawWorldPreUnit() if Spring.IsGUIHidden() then return end local camX, camY, camZ = spGetCameraPosition() for uID, pos in pairs(antiInLos) do local LosOrRadar, inLos, inRadar = spGetPositionLosState(pos.x, pos.y, pos.z) if not inLos then antiOutLos[uID] = pos antiInLos[uID] = nil end end for uID, pos in pairs(antiInLos) do local x, y, z = spGetUnitPosition(uID) if x ~= nil and y ~= nil and z ~= nil then drawCircle(uID, pos.coverageRange, x, y, z, camX, camY, camZ) end end for uID, pos in pairs(antiOutLos) do local LosOrRadar, inLos, inRadar = spGetPositionLosState(pos.x, pos.y, pos.z) if inLos then antiOutLos[uID] = nil antiInLos[uID] = pos end end for uID, pos in pairs(antiOutLos) do if pos.x ~= nil and pos.y ~= nil and pos.z ~= nil then drawCircle(uID, pos.coverageRange, pos.x, pos.y, pos.z, camX, camY, camZ) end end end function drawCircle(uID, coverageRange, x, y, z, camX, camY, camZ) local xDifference = camX - x local yDifference = camY - y local zDifference = camZ - z local camDistance = math.sqrt(xDifference*xDifference + yDifference*yDifference + zDifference*zDifference) local lineWidthMinus = (camDistance/fadeStartDistance) if lineWidthMinus > 2 then lineWidthMinus = 2 end local lineOpacityMultiplier = 1 if fadeOnCloseup then lineOpacityMultiplier = (camDistance - fadeStartDistance) / 1800 if lineOpacityMultiplier > 1 then lineOpacityMultiplier = 1 end end lineOpacityMultiplier = lineOpacityMultiplier * opacityMultiplier if lineOpacityMultiplier > 0 then local numStockpiled, numStockpileQued, stockpileBuild = spGetUnitStockpile(uID) local circleColor = emptyStockpileColor local _,_,_,_,build = GetUnitHealth(uID) if build ~= nil and build < 1 then circleColor = unfinishedStockpileColor else if numStockpiled == nil then circleColor = unknownStockpileColor elseif numStockpiled == 1 then circleColor = filledStockpileColor elseif numStockpiled > 1 then circleColor = multiStockpileColor end end glDepthTest(true) if showLineGlow then glLineWidth(10) glColor(circleColor[1],circleColor[2],circleColor[3], .016*lineOpacityMultiplier) glDrawGroundCircle(x, y, z, coverageRange, 256) end glColor(circleColor[1],circleColor[2],circleColor[3], .5*lineOpacityMultiplier) glLineWidth(3-lineWidthMinus) glDrawGroundCircle(x, y, z, coverageRange, 256) end end function widget:UnitEnteredLos(unitID) processVisibleUnit(unitID) end function processVisibleUnit(unitID) local unitDefId = spGetUnitDefID(unitID); if unitDefId == arm_anti or unitDefId == core_anti or unitDefId == arm_mobile_anti or unitDefId == core_mobile_anti or unitDefId == arm_mobile_anti_water or unitDefId == core_mobile_anti_water then local x, y, z = spGetUnitPosition(unitID) local pos = {} pos["x"] = x pos["y"] = y pos["z"] = z if unitDefId == arm_mobile_anti then pos.coverageRange = coverageRangeArm elseif unitDefId == arm_anti then pos.coverageRange = coverageRangeArmStatic elseif unitDefId == core_anti then pos.coverageRange = coverageRangeCoreStatic elseif unitDefId == arm_mobile_anti_water then pos.coverageRange = coverageRangeArmWater elseif unitDefId == core_mobile_anti then pos.coverageRange = coverageRangeCore else pos.coverageRange = coverageRangeCoreWater end antiInLos[unitID] = pos antiOutLos[unitID] = nil end end function widget:UnitLeftLos(unitID) local unitDefId = spGetUnitDefID(unitID); if unitDefId == arm_anti or unitDefId == core_anti or unitDefId == arm_mobile_anti or unitDefId == core_mobile_anti or unitDefId == arm_mobile_anti_water or unitDefId == core_mobile_anti_water then local x, y, z = spGetUnitPosition(unitID) local pos = {} pos["x"] = x or antiInLos[unitID].x pos["y"] = y or antiInLos[unitID].y pos["z"] = z or antiInLos[unitID].z if unitDefId == arm_mobile_anti then pos.coverageRange = coverageRangeArm elseif unitDefId == arm_mobile_anti_water then pos.coverageRange = coverageRangeArmWater elseif unitDefId == core_mobile_anti then pos.coverageRange = coverageRangeCore else pos.coverageRange = coverageRangeCoreWater end antiOutLos[unitID] = pos antiInLos[unitID] = nil end end function widget:UnitCreated(unitID, unitDefID, teamID, builderID) processVisibleUnit(unitID) end function widget:UnitTaken(unitID, unitDefID, unitTeam, newTeam) processVisibleUnit(unitID) end function widget:UnitGiven(unitID, unitDefID, unitTeam, oldTeam) processVisibleUnit(unitID) end function widget:GameFrame(n) for uID, _ in pairs(antiInLos) do if not spGetUnitDefID(uID) then antiInLos[uID] = nil -- has died end end end function widget:Initialize() checkAllUnits() end function widget:PlayerChanged(playerID) checkAllUnits() end function checkAllUnits() local _, _, spec, teamId = spGetPlayerInfo(spGetMyPlayerID()) antiInLos = {} antiOutLos = {} local allUnits = spGetAllUnits() for _, unitID in ipairs(allUnits) do processVisibleUnit(unitID) end end -------------------------------------------------------------------------------- function widget:GetConfigData(data) savedTable = {} savedTable.showLineGlow = showLineGlow savedTable.fadeOnCloseup = fadeOnCloseup return savedTable end function widget:SetConfigData(data) if data.showLineGlow ~= nil then showLineGlow = data.showLineGlow end if data.fadeOnCloseup ~= nil then fadeOnCloseup = data.fadeOnCloseup end end function widget:TextCommand(command) if (string.find(command, "antiranges_glow") == 1 and string.len(command) == 15) then showLineGlow = not showLineGlow if showLineGlow then Spring.Echo("Anti Ranges: Glow on") else Spring.Echo("Anti Ranges: Glow off") end end if (string.find(command, "antiranges_fade") == 1 and string.len(command) == 15) then fadeOnCloseup = not fadeOnCloseup if fadeOnCloseup then Spring.Echo("Anti Ranges: Fade-out on closeup enabled") else Spring.Echo("Anti Ranges: Fade-out on closeup disabled") end end end