# HG changeset patch # User Wuzzy # Date 1535427993 -7200 # Node ID 0da36902e5b6ae64d6aa333734734e43da86bfd6 # Parent e2b1abb4fba58c86dabe23e37aeb160b8b70fe04 Space Invasion: Continue playing rounds in case the teams are tied at the end Rules in case of a tie: 1) Eliminate all teams not tied for the lead 2) Play another round with the remaining teams 3) Check for the winner again at the end of that round. If there's another tie, repeat the procedure diff -r e2b1abb4fba5 -r 0da36902e5b6 ChangeLog.txt --- a/ChangeLog.txt Tue Aug 28 03:45:44 2018 +0200 +++ b/ChangeLog.txt Tue Aug 28 05:46:33 2018 +0200 @@ -67,6 +67,7 @@ Space Invasion: + Display round score in a separate row + Keep round score displayed after round ends, remove round score announcer message + + If team scores are tied at the end, continue playing rounds with the tied teams until there's a winner * Fix rare Lua error message spam at end of game * Fix round score and other info numbers messing up after screen resize * Fix kamikaze bonus not being shown diff -r e2b1abb4fba5 -r 0da36902e5b6 share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua Tue Aug 28 03:45:44 2018 +0200 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua Tue Aug 28 05:46:33 2018 +0200 @@ -89,8 +89,6 @@ -- add support for other world edges (they are currently disabled) --- maybe add a check for a tie, IMPOSSIBRU THERE ARE NO TIES - -- if more weapons are added, replace primshotsfired all over the place -- look for derp and let invaders shoot again @@ -148,13 +146,10 @@ SI.preciseOn = false SI.roundLimit = 3 -- can be overridden by script parameter "rounds" SI.roundNumber = 0 -SI.firstClan = 10 +SI.lastRound = -1 SI.gameOver = false SI.gameBegun = false -SI.bestClan = 65535 -SI.bestScore = 0 - -- for script parameters -- NOTE: If you change this, also change the default “Space Invasion” game scheme SI.startBarrels = 5 -- "barrels" @@ -172,8 +167,8 @@ SI.numhhs = 0 SI.hhs = {} -SI.numTeams = 0 SI.teamNameArr = {} +SI.teamNameArrReverse = {} SI.teamClan = {} SI.teamSize = {} SI.teamIndex = {} @@ -390,33 +385,12 @@ SI.teamCircsKilled[i] = 0 SI.teamSurfer[i] = false end - SI.numTeams = 0 - - for i = 0, (SI.numhhs-1) do - - local z = 0 - local unfinished = true - while(unfinished == true) do - - local newTeam = true - local tempHogTeamName = GetHogTeamName(SI.hhs[i]) -- this is the new name - - if tempHogTeamName == SI.teamNameArr[z] then - newTeam = false - unfinished = false - end - - z = z + 1 - - if z == (TeamsCount-1) then - unfinished = false - if newTeam == true then - SI.teamNameArr[SI.numTeams] = tempHogTeamName - SI.numTeams = SI.numTeams + 1 - end - end - - end + + for i=0, TeamsCount-1 do + + local name = GetTeamName(i) + SI.teamNameArr[i] = name + SI.teamNameArrReverse[name] = i end @@ -500,6 +474,11 @@ return newAward end +-- Update scoreboard and check victory state. +-- Returns 2 bools: +-- 1: true if game over +-- 2: true if game's not over but we're playing now in tie-breaking phase + function CommentOnScore() local teamStats = {} for i = 0,(TeamsCount-1) do @@ -521,7 +500,7 @@ local comment = teamStats[i].name .. " |" .. string.format(loc("Score: %d"), teamStats[i].score) .. "|" .. string.format(loc("Kills: %d"), teamStats[i].kills) - if i < TeamsCount then + if i < TeamsCount then comment = comment .. "| |" end table.insert(teamComment, comment) @@ -533,20 +512,40 @@ table.insert(teamComment, comment) end + local roundLimitHit = SI.roundNumber >= SI.roundLimit + local tie = teamStats[1].score == teamStats[2].score + local lGameOver = roundLimitHit and (not tie) + local entireC = "" + for i = TeamsCount,1,-1 do entireC = entireC .. teamComment[i] end + local statusText, scoreText - if SI.roundNumber >= SI.roundLimit then + -- Game is over + if lGameOver then statusText = loc("Game over!") scoreText = loc("Final team scores:") - else + -- Round is over and game is not yet complete + elseif not roundLimitHit then AddCaption(string.format(loc("Rounds complete: %d/%d"), SI.roundNumber, SI.roundLimit), capcolDefault, capgrpMessage) - return + return lGameOver, false + -- Teams are tied for the lead at the end + elseif roundLimitHit and tie then + local tieBreakingRound = SI.roundNumber - SI.roundLimit + 1 + local msg + if tieBreakingRound == 1 then + msg = loc("Teams are tied! Continue playing rounds until we have a winner!") + else + msg = string.format(loc("Tie-breaking round %d"), tieBreakingRound) + end + AddCaption(msg, capcolDefault, capgrpMessage) + return lGameOver, true end + local displayTime - if SI.roundNumber >= SI.roundLimit then + if lGameOver then displayTime = 20000 else displayTime = 1 @@ -556,7 +555,7 @@ string.format(loc("Rounds complete: %d/%d"), SI.roundNumber, SI.roundLimit) .. "| " .. "|" .. scoreText .. " |" ..entireC, 4, displayTime) - if SI.roundNumber >= SI.roundLimit then + if lGameOver then local winnerTeam = teamStats[1].name for i = 0, (SI.numhhs-1) do if GetHogTeamName(SI.hhs[i]) == winnerTeam then @@ -583,7 +582,17 @@ --[[ Award some awards (just for fun, its for the stats screen only and has no effect on the score or game outcome. ]] local awardsGiven = 0 - + + if SI.roundNumber == SI.roundLimit + 1 then + SendStat(siCustomAchievement, + loc("The teams were tied, so an additional round has been played to determine the winner.")) + awardsGiven = awardsGiven + 1 + elseif SI.roundNumber > SI.roundLimit then + SendStat(siCustomAchievement, + string.format(loc("The teams were tied, so %d additional rounds have been played to determine the winner."), + SI.roundNumber - SI.roundLimit)) + awardsGiven = awardsGiven + 1 + end if SI.awardTotalKills >= 30 then awardsGiven = awardsGiven + 1 SendStat(siCustomAchievement, @@ -683,30 +692,36 @@ elseif r == 3 then text = loc("Nothing of interest has happened.") elseif r == 4 then text = loc("There are no snarky comments this time.") end - + SendStat(siCustomAchievement, text) end end + + return lGameOver, false end function onNewRound() + SI.lastRound = TotalRounds SI.roundNumber = SI.roundNumber + 1 - CommentOnScore() - - -- end game if its at round limit - if SI.roundNumber >= SI.roundLimit then - + local lGameOver, lTied = CommentOnScore() + local bestScore = 0 + local bestClan = -1 + + -- Game has been determined to be over, so end it + if lGameOver then + + -- Get winning score for i = 0, (TeamsCount-1) do - if SI.teamScore[i] > SI.bestScore then - SI.bestScore = SI.teamScore[i] - SI.bestClan = SI.teamClan[i] + if SI.teamScore[i] > bestScore then + bestScore = SI.teamScore[i] + bestClan = SI.teamClan[i] end end -- Kill off all the losers for i = 0, (SI.numhhs-1) do - if GetHogClan(SI.hhs[i]) ~= SI.bestClan then + if GetHogClan(SI.hhs[i]) ~= bestClan then SetEffect(SI.hhs[i], heResurrectable, 0) SetHealth(SI.hhs[i],0) end @@ -717,13 +732,66 @@ EndTurn(true) SI.TimeLeft = 0 SendStat(siGraphTitle, loc("Score graph")) + + -- Round limit passed and teams are tied! + elseif lTied then + -- Enter (or continue) tie-breaking phase... + + -- Rules in case of a tie: + -- 1) All teams that are not tied for the lead are killed (they can't play anymore, but they will keep their score and be ranked normally) + -- 2) Another round is played with the remaining teams + -- 3) After this round, scores are checked again to determine a winner. If there's a tie again, this procedure is repeated + + -- Get leading teams + for i = 0, (TeamsCount-1) do + if SI.teamScore[i] > bestScore then + bestScore = SI.teamScore[i] + end + end + + local tiedForTheLead = {} + for i = 0, (TeamsCount-1) do + if SI.teamScore[i] == bestScore then + tiedForTheLead[i] = true + end + end + + local wasCurrent = false + -- Kill teams not in the top + for i = 0, (SI.numhhs-1) do + local hog = SI.hhs[i] + if GetHealth(hog) then -- check if hog is still alive + local team = SI.teamNameArrReverse[GetHogTeamName(hog)] + if team and tiedForTheLead[team] ~= true then + -- hilarious loser face + SetState(hog, bor(GetState(hog), gstLoser)) + -- die! + SetEffect(hog, heResurrectable, 0) + SetHealth(hog, 0) + -- Note the death might not trigger immediately since we + -- zero the health at the beginning of a turn rather than + -- the end of one. + -- It's just a minor visual thing, not a big deal. + if hog == CurrentHedgehog then + wasCurrent = true + end + end + end + end + + -- if current hedgehog was among the loser, end the turn + if wasCurrent then + EndTurn(true) + end + + -- From that point on, the game just continues normally ... end end -- gaudy racer function CheckForNewRound() - if GetHogClan(CurrentHedgehog) == SI.firstClan then + if TotalRounds > 0 and TotalRounds > SI.lastRound then onNewRound() end @@ -1108,7 +1176,6 @@ if (SI.gameOver == false) and (SI.gameBegun == false) then SI.gameBegun = true SI.roundNumber = 0 -- 0 - SI.firstClan = GetHogClan(CurrentHedgehog) end if SI.gameOver == true then @@ -1303,7 +1370,7 @@ value = SI.shotsHit, } end - + end -- other awards