Keep track of singleplayer high scores in challenges
authorWuzzy <Wuzzy2@mail.ru>
Wed, 19 Dec 2018 05:50:02 +0100
changeset 14496 2113296b7a29
parent 14495 2c3fb87ad1c5
child 14497 f86bd14a7613
child 14498 4b678aad50e9
Keep track of singleplayer high scores in challenges
ChangeLog.txt
share/hedgewars/Data/Maps/ClimbHome/map.lua
share/hedgewars/Data/Missions/Challenge/Basic_Training_-_Sniper_Rifle.lua
share/hedgewars/Data/Missions/Challenge/User_Mission_-_RCPlane_Challenge.lua
share/hedgewars/Data/Missions/Challenge/User_Mission_-_Rope_Knock_Challenge.lua
share/hedgewars/Data/Missions/Challenge/User_Mission_-_That_Sinking_Feeling.lua
share/hedgewars/Data/Scripts/SpeedShoppa.lua
share/hedgewars/Data/Scripts/TargetPractice.lua
share/hedgewars/Data/Scripts/Utils.lua
--- a/ChangeLog.txt	Wed Dec 19 01:47:41 2018 +0100
+++ b/ChangeLog.txt	Wed Dec 19 05:50:02 2018 +0100
@@ -3,6 +3,7 @@
 ============== 1.0.0-dev (unreleased) ==============
  + Hand-drawn maps can now be scaled with slider
  + Show check mark for completed scenarios, challenges and trainings
+ + Track high scores in singleplayer challenges
  + New chat command: “/help room” (shows room chat commands within the game)
  + Colorize switching arrows, pointing arrow and target cross in clan color
  + Longer delays between turns so its easier to see damage and messages
@@ -22,6 +23,7 @@
  + New call: GetMissionVar(varname): Get value of mission variable
  + New call: SetTurnTimePaused(isPaused): Call with true to pause turn time, false to unpause
  + New call: GetTurnTimePaused(): Returns true if turn time is paused due to Lua
+ + Utils library: New calls: getReadableChallengeRecord, updateChallengeRecord
  + New callback: onGameResult(winningClan): Called when the game ends normally. winningClan = index of winning clan or -1 on draw
  + Params explode, poison in the SpawnFake*Crate functions now optional and default to false
 
--- a/share/hedgewars/Data/Maps/ClimbHome/map.lua	Wed Dec 19 01:47:41 2018 +0100
+++ b/share/hedgewars/Data/Maps/ClimbHome/map.lua	Wed Dec 19 05:50:02 2018 +0100
@@ -128,9 +128,14 @@
 function onGameStart()
     --SetClanColor(ClansCount-1, 0x0000ffff) appears to be broken
     SendHealthStatsOff()
+    local recordInfo = ""
+    if isSinglePlayer then
+        recordInfo = getReadableChallengeRecord("Highscore")
+    end
     ShowMission(loc("Climb Home"),
                 loc("Challenge"),
-                loc("You are far from home, and the water is rising, climb up as high as you can!|Your score will be based on your height."),
+                loc("You are far from home, and the water is rising, climb up as high as you can!|Your score will be based on your height.")
+                .. "|" .. recordInfo,
                 -amRope, 0)
     local x = 1818
     for h,i in pairs(HH) do
@@ -419,7 +424,8 @@
             end
         end
 
-        local finishTime = (GameTime-startTime)/1000
+        local rawFinishTime = GameTime-startTime
+        local finishTime = rawFinishTime/1000
         local roundedFinishTime = math.ceil(math.floor(finishTime+0.5))
         if isSinglePlayer then
             if distanceFromWater < 0 and not YouLost and not YouWon then
@@ -439,7 +445,9 @@
                 SendStat(siGameResult, loc("You have beaten the challenge!"))
                 SendStat(siGraphTitle, loc("Your height over time"))
                 SendStat(siCustomAchievement, string.format(loc("%s reached home in %.3f seconds. Congratulations!"), GetHogName(CurrentHedgehog), finishTime))
+                updateChallengeRecord("TimeRecord", rawFinishTime, false)
                 SendStat(siCustomAchievement, string.format(loc("%s bravely climbed up to a dizzy height of %d to reach home."), GetHogName(CurrentHedgehog), getActualHeight(RecordHeight)))
+                updateChallengeRecord("Highscore", getActualHeight(RecordHeight))
                 SendStat(siPointType, loc("seconds"))
                 SendStat(siPlayerKills, tostring(roundedFinishTime), GetHogTeamName(CurrentHedgehog))
 
@@ -683,6 +691,8 @@
     else
         SendStat(siCustomAchievement, string.format(text, RecordHeightHogName))
     end
+
+    updateChallengeRecord("Highscore", actualHeight)
     SendStat(siPointType, loc("points"))
     SendStat(siPlayerKills, actualHeight, GetHogTeamName(CurrentHedgehog))
     EndGame()
--- a/share/hedgewars/Data/Missions/Challenge/Basic_Training_-_Sniper_Rifle.lua	Wed Dec 19 01:47:41 2018 +0100
+++ b/share/hedgewars/Data/Missions/Challenge/Basic_Training_-_Sniper_Rifle.lua	Wed Dec 19 05:50:02 2018 +0100
@@ -13,6 +13,7 @@
 -- about translations.
 -- We can use the function loc(text) to localize a string.
 
+HedgewarsScriptLoad("/Scripts/Utils.lua")
 HedgewarsScriptLoad("/Scripts/Locale.lua")
 
 -- This variable will hold the number of destroyed targets.
@@ -147,13 +148,16 @@
 	-- Spawn the first target.
 	spawnTarget(860,1020)
 
+	local highscore = getReadableChallengeRecord("Highscore")
 	-- Show some nice mission goals.
 	-- Parameters are: caption, sub caption, description,
 	-- extra text, icon and time to show.
 	-- A negative icon parameter (-n) represents the n-th weapon icon
 	-- A positive icon paramter (n) represents the (n+1)-th mission icon
 	-- A timeframe of 0 is replaced with the default time to show.
-	ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."), -amSniperRifle, 0)
+	ShowMission(loc("Sniper Training"), loc("Aiming Practice"),
+	loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission.")
+	.. "|" .. highscore, -amSniperRifle, 0)
 
 	-- Displayed initial player score
 	SetTeamLabel(playerTeamName, "0")
@@ -433,5 +437,6 @@
 	end
 	SendStat(siPointType, loc("points"))
 	SendStat(siPlayerKills, tostring(end_score_overall), playerTeamName)
+	updateChallengeRecord("Highscore", end_score_overall)
 end
 
--- a/share/hedgewars/Data/Missions/Challenge/User_Mission_-_RCPlane_Challenge.lua	Wed Dec 19 01:47:41 2018 +0100
+++ b/share/hedgewars/Data/Missions/Challenge/User_Mission_-_RCPlane_Challenge.lua	Wed Dec 19 05:50:02 2018 +0100
@@ -1,3 +1,4 @@
+HedgewarsScriptLoad("/Scripts/Utils.lua")
 HedgewarsScriptLoad("/Scripts/Locale.lua")
 HedgewarsScriptLoad("/Scripts/Achievements.lua")
 
@@ -46,13 +47,14 @@
 
 	SendHealthStatsOff()
 
+	local recordInfo = getReadableChallengeRecord("Lowscore")
 	ShowMission     (
                                 loc("RC Plane Challenge"),
                                 loc("Challenge"),
 
                                 loc("Collect or destroy all the health crates.") .. "|" ..
                                 loc("Compete to use as few planes as possible!") .. "|" ..
-								"", -amRCPlane, 4000
+                                recordInfo, -amRCPlane, 4000
                                 )
 	SetTeamLabel(loc("Wannabe Flyboys"), "0")
 
@@ -408,6 +410,7 @@
 				SendStat(siCustomAchievement, string.format(loc("You have used %d RC planes."), planesUsed))
 			end
 			SaveMissionVar("Won", "true")
+			updateChallengeRecord("Lowscore", planesUsed)
 		
 			if(totalMissiles > 1) then
 				SendStat(siCustomAchievement, string.format(loc("You have dropped %d missiles."), totalMissiles))
--- a/share/hedgewars/Data/Missions/Challenge/User_Mission_-_Rope_Knock_Challenge.lua	Wed Dec 19 01:47:41 2018 +0100
+++ b/share/hedgewars/Data/Missions/Challenge/User_Mission_-_Rope_Knock_Challenge.lua	Wed Dec 19 05:50:02 2018 +0100
@@ -1,3 +1,4 @@
+HedgewarsScriptLoad("/Scripts/Utils.lua")
 HedgewarsScriptLoad("/Scripts/Locale.lua")
 
 local hhs = {}
@@ -98,6 +99,10 @@
 	SendStat(siPointType, loc("points"))
 	SendStat(siPlayerKills, tostring(score), playerTeamName)
 	PlaySound(sndHellish)
+
+	-- Update highscore
+	updateChallengeRecord("Highscore", score)
+
 	EndGame()
 end
 
@@ -117,6 +122,9 @@
 	SendStat(siPlayerKills, tostring(score), playerTeamName)
 	SetTeamLabel(playerTeamName, tostring(score))
 
+	-- Update highscore
+	updateChallengeRecord("Highscore", score)
+
 	if hhs[0] and GetHealth(hhs[0]) then
 		SetEffect(hhs[0], heInvulnerable, 1)
 	end
@@ -188,11 +196,17 @@
 function onGameStart()
 	SendHealthStatsOff()
 
+	local recordInfo = getReadableChallengeRecord("Highscore")
+	if recordInfo == nil then
+		recordInfo = ""
+	else
+		recordInfo = "|" .. recordInfo
+	end
 	ShowMission     (
                         loc("Rope-knocking Challenge"),
                         loc("Challenge"),
                         loc("Use the rope to knock your enemies to their doom.") .. "|" ..
-                        loc("Finish this challenge as fast as possible to earn bonus points."),
+                        loc("Finish this challenge as fast as possible to earn bonus points.").. recordInfo,
                         -amRope, 4000)
 	SetTeamLabel(playerTeamName, "0")
 
--- a/share/hedgewars/Data/Missions/Challenge/User_Mission_-_That_Sinking_Feeling.lua	Wed Dec 19 01:47:41 2018 +0100
+++ b/share/hedgewars/Data/Missions/Challenge/User_Mission_-_That_Sinking_Feeling.lua	Wed Dec 19 05:50:02 2018 +0100
@@ -1,6 +1,7 @@
 
 
 HedgewarsScriptLoad("/Scripts/Locale.lua")
+HedgewarsScriptLoad("/Scripts/Utils.lua")
 HedgewarsScriptLoad("/Scripts/Achievements.lua")
 
 local player
@@ -15,6 +16,17 @@
 local watGear = nil
 local cinematic = false
 
+function printMission()
+	local highscore = tonumber(GetMissionVar("Highscore"))
+	local show = (type(highscore) == "number") and (highscore > 0)
+	local recordInfo = ""
+	if show then
+		recordInfo = getReadableChallengeRecord("Highscore")
+	end
+	ShowMission(loc("That Sinking Feeling"), loc("Challenge"), loc("Save as many hapless hogs as possible!")
+	.. "|" .. recordInfo, 4, 0)
+end
+
 -- allow skipping of the intro via hitting precise key
 function onPrecise()
 	if introStage < 100 then
@@ -22,7 +34,7 @@
 		genCounter = 0
 		FollowGear(CurrentHedgehog)
 		AddCaption(loc("Good luck out there!"))
-		ShowMission(loc("That Sinking Feeling"), loc("Challenge"), loc("Save as many hapless hogs as possible!"), 4, 0)
+		printMission()
 		SetInputMask(0xFFFFFFFF)
 	end
 end
@@ -70,11 +82,12 @@
 
 
 function onGameStart()
-    cinematic = true
-    SetCinematicMode(true)
+	cinematic = true
+	SetCinematicMode(true)
 	SendHealthStatsOff()
 
-	ShowMission(loc("That Sinking Feeling"), loc("Challenge"), loc("Save as many hapless hogs as possible!"), 4, 1)
+	printMission()
+	HideMission()
 
 	HogTurnLeft(hh[0], false)
 	HogTurnLeft(hh[1], true)
@@ -241,6 +254,9 @@
 
 				SendStat(siCustomAchievement, string.format(loc("You saved %d of 8 Hapless Hogs."), hhLeft))
 
+				-- Update highscore
+				updateChallengeRecord("Highscore", hhLeft)
+
 				if hhLeft == 8 then
 					SaveMissionVar("Won", "true")
 					awardAchievement(loc("Lively Lifeguard"))
@@ -293,6 +309,9 @@
 		end
 		SendStat(siPointType, loc("points"))
 		SendStat(siPlayerKills, "0", loc("Nameless Heroes"))
+		local highscore = tonumber(GetMissionVar("Highscore"))
+		show = (type(highscore) == "number") and (highscore > 0)
+		updateChallengeRecord("Highscore", 0, show)
 
 		SendStat(siGameResult, loc("Disqualified!"))
 		GameOver = true
--- a/share/hedgewars/Data/Scripts/SpeedShoppa.lua	Wed Dec 19 01:47:41 2018 +0100
+++ b/share/hedgewars/Data/Scripts/SpeedShoppa.lua	Wed Dec 19 05:50:02 2018 +0100
@@ -21,6 +21,7 @@
 
 ]=]
 
+HedgewarsScriptLoad("/Scripts/Utils.lua")
 HedgewarsScriptLoad("/Scripts/Locale.lua")
 
 --[[
@@ -115,7 +116,8 @@
 
 	_G.onGameStart = function()
 		SendHealthStatsOff()
-		ShowMission(params.missionTitle, loc("Challenge"), params.goalText, -amRope, 5000) 
+		local append = getReadableChallengeRecord("TimeRecord")
+		ShowMission(params.missionTitle, loc("Challenge"), params.goalText .. "|" .. append, -amRope, 5000)
 		-- <crates collected>/<total number of crates>
 		SetTeamLabel(params.teamName, string.format(loc("%d/%d"), cratesCollected, #crates))
 		for i=1,#crates do
@@ -176,6 +178,7 @@
 				SendStat(siPlayerKills, tostring(time), params.teamName)
 				SendStat(siCustomAchievement, string.format(loc("You have finished the challenge in %.3f s."), (time/1000)))
 				SetTurnTimeLeft(0)
+				updateChallengeRecord("TimeRecord", time)
 			else
 				SendStat(siGameResult, loc("Challenge failed!"))
 				SendStat(siPointType, loc("crate(s)"))
--- a/share/hedgewars/Data/Scripts/TargetPractice.lua	Wed Dec 19 01:47:41 2018 +0100
+++ b/share/hedgewars/Data/Scripts/TargetPractice.lua	Wed Dec 19 05:50:02 2018 +0100
@@ -55,6 +55,7 @@
 ----- snip -----
 ]=]
 
+HedgewarsScriptLoad("/Scripts/Utils.lua")
 HedgewarsScriptLoad("/Scripts/Locale.lua")
 
 local player = nil
@@ -167,7 +168,8 @@
 
 	_G.onGameStart = function()
 		SendHealthStatsOff()
-		ShowMission(params.missionTitle, loc("Aiming practice"), params.goalText, -params.ammoType, 5000)
+		local recordInfo = getReadableChallengeRecord("Highscore")
+		ShowMission(params.missionTitle, loc("Aiming practice"), params.goalText .. "|" .. recordInfo, -params.ammoType, 5000)
 		SetTeamLabel(params.teamName, "0")
 		spawnTarget()
 	end
@@ -317,5 +319,7 @@
 		end
 		SendStat(siPointType, loc("point(s)"))
 		SendStat(siPlayerKills, tostring(end_score_overall), loc(params.teamName))
+		-- Update highscore
+		updateChallengeRecord("Highscore", end_score_overall)
 	end
 end
--- a/share/hedgewars/Data/Scripts/Utils.lua	Wed Dec 19 01:47:41 2018 +0100
+++ b/share/hedgewars/Data/Scripts/Utils.lua	Wed Dec 19 05:50:02 2018 +0100
@@ -1,5 +1,7 @@
 -- Library for miscellaneous utilitiy functions and global helper variables
 
+HedgewarsScriptLoad("/Scripts/Locale.lua")
+
 --[[ FUNCTIONS ]]
 -- Check if a gear is inside a box
 function gearIsInBox(gear, x, y, w, h)
@@ -33,6 +35,59 @@
 	end
 end
 
+local function challengeRecordToString(recordType, value)
+	if recordType == "TimeRecord" or recordType == "TimeRecordHigh" then
+		return string.format(loc("Team record: %.3fs"), value/1000)
+	elseif recordType == "Highscore" then
+		return string.format(loc("Team high score: %d"), value)
+	else
+		return string.format(loc("Team record: %d"), value)
+	end
+end
+
+function getReadableChallengeRecord(recordType)
+	local record = tonumber(GetMissionVar(recordType))
+	if type(record) ~= "number" then
+		return ""
+	else
+		return challengeRecordToString(recordType, record)
+	end
+end
+
+function updateChallengeRecord(recordType, value, stat)
+	local oldRecord = tonumber(GetMissionVar(recordType))
+	local newRecord = false
+	if stat == nil then
+		stat = true
+	end
+	if type(oldRecord) ~= "number" then
+		newRecord = true
+	else
+		local recordBeaten = false
+		if recordType == "Lowscore" or recordType == "TimeRecord" then
+			if value < oldRecord then
+				recordBeaten = true
+				newRecord = true
+			end
+		else
+			if value > oldRecord then
+				recordBeaten = true
+				newRecord = true
+			end
+		end
+		if stat then
+			if recordBeaten then
+				SendStat(siCustomAchievement, loc("You have beaten the team record, congratulations!"))
+			else
+				SendStat(siCustomAchievement, challengeRecordToString(recordType, oldRecord))
+			end
+		end
+	end
+	if newRecord then
+		SaveMissionVar(recordType, value)
+	end
+end
+
 -- Completely fill the map with land. Requires MapGen=mgDrawn.
 -- If flush is false, FlushPoints() is not called.
 function fillMap(flush)