function widget:GetInfo() return { name = "SpecMode", desc = "coming soon", author = "MelTraX", date = "Mar 21, 2007", license = "GNU GPL, v2 or later", layer = 0, enabled = false } end -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- local SECTOR_WIDTH = 500 local SECTOR_HEIGHT = 500 local IDLE_THRESHOLD = 100 local CHECK_EVERY = 5 local DECAY_EVERY = 100 local DECAY_BY = 1.5 local TRANSITION_DURATION = 2 local HEALTH_GAIN_TO_LOSS_FACTOR = 20 -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- include("colors.h.lua") include("keysym.h.lua") include("utils.lua") local inSpecMode = false local newPointAdded = false local frameCounter = 0 local teams = {} local unitHealths = {} local sectorHealthChanges = {} local sectorX = 0 local sectorY = 0 local maxValue = 0 local function EnterSpecMode() inSpecMode = true Spring.SendCommands({"hideinterface", "showhealthbars"}) --, "viewrot" end local function LeaveSpecMode() inSpecMode = false Spring.SendCommands({"hideinterface", "showhealthbars"}) --, "viewta" end local function HealthChange(unit, difference) if difference > 0 then difference = difference / -HEALTH_GAIN_TO_LOSS_FACTOR end local x, y, z = Spring.GetUnitPosition(unit) if sectorHealthChanges[math.floor(x/SECTOR_WIDTH+1)] then local oldDif = sectorHealthChanges[math.floor(x/SECTOR_WIDTH+1)][math.floor(z/SECTOR_HEIGHT+1)] or 0 sectorHealthChanges[math.floor(x/SECTOR_WIDTH+1)][math.floor(z/SECTOR_HEIGHT+1)] = oldDif + difference end end local function CheckMostActiveSector() sectorX = 0 sectorY = 0 maxValue = 0 for i,v in ipairs(sectorHealthChanges) do for j,w in pairs(v) do if -w > maxValue then maxValue = -w sectorX = i sectorY = j end end end end local function UpdateCamera() if maxValue > IDLE_THRESHOLD then local realX = (sectorX - 0.5) * SECTOR_WIDTH local realY = (sectorY - 0.5) * SECTOR_HEIGHT local currentCamState = Spring.GetCameraState() currentCamState[2] = realX currentCamState[4] = realY Spring.SetCameraState(currentCamState, TRANSITION_DURATION) end end function widget:Initialize() teams = Spring.GetTeamList() local mapX = math.floor(Game.mapX * 500 / SECTOR_WIDTH + 1) local mapY = math.floor(Game.mapY * 500 / SECTOR_HEIGHT + 1) for i=1,mapX do sectorHealthChanges[i] = {} end --EnterSpecMode() end function widget:TextCommand(command) if (command == 'specmode' or command == 'specmode 1') and not inSpecMode then EnterSpecMode() return false elseif (command == 'specmode' or command == 'specmode 0') and inSpecMode then LeaveSpecMode() end local cmd = string.sub(command, 10) return true end function widget:KeyPress(key, mods, isRepeat) if key == KEYSYMS.ESCAPE and inSpecMode and not (mods.alt or mods.ctrl or mods.meta or mods.shift) then LeaveSpecMode() return true end return false end --[[ function widget:AddConsoleLine(line) if not inSpecMode then return end if string.find(line, "added point") then newPointAdded = true end end function widget:UnitDestroyed(unitID, unitDefID, unitTeam) if inSpecMode and UnitDefs[unitDefID].springCategories.weapon then Spring.SendCommands({"specteam " .. Spring.GetUnitTeam(unitID)}) local currentCamState = Spring.GetCameraState() local x, y, z = Spring.GetUnitPosition(unitID) currentCamState[2] = x currentCamState[4] = z Spring.SetCameraState(currentCamState, 2) end end ]] function widget:Update() if not inSpecMode then return end frameCounter = frameCounter + 1 if newPointAdded then Spring.SendCommands({"LastMsgPos"}) newPointAdded = false end if math.mod(frameCounter, DECAY_EVERY) == 0 then for i,v in ipairs(sectorHealthChanges) do for j,w in pairs(v) do v[j] = w/DECAY_BY end end end local currentTeam = math.mod(frameCounter, table.getn(teams)*CHECK_EVERY) if math.mod(currentTeam, CHECK_EVERY) == 0 then currentTeam = currentTeam/CHECK_EVERY --Spring.SendCommands({"specteam " .. currentTeam}) local units = Spring.GetTeamUnits(currentTeam) for i,v in ipairs(units) do local unitHealth = Spring.GetUnitHealth(v) if not unitHealths[v] then HealthChange(v, unitHealth) unitHealths[v] = unitHealth elseif unitHealth ~= unitHealths[v] then HealthChange(v, unitHealth - unitHealths[v]) unitHealths[v] = unitHealth end end CheckMostActiveSector() end UpdateCamera() end --[[ function widget:DrawScreen() if inSpecMode then drawTable(sectorHealthChanges) end end ]] -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- debug functions function drawTable(theTable, maxDepth, initX, initY, level, knownTables) local TEXT_HEIGHT = 9 local INDENT = 100 if maxDepth == nil then maxDepth = 10 end if initX == nil then initX = 20 end if initY == nil then initY = 730 end if level == nil then level = 1 end if knownTables == nil then knownTables = {} end if initY <= 0 then return 0 end local currentY = initY for i, v in pairs(knownTables) do if v == theTable then gl.Text(MagentaStr .. "--> " .. i, initX, currentY, TEXT_HEIGHT, "O") return 0 end end table.insert(knownTables, theTable) --gl.Text(MagentaStr .. table.getn(knownTables), initX-1-INDENT, currentY, TEXT_HEIGHT, "or") if level == maxDepth+1 then gl.Text(RedStr..tostring(theTable).." (max Depth - getn: "..table.getn(theTable)..")", initX, currentY, TEXT_HEIGHT, "O") return 0 end gl.Text(GreenStr .. "__tostring", initX, currentY, TEXT_HEIGHT, "o") gl.Text(tostring(theTable), initX+INDENT, currentY, TEXT_HEIGHT, "o") currentY = currentY - TEXT_HEIGHT - 1 for i, v in pairs(theTable) do gl.Text(GreenStr .. i, initX, currentY, TEXT_HEIGHT, "o") if type(v) == "string" or type(v) == "number" then gl.Text(v, initX+INDENT, currentY, TEXT_HEIGHT, "o") end if type(v) == "boolean" then if v then gl.Text("true", initX+INDENT, currentY, TEXT_HEIGHT, "o") else gl.Text("false", initX+INDENT, currentY, TEXT_HEIGHT, "o") end end if type(v) == "table" then currentY = currentY - drawTable(v, maxDepth, initX + INDENT, currentY, level+1, knownTables) end if type(v) == "function" then gl.Text(BlackStr .. "function", initX+INDENT, currentY, TEXT_HEIGHT, "O") end currentY = currentY - TEXT_HEIGHT - 1 end if currentY == initY then gl.Text(BlackStr .. "empty table", initX, currentY, TEXT_HEIGHT, "O") end local metaT = getmetatable(theTable) if metaT ~= nil then gl.Text(YellowStr .. "metatable", initX, currentY, TEXT_HEIGHT, "o") currentY = currentY - drawTable(metaT, maxDepth, initX+INDENT, currentY, level+1, knownTables) end return initY-currentY end