diff --git a/LuaRules/gadgets/game_end.lua b/LuaRules/gadgets/game_end.lua new file mode 100644 index 0000000..b80e6a0 --- /dev/null +++ b/LuaRules/gadgets/game_end.lua @@ -0,0 +1,321 @@ +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-- +-- file: game_end.lua +-- brief: handles trigger conditions for game over +-- author: Andrea Piras +-- +-- Copyright (C) 2010-2013. +-- Licensed under the terms of the GNU GPL, v2 or later. +-- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +function gadget:GetInfo() + return { + name = "Game End", + desc = "Handles team/allyteam deaths and declares gameover", + author = "Andrea Piras", + date = "June, 2013", + license = "GNU GPL, v2 or later", + layer = 0, + enabled = true -- loaded by default? + } +end + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +-- synced only +if (not gadgetHandler:IsSyncedCode()) then + return false +end + +-- In this gadget, an allyteam is declared dead when it no longer has any units +-- Allyteam explosion when no coms are left (killing all remaining units of that allyteam) is implemented in teamcomends.lua + +-- sharedDynamicAllianceVictory is a C-like bool +local sharedDynamicAllianceVictory = tonumber(Spring.GetModOptions().shareddynamicalliancevictory) or 0 + +-- ignoreGaia is a C-like bool +local ignoreGaia = 1 + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +local KillTeam = Spring.KillTeam +local GetAllyTeamList = Spring.GetAllyTeamList +local GetTeamList = Spring.GetTeamList +local GetPlayerInfo = Spring.GetPlayerInfo +local GetPlayerList = Spring.GetPlayerList +local GetTeamInfo = Spring.GetTeamInfo +local GetTeamUnitCount = Spring.GetTeamUnitCount +local GetAIInfo = Spring.GetAIInfo +local GetTeamLuaAI = Spring.GetTeamLuaAI +local GameOver = Spring.GameOver +local AreTeamsAllied = Spring.AreTeamsAllied + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +--allyTeamInfos structure: +-- allyTeamInfos = { +-- [allyTeamID] = { +-- teams = { +-- [teamID]= { +-- unitCount, +-- isGaia, +-- dead, +-- isAI, +-- isControlled, +-- players = { +-- [playerID] = isControlling +-- }, +-- }, +-- }, +-- unitCount, +-- isGaia, +-- dead, +-- }, +--} +local allyTeamInfos = {} +local teamToAllyTeam = {} +local playerIDtoAIs = {} +local playerQuitIsDead = true +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +function gadget:GameOver() + -- remove ourself after successful game over + gadgetHandler:RemoveGadget(self) +end + +function gadget:Initialize() + if tostring(Spring.GetModOptions().deathmode) == "neverend" or Spring.GetModOptions().deathmode == nil or true then + gadgetHandler:RemoveGadget(self) + return + end + + local gaiaTeamID = Spring.GetGaiaTeamID() + local teamCount = 0 + for _,teamID in ipairs(GetTeamList()) do + if ignoreGaia ~= 1 or teamID ~= gaiaTeamID then + teamCount = teamCount + 1 + end + end + + if teamCount < 2 then -- sandbox mode ( possibly gaia + possibly one player) + gadgetHandler:RemoveGadget(self) + return + elseif teamCount == 2 then + playerQuitIsDead = false -- let player quit & rejoin in 1v1 + end + + -- at start, fill in the table of all alive allyteams + for _,allyTeamID in ipairs(GetAllyTeamList()) do + local allyTeamInfo = {} + allyTeamInfo.unitCount = 0 + allyTeamInfo.teams = {} + for _,teamID in ipairs(GetTeamList(allyTeamID)) do + teamToAllyTeam[teamID] = allyTeamID + local teamInfo = {} + teamInfo.players = {} + --is it engine ai? + teamInfo.isAI = select(4,GetTeamInfo(teamID)) + teamInfo.hasLeader = select(2,GetTeamInfo(teamID)) >= 0 + if teamInfo.isAI then + --store who hosts that engine ai + local AIHostPlayerID = select(3,GetAIInfo(teamID)) + playerIDtoAIs[AIHostPlayerID] = playerIDtoAIs[AIHostPlayerID] or {} + playerIDtoAIs[AIHostPlayerID][teamID] = allyTeamID + end + --is luaai + if GetTeamLuaAI(teamID) ~= "" then + teamInfo.isAI = true + teamInfo.isControlled = true + end + --is gaia + if teamID == gaiaTeamID then + allyTeamInfo.isGaia = true + teamInfo.isGaia = true + teamInfo.isControlled = true + end + teamInfo.unitCount = GetTeamUnitCount(teamID) + allyTeamInfo.unitCount = allyTeamInfo.unitCount + teamInfo.unitCount + allyTeamInfo.teams[teamID] = teamInfo + end + allyTeamInfos[allyTeamID] = allyTeamInfo + end + for _,playerID in ipairs(GetPlayerList()) do + CheckPlayer(playerID) + end +end + +local function IsCandidateWinner(allyTeamID) + return not allyTeamInfos[allyTeamID].dead and (ignoreGaia == 0 or not allyTeamInfos[allyTeamID].isGaia) +end + +local function CheckSingleAllyVictoryEnd() + local winnerCount = 0 + local candidateWinners = {} + -- find the last remaining allyteam + for allyTeamID in pairs(allyTeamInfos) do + if IsCandidateWinner(allyTeamID) then + winnerCount = winnerCount + 1 + candidateWinners[#candidateWinners+1] = allyTeamID + end + end + if #candidateWinners > 1 then + return false + end + return candidateWinners +end + +local function AreAllyTeamsDoubleAllied(firstAllyTeamID, secondAllyTeamID) + -- we need to check for both directions of alliance + for teamA in pairs(allyTeamInfos[firstAllyTeamID].teams) do + for teamB in pairs(allyTeamInfos[secondAllyTeamID].teams) do + if not AreTeamsAllied(teamA, teamB) or not AreTeamsAllied(teamB, teamA) then + return false + end + end + end + return true +end + +local function CheckSharedAllyVictoryEnd() + -- we have to cross check all the alliances + local candidateWinners = {} + local winnerCountSquared = 0 + local aliveCount = 0 + for allyTeamA in pairs(allyTeamInfos) do + if IsCandidateWinner(allyTeamA) then + aliveCount = aliveCount + 1 + for allyTeamB in pairs(allyTeamInfos) do + if IsCandidateWinner(allyTeamB) and AreAllyTeamsDoubleAllied(allyTeamA, allyTeamB) then + -- store both check directions + -- since we're gonna check if we're allied against ourself, only secondAllyTeamID needs to be stored + candidateWinners[allyTeamB] = true + winnerCountSquared = winnerCountSquared + 1 + end + end + end + end + + if aliveCount*aliveCount ~= winnerCountSquared then + return false + end + + -- all the allyteams alive are bidirectionally allied against eachother, they are all winners + local winnersCorrectFormat = {} + for winner in pairs(candidateWinners) do + winnersCorrectFormat[#winnersCorrectFormat+1] = winner + end + return winnersCorrectFormat + +end + + +local function UpdateAllyTeamIsDead(allyTeamID) + local allyTeamInfo = allyTeamInfos[allyTeamID] + local dead = true + for teamID,teamInfo in pairs(allyTeamInfo.teams) do + if not playerQuitIsDead then + dead = dead and (teamInfo.dead or not teamInfo.hasLeader ) + else + dead = dead and (teamInfo.dead or not teamInfo.isControlled ) + end + end + allyTeamInfos[allyTeamID].dead = dead +end + +function gadget:GameFrame() + for _,playerID in ipairs(GetPlayerList()) do + CheckPlayer(playerID) -- because not all events that we want to test call gadget:PlayerChanged (e.g. allying) + end + local winners + if sharedDynamicAllianceVictory == 0 then + winners = CheckSingleAllyVictoryEnd() + else + winners = CheckSharedAllyVictoryEnd() + end + + if winners then + GameOver(winners) + end +end + + +function CheckPlayer(playerID) + local _,active,spectator,teamID = GetPlayerInfo(playerID) + local allyTeamID = teamToAllyTeam[teamID] + local teamInfo = allyTeamInfos[allyTeamID].teams[teamID] + teamInfo.players[playerID] = active and not spectator + teamInfo.hasLeader = select(2,GetTeamInfo(teamID)) >= 0 + if not teamInfo.hasLeader and not teamInfo.dead then + KillTeam(teamID) + Script.LuaRules.TeamDeathMessage(teamID) + end + if not teamInfo.isAI then + --if team isn't AI controlled, then we need to check if we have attached players + teamInfo.isControlled = false + for _,isControlling in pairs(teamInfo.players) do + if isControlling then + teamInfo.isControlled = true + break + end + end + end + --if player is an AI controller, then mark all hosted AIs as uncontrolled + local AIHostList = playerIDtoAIs[playerID] or {} + for AITeam, AIAllyTeam in pairs(AIHostList) do + allyTeamInfos[AIAllyTeam].teams[AITeam].isControlled = active + end + allyTeamInfos[allyTeamID].teams[teamID] = teamInfo + UpdateAllyTeamIsDead(allyTeamID) +end + + + +function gadget:TeamDied(teamID) + local allyTeamID = teamToAllyTeam[teamID] + local allyTeamInfo = allyTeamInfos[allyTeamID] + allyTeamInfo.teams[teamID].dead = true + allyTeamInfos[allyTeamID] = allyTeamInfo + UpdateAllyTeamIsDead(allyTeamID) + Script.LuaRules.TeamDeathMessage(teamID) +end + + +function gadget:UnitCreated(unitID, unitDefID, unitTeamID) + local allyTeamID = teamToAllyTeam[unitTeamID] + local allyTeamInfo = allyTeamInfos[allyTeamID] + allyTeamInfo.teams[unitTeamID].unitCount = allyTeamInfo.teams[unitTeamID].unitCount + 1 + allyTeamInfo.unitCount = allyTeamInfo.unitCount + 1 + allyTeamInfos[allyTeamID] = allyTeamInfo +end + +gadget.UnitGiven = gadget.UnitCreated +gadget.UnitCaptured = gadget.UnitCreated + +function gadget:UnitDestroyed(unitID, unitDefID, unitTeamID) + local allyTeamID = teamToAllyTeam[unitTeamID] + local allyTeamInfo = allyTeamInfos[allyTeamID] + local teamUnitCount = allyTeamInfo.teams[unitTeamID].unitCount -1 + local allyTeamUnitCount = allyTeamInfo.unitCount - 1 + allyTeamInfo.teams[unitTeamID].unitCount = teamUnitCount + allyTeamInfo.unitCount = allyTeamUnitCount + allyTeamInfos[allyTeamID] = allyTeamInfo + if allyTeamInfo.isGaia and ignoreGaia == 1 then + return + end + + if allyTeamUnitCount == 0 then + Script.LuaRules.AllyTeamDeathMessage(allyTeamID) + for teamID in pairs(allyTeamInfo.teams) do + KillTeam(teamID) + end + end +end + +gadget.UnitTaken = gadget.UnitDestroyed diff --git a/LuaRules/gadgets/game_over.lua b/LuaRules/gadgets/game_over.lua new file mode 100644 index 0000000..d081f02 --- /dev/null +++ b/LuaRules/gadgets/game_over.lua @@ -0,0 +1,455 @@ +function gadget:GetInfo() + return { + name = "Game Over", + desc = "GAME OVER!! (handles conditions thereof)", + author = "SirMaverick, Google Frog, KDR_11k, CarRepairer (unified by KingRaptor)", + date = "2009", + license = "GPL", + layer = 1, + enabled = true -- loaded by default? + } +end + +-------------------------------------------------------------------------------- +-- End game if only one allyteam with players AND units is left. +-- An allyteam is counted as dead if none of +-- its active players have units left. +-------------------------------------------------------------------------------- + +if (gadgetHandler:IsSyncedCode()) then + +--if Spring.GetModOption("zkmode",false,nil) == nil then +-- Spring.Echo(" Testing mode. Gadget removed.") +-- return +--end +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +local spGetTeamInfo = Spring.GetTeamInfo +local spGetTeamList = Spring.GetTeamList +local spGetTeamUnits = Spring.GetTeamUnits +local spDestroyUnit = Spring.DestroyUnit +local spGetAllUnits = Spring.GetAllUnits +local spGetAllyTeamList = Spring.GetAllyTeamList +local spGetPlayerInfo = Spring.GetPlayerInfo +local spGetPlayerList = Spring.GetPlayerList +local spAreTeamsAllied = Spring.AreTeamsAllied +local spGetUnitTeam = Spring.GetUnitTeam +local spGetUnitDefID = Spring.GetUnitDefID +local spGetUnitIsStunned= Spring.GetUnitIsStunned +local spGetUnitHealth = Spring.GetUnitHealth +local spGetUnitAllyTeam = Spring.GetUnitAllyTeam +local spTransferUnit = Spring.TransferUnit +local spKillTeam = Spring.KillTeam +local spGameOver = Spring.GameOver + +local COMM_VALUE = UnitDefNames.ecommander.metalCost or 150 +local ECON_SUPREMACY_MULT = 25 + +-------------------------------------------------------------------------------- +-- vars +-------------------------------------------------------------------------------- +local gaiaTeamID = Spring.GetGaiaTeamID() +local gaiaAllyTeamID = select(6, Spring.GetTeamInfo(gaiaTeamID)) +local chickenAllyTeamID + +local aliveCount = {} +local aliveValue = {} +local destroyedAlliances = {} +local allianceToReveal + +local finishedUnits = {} -- this stores a list of all units that have ever been completed, so it can distinguish between incomplete and partly reclaimed units +local toDestroy = {} + +local modOptions = Spring.GetModOptions() or {} +local destroy_type = modOptions.defeatmode or 'destroy' +local commends = tobool(modOptions.commends) +local noElo = tobool(modOptions.noelo) + +local revealed = false +local gameover = false + +local nilUnitDef = {id=-1} +local function GetUnitDefIdByName(defName) + return (UnitDefNames[defName] or nilUnitDef).id +end + +local doesNotCountList = { + [GetUnitDefIdByName("emine")] = true, + [GetUnitDefIdByName("emineai")] = true, + [GetUnitDefIdByName("edrone")] = true, +} + +-- auto detection of doesnotcount units +for name, ud in pairs(UnitDefs) do + if (ud.customParams.dontcount) then + doesNotCountList[ud.id] = true + elseif (ud.isFeature) then + doesNotCountList[ud.id] = true + elseif (not ud.canAttack) and (not ud.speed) and (not ud.isFactory) then + doesNotCountList[ud.id] = true + end +end + +local commsAlive = {} +local allyTeams = spGetAllyTeamList() +for i=1,#allyTeams do + commsAlive[allyTeams[i]] = {} +end + +local function IsPlayMode() + local sb_gameMode = Spring.GetGameRulesParam("sb_gameMode") + return sb_gameMode == nil or sb_gameMode == "play" +end +-------------------------------------------------------------------------------- +-- local funcs +-------------------------------------------------------------------------------- +local function GetTeamIsChicken(teamID) + local luaAI = Spring.GetTeamLuaAI(teamID) + if luaAI and string.find(string.lower(luaAI), "chicken") then + return true + end + return false +end + +local function CountAllianceUnits(allianceID) + local teamlist = spGetTeamList(allianceID) or {} + local count = 0 + for i=1,#teamlist do + local teamID = teamlist[i] + count = count + (aliveCount[teamID] or 0) + if (GG.waitingForComm or {})[teamID] then + count = count + 1 + end + end + return count +end + +local function CountAllianceValue(allianceID) + local teamlist = spGetTeamList(allianceID) or {} + local value = 0 + for i=1,#teamlist do + local teamID = teamlist[i] + value = value + (aliveValue[teamID] or 0) + if (GG.waitingForComm or {})[teamID] then + value = value + COMM_VALUE + end + end + return value +end + +local function HasNoComms(allianceID) + for unitID in pairs(commsAlive[allianceID]) do + return false + end + return true +end + +local function UnitWithinBounds(unitID) + local x, y, z = Spring.GetUnitPosition(unitID) + return (x > -500) and (x < Game.mapSizeX + 500) and (y > -1000) and (z > -500) and (z < Game.mapSizeZ + 500) +end + +-- if only one allyteam left, declare it the victor +local function CheckForVictory() + local allylist = spGetAllyTeamList() + local count = 0 + local lastAllyTeam + for _,a in pairs(allylist) do + if not destroyedAlliances[a] and (a ~= gaiaAllyTeamID) then + --Spring.Echo("Alliance " .. a .. " remains in the running") + count = count + 1 + lastAllyTeam = a + end + end + if count < 2 then + Spring.Echo(( (lastAllyTeam and ("Team " .. lastAllyTeam)) or "Nobody") .. " wins!") + spGameOver({lastAllyTeam}) + end +end + +local function RevealAllianceUnits(allianceID) + allianceToReveal = allianceID + local teamList = spGetTeamList(allianceID) + for i=1,#teamList do + local t = teamList[i] + local teamUnits = spGetTeamUnits(t) + for j=1,#teamUnits do + local u = teamUnits[j] + -- purge extra-map units + if not UnitWithinBounds(u) then + Spring.DestroyUnit(u) + else + Spring.SetUnitAlwaysVisible(u, true) + end + end + end +end + +-- purge the alliance! +local function DestroyAlliance(allianceID) + if not destroyedAlliances[allianceID] then + destroyedAlliances[allianceID] = true + local teamList = spGetTeamList(allianceID) + if teamList == nil then return end -- empty allyteam, don't bother + + if destroy_type == 'debug' then + Spring.Echo("Game Over: DEBUG") + Spring.Echo("Game Over: Allyteam " .. allianceID .. " has met the game over conditions.") + Spring.Echo("Game Over: If this is true, then please resign.") + return -- don't perform victory check + elseif destroy_type == 'destroy' then -- kaboom + Spring.Echo("Game Over: Destroying alliance " .. allianceID) + for i=1,#teamList do + local t = teamList[i] + local teamUnits = spGetTeamUnits(t) + for j=1,#teamUnits do + local u = teamUnits[j] + local pwUnits = (GG.PlanetWars or {}).unitsByID + if pwUnits and pwUnits[u] then + spTransferUnit(u, gaiaTeamID, true) -- don't blow up PW buildings + else + toDestroy[u] = true + end + end + spKillTeam(t) + end + elseif destroy_type == 'losecontrol' then -- no orders can be issued to team + Spring.Echo("Game Over: Destroying alliance " .. allianceID) + for i=1,#teamList do + spKillTeam(teamList[i]) + end + end + end + CheckForVictory() +end +GG.DestroyAlliance = DestroyAlliance + +local function AddAllianceUnit(u, ud, teamID) + local _, _, _, _, _, allianceID = spGetTeamInfo(teamID) + aliveCount[teamID] = aliveCount[teamID] + 1 + + aliveValue[teamID] = aliveValue[teamID] + UnitDefs[ud].metalCost + + --Spring.Echo("added alliance=" .. teamID, 'count='..aliveCount[allianceID]) + if UnitDefs[ud].customParams.commtype then + commsAlive[allianceID][u] = true + end +end + +local function RemoveAllianceUnit(u, ud, teamID) + local _, _, _, _, _, allianceID = spGetTeamInfo(teamID) + aliveCount[teamID] = aliveCount[teamID] - 1 + + aliveValue[teamID] = aliveValue[teamID] - UnitDefs[ud].metalCost + if aliveValue[teamID] < 0 then + aliveValue[teamID] = 0 + end + + --Spring.Echo("removed alliance=" .. teamID, 'count='..aliveCount[allianceID]) + if UnitDefs[ud].customParams.commtype then + commsAlive[allianceID][u] = nil + end + Spring.Echo("IsPlayMode()", IsPlayMode()) + if ((CountAllianceUnits(allianceID) <= 0) or (commends and HasNoComms(allianceID))) and (allianceID ~= chickenAllyTeamID) and IsPlayMode() then + Spring.Log(gadget:GetInfo().name, LOG.INFO, " Purging allyTeam " .. allianceID) + DestroyAlliance(allianceID) + end +end + +local function CompareArmyValues(ally1, ally2) + local value1, value2 = CountAllianceValue(ally1), CountAllianceValue(ally2) + if value1 > ECON_SUPREMACY_MULT*value2 then + return ally1 + elseif value2 > ECON_SUPREMACY_MULT*value1 then + return ally2 + end + return nil +end + +-- used during initialization +local function CheckAllUnits() + aliveCount = {} + local teams = spGetTeamList() + for i=1,#teams do + local teamID = teams[i] + if teamID ~= gaiaTeamID then + aliveCount[teamID] = 0 + end + end + local units = spGetAllUnits() + for i=1,#units do + local unitID = units[i] + local teamID = spGetUnitTeam(unitID) + local unitDefID = spGetUnitDefID(unitID) + gadget:UnitFinished(unitID, unitDefID, teamID) + end +end + +-- check for active players +local function ProcessLastAlly() + if Spring.IsCheatingEnabled() or destroy_type == 'debug' then + return + end + local allylist = spGetAllyTeamList() + local activeAllies = {} + local lastActive = nil + for i=1,#allylist do + repeat + local a = allylist[i] + if (a == gaiaAllyTeamID) then break end -- continue + if (destroyedAlliances[a]) then break end -- continue + local teamlist = spGetTeamList(a) + if (not teamlist) then break end -- continue + local activeTeams = 0 + for i=1,#teamlist do + local t = teamlist[i] + -- any team without units is dead to us; so only teams who are active AND have units matter + -- except chicken, who are alive even without units + local numAlive = aliveCount[t] + if #(Spring.GetTeamUnits(t)) == 0 then numAlive = 0 end + if (numAlive > 0) or (GG.waitingForComm or {})[t] or (GetTeamIsChicken(t)) then + local playerlist = spGetPlayerList(t, true) -- active players + if playerlist then + for j=1,#playerlist do + local _,active,spec = spGetPlayerInfo(playerlist[j]) + if active and not spec then + activeTeams = activeTeams + 1 + end + end + end + -- count AI teams as active + local _,_,_,isAiTeam = spGetTeamInfo(t) + if isAiTeam then + activeTeams = activeTeams + 1 + end + end + end + if activeTeams > 0 then + activeAllies[#activeAllies+1] = a + lastActive = a + end + until true + end -- for + + if #activeAllies == 2 then + if revealed then return end + if activeAllies[1] == chickenAllyTeamID or activeAllies[2] == chickenAllyTeamID then + return + end + -- run value comparison + local supreme = CompareArmyValues(activeAllies[1], activeAllies[2]) + if supreme then + Spring.Echo("AllyTeam " .. supreme .. " has an overwhelming numerical advantage!") + for i=1, #allylist do + local a = allylist[i] + if (a ~= supreme) and (a ~= gaiaAllyTeamID) then + RevealAllianceUnits(a) + revealed = true + end + end + end + elseif #activeAllies < 2 then + -- remove every unit except for last active alliance + for i=1, #allylist do + local a = allylist[i] + if (a ~= lastActive)and(a ~= gaiaAllyTeamID) and IsPlayMode() then + DestroyAlliance(a) + end + end + end +end + +-------------------------------------------------------------------------------- +-- callins +-------------------------------------------------------------------------------- + +function gadget:UnitFinished(u, ud, team) + if (team ~= gaiaTeamID) + and(not doesNotCountList[ud]) + and(not finishedUnits[u]) + then + finishedUnits[u] = true + AddAllianceUnit(u, ud, team) + end +end + +function gadget:UnitCreated(u, ud, team) + if revealed then + local allyTeam = select(6, spGetTeamInfo(team)) + if allyTeam == allianceToReveal then + Spring.SetUnitAlwaysVisible(u, true) + end + end +end + +function gadget:UnitDestroyed(u, ud, team) + if (team ~= gaiaTeamID) + and(not doesNotCountList[ud]) + and finishedUnits[u] + then + finishedUnits[u] = nil + RemoveAllianceUnit(u, ud, team) + end + toDestroy[u] = nil +end + +-- note: Taken comes before Given +function gadget:UnitGiven(u, ud, newTeam, oldTeam) + if (newTeam ~= gaiaTeamID) + and(not doesNotCountList[ud]) + and(not select(3,spGetUnitIsStunned(u))) + then + AddAllianceUnit(u, ud, newTeam) + end +end + +function gadget:UnitTaken(u, ud, oldTeam, newTeam) + if (oldTeam ~= gaiaTeamID) + and(not doesNotCountList[ud]) + and(select(5,spGetUnitHealth(u))>=1) + then + RemoveAllianceUnit(u, ud, oldTeam) + end +end + +function gadget:Initialize() + local teams = spGetTeamList() + for i=1,#teams do + aliveValue[teams[i]] = 0 + if GetTeamIsChicken(teams[i]) then + Spring.Log(gadget:GetInfo().name, LOG.INFO, " Chicken team found") + chickenAllyTeamID = select(6, Spring.GetTeamInfo(teams[i])) + --break + end + end + + CheckAllUnits() + + Spring.Log(gadget:GetInfo().name, LOG.INFO, "Game Over initialized") +end + +function gadget:GameFrame(n) + -- check for last ally: + -- end condition: only 1 ally with human players, no AIs in other ones + if (n % 45 == 0) then + for u in pairs(toDestroy) do + spDestroyUnit(u, true) + end + toDestroy = {} + if not gameover then + ProcessLastAlly() + end + end +end + +function gadget:GameOver() + gameover = true + if noElo then + Spring.SendCommands("wbynum 255 SPRINGIE:noElo") + end + Spring.Log(gadget:GetInfo().name, LOG.INFO, "GAME OVER!!") +end + +else -- UNSYNCED + +end