Climb Home: Fix game getting stuck when player reaches home
authorWuzzy <almikes@aol.com>
Thu, 05 Oct 2017 17:39:04 +0200
changeset 12653 1215fd246e08
parent 12652 31c4a81823eb
child 12654 26b0d3b76dea
Climb Home: Fix game getting stuck when player reaches home What now happens if a player reaches home: - sndWinning - Show caption with finishing time - Winning hog is teleported to roof and can be seen by everyone - 4 second delay - If there are still hogs left, the game continues normally - Each victory is mentioned in stats screen at the end
ChangeLog.txt
share/hedgewars/Data/Maps/ClimbHome/map.lua
--- a/ChangeLog.txt	Thu Oct 05 05:20:25 2017 +0200
+++ b/ChangeLog.txt	Thu Oct 05 17:39:04 2017 +0200
@@ -249,7 +249,8 @@
  * Portal Mind Challenge was cleaned up and reworked (especially less awful wording)
  * Fixed Target Practice missions getting stuck when a target dropped into water
  * Fixed mistakes and bad wording of strings in several missions, scripts and campaigns
- * Fixed Lua error messages and broken stats screen in Climb Home singleplayer mission
+ * Climb Home: Fix game getting stuck when a player reached home in multiplayer
+ * Climb Home: Fix Lua error messages and broken stats screen
 
 Frontend:
  + Campaign screen shows which campaigns and missions you've completed so far
--- a/share/hedgewars/Data/Maps/ClimbHome/map.lua	Thu Oct 05 05:20:25 2017 +0200
+++ b/share/hedgewars/Data/Maps/ClimbHome/map.lua	Thu Oct 05 17:39:04 2017 +0200
@@ -46,6 +46,21 @@
 local airMineY = {}
 local airMine = {}
 local init = true
+local multiplayerVictoryDelay = -1
+local multiplayerWinningHogs = {}
+local multiplayerWins = 0
+
+-- Placement positions of winning hogs
+local victoryPosses = { }
+do
+    local m = 0
+    for y=108, 39, -32 do
+        for x=1820+m, 1972-m, 22 do
+            table.insert(victoryPosses, {x=x, y=y})
+        end
+        m = m + 32
+    end
+end
 
 function onParameters()
     parseParams()
@@ -167,7 +182,7 @@
     recordBroken = false
     currTeam = GetHogTeamName(CurrentHedgehog)
     if CurrentHedgehog ~= nil then
-        if CurrentHedgehog ~= dummyHog then
+        if CurrentHedgehog ~= dummyHog or multiplayerWinningHogs[CurrentHedgehog] == true then
             SetGearPosition(CurrentHedgehog, 1951,32640)
             if not HogsAreInvulnerable then SetEffect(CurrentHedgehog,heInvulnerable,0) end
             AddVisualGear(1951,32640,vgtExplosion,0,false)
@@ -178,6 +193,9 @@
             dummySkip = GameTime+1
         end
     end
+    for hog, _ in pairs(multiplayerWinningHogs) do
+        SetEffect(hog, heInvulnerable, 1)
+    end
     for f,i in pairs(Fire) do
         DeleteGear(f)
     end
@@ -257,6 +275,39 @@
         --end
     end
 
+    -- This will be executed if a player reached home in multiplayer
+    if multiplayerVictoryDelay > 0 then
+        multiplayerVictoryDelay = multiplayerVictoryDelay - 20
+        if multiplayerVictoryDelay <= 0 then
+            -- If delay's over, the game will continue with the next hog
+            if CurrentHedgehog then
+
+                multiplayerWinningHogs[CurrentHedgehog] = true
+                multiplayerWins = multiplayerWins + 1
+
+                local victoryX, victoryY
+                if multiplayerWins <= #victoryPosses then
+                    victoryX, victoryY = victoryPosses[multiplayerWins].x, victoryPosses[multiplayerWins].y
+                else
+                    victoryX, victoryY = victoryPosses[#victoryPosses].x, victoryPosses[#victoryPosses].y
+                end
+                SetGearPosition(CurrentHedgehog, victoryX, victoryY)
+                SetEffect(CurrentHedgehog, heInvulnerable, 1)
+                SetHealth(CurrentHedgehog, 1)
+
+                if (deadHedgehogs + multiplayerWins) >= totalHedgehogs then
+                    makeFinalMultiPlayerStats()
+                    EndGame()
+                    onAchievementsDeclaration()
+                else
+                    EndTurn(true)
+                    SetInputMask(0xFFFFFFFF)
+                end
+                return
+            end
+        end
+    end
+
     if CurrentHedgehog ~= nil then x,y = GetGearPosition(CurrentHedgehog) end
     if Cake ~= nil and CurrentHedgehog ~= nil then
         local cx,cy = GetGearPosition(Cake)
@@ -354,14 +405,15 @@
                 }
             end
         end
+            local finishTime = (GameTime-startTime)/1000
+            local roundedFinishTime = math.ceil(math.floor(finishTime+0.5))
             if isSinglePlayer then
                 if distanceFromWater < 0 and not YouLost and not YouWon then
                     makeSinglePlayerLoserStats()
                     YouLost = true
                 end
+                -- FIXME: Hog is also in winning box if it just walks into the chair from the left, touching it. Intentional?
                 if not YouWon and not YouLost and gearIsInBox(CurrentHedgehog, 1920, 252, 50, 50) then
-                    local finishTime = (GameTime-startTime)/1000
-                    local roundedFinishTime = math.ceil(math.floor(finishTime+0.5))
                     AddCaption(loc("Victory!"))
                     ShowMission(loc("Climb Home"),
                                 loc("Made it!"),
@@ -380,14 +432,34 @@
                     onAchievementsDeclaration()
                     YouWon = true
                 end
-            elseif distanceFromWater < 0 and not YouLost then
-                makeMultiPlayerLoserStat(CurrentHedgehog)
-                deadHedgehogs = deadHedgehogs + 1
-                YouLost = true
-                if deadHedgehogs >= totalHedgehogs then
-                    makeFinalMultiPlayerStats()
-                    EndGame()
-                    onAchievementsDeclaration()
+            else
+                if distanceFromWater < 0 and not YouLost and not YouWon then
+                    makeMultiPlayerLoserStat(CurrentHedgehog)
+                    deadHedgehogs = deadHedgehogs + 1
+                    YouLost = true
+                    if deadHedgehogs >= totalHedgehogs then
+                        makeFinalMultiPlayerStats()
+                        EndGame()
+                        onAchievementsDeclaration()
+                    end
+                end
+                -- Check victory
+                if not YouWon and not YouLost and gearIsInBox(CurrentHedgehog, 1920, 252, 50, 50) and
+                        -- Delay victory if MrMine is triggered
+                        (not MrMine or (MrMine and band(GetState(MrMine), gstAttacking) == 0)) then
+                    -- Player managed to reach home in multiplayer.
+                    -- Stop hog, disable controls, celebrate victory and continue the game after 4 seconds.
+                    AddCaption(string.format(loc("%s climbed home in %d seconds!"), GetHogName(CurrentHedgehog), roundedFinishTime))
+                    SendStat(siCustomAchievement, string.format(loc("%s (%s) reached home in %.3f seconds."), GetHogName(CurrentHedgehog), GetHogTeamName(CurrentHedgehog), finishTime))
+                    makeMultiPlayerWinnerStat(CurrentHedgehog)
+                    PlaySound(sndVictory, CurrentHedgehog)
+                    -- TODO: Unselect weapon.
+                    -- Note: SetWeapon(amNothing) does not work. :-(
+                    SetGearMessage(CurrentHedgehog, band(GetGearMessage(CurrentHedgehog), bnot(gmLeft+gmRight+gmUp+gmDown+gmHJump+gmLJump+gmPrecise)))
+                    SetInputMask(0x00)
+                    -- TODO: Add stupid winner grin.
+                    multiplayerVictoryDelay = 4000
+                    YouWon = true
                 end
             end
 
@@ -541,7 +613,7 @@
             makeSinglePlayerLoserStats()
         else
             deadHedgehogs = deadHedgehogs + 1
-            if deadHedgehogs >= totalHedgehogs then
+            if (deadHedgehogs + multiplayerWins) >= totalHedgehogs then
                 makeFinalMultiPlayerStats()
                 EndGame()
                 onAchievementsDeclaration()
@@ -606,6 +678,10 @@
     --SendStat(siClanHealth, tostring(teamBests[teamName]), teamName)
 end
 
+function makeMultiPlayerWinnerStat(gear)
+    return makeMultiPlayerLoserStat(gear)
+end
+
 function makeFinalMultiPlayerStats()
     local ranking = {}
     for k,v in pairs(teamBests) do