mirror of
https://github.com/CorsixTH/CorsixTH.git
synced 2025-07-23 04:13:01 +02:00
Encourage level restarts on very_old_saves (#2518)
* Encourage level restarts on very_old_saves Changes this UIInformation to a UIConfirmDIalog for old saves. * Add overhauled save version logs * Add Dutch, Czech, French, Spanish translation --- Co-authored-by: jansakos Co-authored-by: Alberth <alberth289346@gmail.com> Co-authored-by: Antoine Lemaire <2025537+AntoineLemaire@users.noreply.github.com> Co-authored-by: Stephen E. Baker <baker.stephen.e@gmail.com>
This commit is contained in:
@@ -96,7 +96,7 @@ function App:init()
|
||||
print("")
|
||||
print("---------------------------------------------------------------")
|
||||
print("")
|
||||
print("Welcome to CorsixTH " .. self:getVersion() .. "!")
|
||||
print("Welcome to CorsixTH " .. self:getReleaseString() .. "!")
|
||||
print("")
|
||||
print("---------------------------------------------------------------")
|
||||
print("")
|
||||
@@ -1680,60 +1680,136 @@ function App:loadLuaFolder(dir, no_results, append_to)
|
||||
end
|
||||
end
|
||||
|
||||
--! Returns the version number (name) of the local copy of the game based on
|
||||
--! which save game version it is. This was added after the Beta 8
|
||||
--! release, which is why the checks prior to that version aren't made.
|
||||
--!param version An optional value if you want to find what game version
|
||||
-- a specific savegame version is from.
|
||||
function App:getVersion(version)
|
||||
local ver = version or self.savegame_version
|
||||
--[[
|
||||
CorsixTH versioning follows a convention similar to semantic versioning but it
|
||||
does not accurately follow its standard. As we are currently <1.0.0 the major
|
||||
integer is not at play. Instead:
|
||||
Minor - denotes an new milestone of the program that often encompassses multiple
|
||||
patches that could break savegames without in-situ afterLoads
|
||||
Revision - denotes a revised hotfix release of the program that patches a major
|
||||
bug before the next milestone. The bug is then patched for the next milestone.
|
||||
Moving forward, revisions should have a savegame_version bump of 1, as 10
|
||||
savegame versions are reserved each release for patching.
|
||||
All beta versions must have a savegame increment each time
|
||||
Each patch note must begin with a '-'
|
||||
--]]
|
||||
local release_table = {
|
||||
-- Format: major, minor, revision, patch (string), savegame_version
|
||||
{major = 0, minor = 0, revision = 8, patch = "", version = 0}, -- Beta 8 or below
|
||||
{major = 0, minor = 1, revision = 0, patch = "", version = 51},
|
||||
{major = 0, minor = 10, revision = 0, patch = "", version = 53},
|
||||
{major = 0, minor = 11, revision = 0, patch = "", version = 54},
|
||||
{major = 0, minor = 20, revision = 0, patch = "", version = 66},
|
||||
{major = 0, minor = 21, revision = 0, patch = "", version = 72},
|
||||
{major = 0, minor = 30, revision = 0, patch = "", version = 78},
|
||||
{major = 0, minor = 40, revision = 0, patch = "", version = 91},
|
||||
{major = 0, minor = 50, revision = 0, patch = "", version = 105},
|
||||
{major = 0, minor = 60, revision = 0, patch = "", version = 111},
|
||||
{major = 0, minor = 61, revision = 0, patch = "", version = 122},
|
||||
{major = 0, minor = 62, revision = 0, patch = "", version = 127},
|
||||
{major = 0, minor = 63, revision = 0, patch = "", version = 134},
|
||||
{major = 0, minor = 64, revision = 0, patch = "", version = 138},
|
||||
{major = 0, minor = 65, revision = 0, patch = "", version = 156},
|
||||
-- There was also 0.65.1, not differentiated by version number
|
||||
{major = 0, minor = 66, revision = 0, patch = "", version = 170},
|
||||
{major = 0, minor = 67, revision = 0, patch = "", version = 180},
|
||||
{major = 0, minor = 68, revision = 0, patch = "", version = 194},
|
||||
{major = 0, minor = 69, revision = 0, patch = "-beta-1", version = 216}
|
||||
}
|
||||
|
||||
-- Versioning format is major.minor.revision (required) Patch (optional)
|
||||
-- Old versions (<= 0.67) retain existing format
|
||||
-- All patch versions should be retained in this table (due to be replaced, see PR2518)
|
||||
if ver > 216 then
|
||||
return "Trunk"
|
||||
elseif ver > 194 then
|
||||
return "v0.69.0-beta1"
|
||||
elseif ver > 180 then
|
||||
return "v0.68.0"
|
||||
elseif ver > 170 then
|
||||
return "v0.67"
|
||||
elseif ver > 156 then
|
||||
return "v0.66"
|
||||
elseif ver > 138 then
|
||||
return "v0.65"
|
||||
elseif ver > 134 then
|
||||
return "v0.64"
|
||||
elseif ver > 127 then
|
||||
return "v0.63"
|
||||
elseif ver > 122 then
|
||||
return "v0.62"
|
||||
elseif ver > 111 then
|
||||
return "v0.61"
|
||||
elseif ver > 105 then
|
||||
return "v0.60"
|
||||
elseif ver > 91 then
|
||||
return "0.50"
|
||||
elseif ver > 78 then
|
||||
return "0.40"
|
||||
elseif ver > 72 then
|
||||
return "0.30"
|
||||
elseif ver > 66 then
|
||||
return "0.21"
|
||||
elseif ver > 54 then
|
||||
return "0.20"
|
||||
elseif ver > 53 then
|
||||
return "0.11"
|
||||
elseif ver > 51 then
|
||||
return "0.10"
|
||||
elseif ver > 45 then
|
||||
return "0.01"
|
||||
else
|
||||
return "Beta 8 or earlier"
|
||||
--! Retrieve the current savegame version as defined in the application.
|
||||
function App:getCurrentVersion()
|
||||
return self.savegame_version
|
||||
end
|
||||
|
||||
--! Requests data regarding a given savegame version
|
||||
--!param savegame_version (number) What to lookup, uses application version if blank
|
||||
--!return the matching release table entry
|
||||
-- If no releases match it returns the base release with the savegame version
|
||||
-- inserted
|
||||
function App:getReleaseData(savegame_version)
|
||||
savegame_version = savegame_version or self:getCurrentVersion()
|
||||
local release_data
|
||||
for i = #release_table, 1, -1 do
|
||||
local release = release_table[i]
|
||||
if release.version == savegame_version then
|
||||
release_data = release
|
||||
break
|
||||
elseif (release.version - savegame_version) < 0 then
|
||||
-- we're not on a release version
|
||||
local develop = shallow_clone(release) -- prevent recursion
|
||||
develop.version = savegame_version
|
||||
develop.patch = release.patch .. "-dev" .. savegame_version
|
||||
release_data = develop
|
||||
break
|
||||
end
|
||||
end
|
||||
return release_data
|
||||
end
|
||||
|
||||
--! Provides the release (or development) string for a given savegame version
|
||||
--!param savegame_version (number) The version to look up
|
||||
--!return A string in the format "v<major>.<minor>.<revision>[patch]"
|
||||
--! For development builds, the savegame version is appended as a patch e.g. 'dev213'
|
||||
function App:getReleaseString(savegame_version)
|
||||
local release = self:getReleaseData(savegame_version)
|
||||
local release_string = "v" .. release.major .. "." .. release.minor .. "." ..
|
||||
release.revision
|
||||
release_string = release_string .. release.patch
|
||||
return release_string
|
||||
end
|
||||
|
||||
--! Reports a difference between two versions based on requested methodology.
|
||||
--!param version_a (number or table) The first (usually newer) version to test
|
||||
--!param version_b (number or table) The second (usually older) version to test
|
||||
--!param method (string) What method to compare by
|
||||
--- method(release) reports the difference between the matching releases in steps,
|
||||
--- revisions are not counted.
|
||||
--- For development builds it will use the base release it started from when using
|
||||
--- the release method
|
||||
--- method(version) reports the difference between two savegame versions
|
||||
--!return The step difference between release a and release b for release method
|
||||
--- or The raw savegame version difference for version method
|
||||
function App:compareVersions(version_a, version_b, method)
|
||||
assert(type(version_a) == "table" or type(version_a) == "number",
|
||||
"version_a requires savegame version or an entry from the version table to compare")
|
||||
assert(type(version_b) == "table" or type(version_b) == "number",
|
||||
"version_b requires savegame version or an entry from the version table to compare")
|
||||
assert(method == "release" or method == "version",
|
||||
"Not using a valid compare method")
|
||||
|
||||
if method == "release" then
|
||||
local function countBackward(version_to_check)
|
||||
local step = 0
|
||||
for i = #release_table, 1, -1 do
|
||||
local release = release_table[i]
|
||||
if release.version == version_to_check then
|
||||
break
|
||||
elseif (release.version - version_to_check) < 0 then
|
||||
-- we're not on a release version
|
||||
if step == 0 then step = 1 break end -- working from current development
|
||||
break
|
||||
end
|
||||
if release.revision == 0 and release.patch == "" then
|
||||
step = step - 1
|
||||
end
|
||||
end
|
||||
return step
|
||||
end
|
||||
|
||||
if type(version_a) == "number" then version_a = self:getReleaseData(version_a) end
|
||||
if type(version_b) == "number" then version_b = self:getReleaseData(version_b) end
|
||||
return countBackward(version_a.version) - countBackward(version_b.version)
|
||||
end
|
||||
|
||||
if method == "version" then
|
||||
local a = version_a.version or version_a
|
||||
local b = version_b.version or version_b
|
||||
return a - b
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function App:save(filename)
|
||||
return SaveGameFile(filename)
|
||||
end
|
||||
@@ -1821,9 +1897,10 @@ function App:_checkOrFind(test_file, campaign_dir)
|
||||
end
|
||||
|
||||
--! Restarts the current level (offers confirmation window first)
|
||||
function App:restart()
|
||||
--!param message (string) Optional message to the player
|
||||
function App:restart(message)
|
||||
assert(self.map, "Trying to restart while no map is loaded.")
|
||||
self.ui:addWindow(UIConfirmDialog(self.ui, false, _S.confirmation.restart_level,
|
||||
self.ui:addWindow(UIConfirmDialog(self.ui, true, message or _S.confirmation.restart_level,
|
||||
--[[persistable:app_confirm_restart]] function()
|
||||
self:worldExited()
|
||||
local campaign_info = self.world.campaign_info
|
||||
@@ -1882,9 +1959,9 @@ function App:afterLoad()
|
||||
local first = self.world.original_savegame_version
|
||||
|
||||
-- Generate the human-readable version number (old [loaded save], new [program], first [original])
|
||||
local first_version = first .. " (" .. self:getVersion(first) .. ")"
|
||||
local old_version = old .. " (" .. self:getVersion(old) .. ")"
|
||||
local new_version = new .. " (" .. self:getVersion() .. ")"
|
||||
local first_version = first .. " (" .. self:getReleaseString(first) .. ")"
|
||||
local old_version = old .. " (" .. self:getReleaseString(old) .. ")"
|
||||
local new_version = new .. " (" .. self:getReleaseString(new) .. ")"
|
||||
|
||||
if new == old then
|
||||
local msg_same = "Savegame version is %s, originally it was %s."
|
||||
@@ -1900,7 +1977,7 @@ function App:afterLoad()
|
||||
self.world:gameLog(msg_newer:format(old_version, new_version))
|
||||
self.ui:addWindow(UIInformation(self.ui, { _S.warnings.newersave }))
|
||||
end
|
||||
self.world.release_version = self:getVersion()
|
||||
self.world.release_version = self:getReleaseString(new)
|
||||
self.world.savegame_version = new
|
||||
|
||||
if old < 87 then
|
||||
@@ -1944,11 +2021,11 @@ function App:checkForUpdates()
|
||||
|
||||
-- Default language to use for the changelog if no localised version is available
|
||||
local default_language = "en"
|
||||
local current_version = self:getVersion()
|
||||
local current_version = self:getReleaseString()
|
||||
|
||||
-- Only check for updates against released versions
|
||||
if current_version == "Trunk" then
|
||||
print("Will not check for updates since this is the Trunk version.")
|
||||
if string.find(current_version, "dev") then
|
||||
print("Will not check for updates since this is a development version.")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -2057,7 +2134,7 @@ function App:gamelogHeader()
|
||||
table.concat(comp_details, ", "), self.video:getRendererDetails())
|
||||
local running = string.format("%s run with api version: %s, game version: %s, savegame version: %s\n",
|
||||
compile_opts.jit or _VERSION, tostring(corsixth.require("api_version")),
|
||||
self:getVersion(), tostring(SAVEGAME_VERSION))
|
||||
self:getReleaseString(), tostring(SAVEGAME_VERSION))
|
||||
return (compiled .. running)
|
||||
end
|
||||
|
||||
|
@@ -68,7 +68,8 @@ function UIMainMenu:UIMainMenu(ui)
|
||||
-- Work out the menu's height, giving extra space for the version information
|
||||
local line_height = 15
|
||||
local top_padding = 20
|
||||
local num_lines = computeSize({TheApp:isUpdateCheckDisabledByConfig(), TheApp.config.debug, TheApp:getVersion()}) -- see UIMainMenu:draw for how these are used
|
||||
local release_string = TheApp:getReleaseString()
|
||||
local num_lines = computeSize({TheApp:isUpdateCheckDisabledByConfig(), TheApp.config.debug, release_string}) -- see UIMainMenu:draw for how these are used
|
||||
local bottom_text_height = (line_height * num_lines)
|
||||
self.height = top_padding + ((menu_item_height + 10) * #menu_items) + bottom_text_height
|
||||
|
||||
@@ -81,7 +82,7 @@ function UIMainMenu:UIMainMenu(ui)
|
||||
|
||||
-- The main menu also shows the version number of the player's copy of the game.
|
||||
self.label_font = TheApp.gfx:loadFontAndSpriteTable("QData", "Font01V", nil, nil, 0, 0, label_ttf_col)
|
||||
self.version_number = TheApp:getVersion()
|
||||
self.release_string = release_string
|
||||
|
||||
-- individual buttons
|
||||
self.default_button_sound = "selectx.wav"
|
||||
@@ -126,7 +127,7 @@ function UIMainMenu:draw(canvas, x, y)
|
||||
self.label_font:draw(canvas, _S.main_menu.savegame_version .. TheApp.savegame_version, x + 5, ly, 190, 0, "right")
|
||||
ly = ly - 15
|
||||
end
|
||||
self.label_font:draw(canvas, _S.main_menu.version .. self.version_number, x + 5, ly, 190, 0, "right")
|
||||
self.label_font:draw(canvas, _S.main_menu.version .. self.release_string, x + 5, ly, 190, 0, "right")
|
||||
end
|
||||
|
||||
function UIMainMenu:onTick()
|
||||
|
@@ -303,6 +303,8 @@ confirmation = {
|
||||
return_to_blueprint = "Jste si jisti, že se chcete vrátit do režimu Návrhu?",
|
||||
maximum_screen_size = "Velikost obrazovky, kterou jste zadali, je vyšší než 3000 x 2000. Na tato rozlišení lze přejít za předpokladu, že máte hardware schopný tuto hru udržet v hratelné rychlosti. Opravdu chcete pokračovat?",
|
||||
remove_destroyed_room = "Opravdu chcete odebrat místnost? Bude to stát $%d.",
|
||||
very_old_save = "Od doby, kdy jste začali s touto hrou, jsme již mnohokrát program aktualizovali. Chcete teď restartovat úroveň, pro jistotu, že vše správně funguje?//" ..
|
||||
"Vaše uložené rozehrané hry nebudou smazány, dokud je sami nepřepíšete novým uložením.",
|
||||
}
|
||||
adviser = {
|
||||
goals = {
|
||||
|
@@ -2582,6 +2582,7 @@ confirmation = { --spaces on the end make the text fit properly in text windows
|
||||
maximum_screen_size = "De resolutie die je hebt ingevoerd is groter dan 3000x2000. Een hoge resolutie is mogelijk, mits je hardware goed genoeg is om een speelbare framerate te behalen. Weet je zeker dat je wilt doorgaan?",
|
||||
replace_machine_extra_info = "De nieuwe machine zal %d vermogen hebben (momenteel %d)",
|
||||
remove_destroyed_room = "Wil je de kamer voor $%d verwijderen?",
|
||||
very_old_save = "Er zijn veel updates geweest sinds je met dit level bent begonnen. Om zeker te zijn dat alles werkt zoals het hoort, zou je nu opnieuw willen beginnen dit level?//Je opgeslagen spel blijft beschikbaar tenzij je het overschrijft.",
|
||||
}
|
||||
menu_display = {
|
||||
mcga_lo_res = " LAGE RES ",
|
||||
|
@@ -799,13 +799,14 @@ confirmation = {
|
||||
replace_machine_extra_info = "The new machine will have %d strength (currently %d).",
|
||||
restart_mapeditor = "Are you sure you want to restart the map editor?",
|
||||
quit_mapeditor = "Are you sure you want to quit the map editor?",
|
||||
very_old_save = "There have been a lot of updates to the game since you started. To be sure that all features work as intended would you like to restart this level now?//" ..
|
||||
"Your old save won't be deleted unless you overwrite it.",
|
||||
}
|
||||
|
||||
information = {
|
||||
custom_game = "Welcome to CorsixTH. Have fun with this custom map!",
|
||||
no_custom_game_in_demo = "Sorry, but in the demo version you can't play any custom maps.",
|
||||
cannot_restart = "Unfortunately this custom game was saved before the restart feature was implemented.",
|
||||
very_old_save = "There have been a lot of updates to the game since you started this level. To be sure that all features work as intended please consider restarting it.",
|
||||
level_lost = {
|
||||
"Bummer! You failed the level. Better luck next time!",
|
||||
"The reason you lost:",
|
||||
@@ -1039,6 +1040,7 @@ tooltip.status = {
|
||||
|
||||
options_window.change_resolution = "Change resolution"
|
||||
tooltip.options_window.change_resolution = "Change the window resolution to the dimensions entered on the left"
|
||||
information.very_old_save = "There have been a lot of updates to the game since you started this level. To be sure that all features work as intended please consider restarting it."
|
||||
|
||||
cheats_window.cheats = {
|
||||
toggle_infected = show_infected,
|
||||
|
@@ -1046,7 +1046,9 @@ confirmation = {
|
||||
abort_edit_room = "Vous êtes actuellement en train de construire ou d'éditer une pièce. Si tous les objets requis sont placés, elle sera validée, mais sinon elle sera détruite. Continuer ?",
|
||||
maximum_screen_size = "La taille de l'écran que vous avez entrée est supérieure à 3000 x 2000. Des plus hautes résolutions sont possibles, mais il faudra un meilleur matériel afin de maintenir un taux de trame jouable. Êtes-vous sûr de vouloir continuer?",
|
||||
remove_destroyed_room = "Souhaitez-vous supprimer la salle pour %d $ ?",
|
||||
replace_machine_extra_info = "La nouvelle machine aura une puissance de %d (actuellement %d)."
|
||||
replace_machine_extra_info = "La nouvelle machine aura une puissance de %d (actuellement %d).",
|
||||
very_old_save = "Il y a eu de nombreuses mises à jour du jeu depuis que vous avez commencé. Pour être sûr que toutes les fonctionnalités fonctionnent comme prévu, voudriez-vous recommencer ce niveau maintenant ?//"..
|
||||
"Votre ancienne sauvegarde ne sera pas supprimée à moins que vous ne l'écrasiez."
|
||||
}
|
||||
|
||||
-- Information dialog
|
||||
|
@@ -1212,6 +1212,8 @@ confirmation = {
|
||||
music_warning = "Nota: Necesitas el archivo smpeg.dll o el equivalente para tu sistema operativo, de lo contrario no tendrás música en el juego. ¿Quieres continuar?",
|
||||
remove_destroyed_room = "¿Te gustaría eliminar la habitación por $%d?",
|
||||
replace_machine_extra_info = "La nueva máquina tendrá una resistencia de %d (actualmente es de %d).",
|
||||
very_old_save = "Ha habido muchas actualizaciones en el juego desde que comenzaste. Para asegurarte de que todas las características funcionen como se espera, ¿te gustaría reiniciar este nivel ahora?//" ..
|
||||
"Tu archivo de guardado anterior no se eliminará a menos que lo sobrescribas."
|
||||
}
|
||||
|
||||
information = {
|
||||
|
@@ -90,7 +90,7 @@ function World:World(app, free_build_mode)
|
||||
self.floating_dollars = {}
|
||||
self.game_log = {} -- saves list of useful debugging information
|
||||
self.savegame_version = app.savegame_version -- Savegame version number
|
||||
self.release_version = app:getVersion(self.savegame_version) -- Savegame release version (e.g. 0.60), or Trunk
|
||||
self.release_version = app:getReleaseString() -- Savegame release version (e.g. 0.60), or Trunk
|
||||
-- Also preserve this throughout future updates.
|
||||
self.original_savegame_version = app.savegame_version
|
||||
|
||||
@@ -2175,16 +2175,6 @@ end
|
||||
--!param old (integer) The old version of the save game.
|
||||
--!param new (integer) The current version of the save game format.
|
||||
function World:afterLoad(old, new)
|
||||
|
||||
if not self.original_savegame_version then
|
||||
self.original_savegame_version = old
|
||||
end
|
||||
-- If the original save game version is considerably lower than the current, warn the player.
|
||||
-- For 2024 release, bump cutoff from 20 to 25 pending new methods in PR2518
|
||||
if new - 25 > self.original_savegame_version then
|
||||
self.ui:addWindow(UIInformation(self.ui, {_S.information.very_old_save}))
|
||||
end
|
||||
|
||||
self:setUI(self.ui)
|
||||
|
||||
-- insert global compatibility code here
|
||||
@@ -2571,9 +2561,19 @@ function World:afterLoad(old, new)
|
||||
self:previousSpeed()
|
||||
|
||||
self.earthquake:afterLoad(old, new)
|
||||
|
||||
-- Savegame version housekeeping
|
||||
if not self.original_savegame_version then
|
||||
self.original_savegame_version = old
|
||||
end
|
||||
-- If the original save game version is considerably lower than the current, ask
|
||||
-- the player if they want to restart the level.
|
||||
if TheApp:compareVersions(new, old, "release") > 2 then
|
||||
TheApp:restart(_S.confirmation.very_old_save)
|
||||
end
|
||||
self.savegame_version = new
|
||||
self.release_version = TheApp:getVersion(new)
|
||||
self.system_pause = false -- Reset flag on load
|
||||
self.release_version = TheApp:getReleaseString(new)
|
||||
self:setSystemPause(false) -- Reset flag on load
|
||||
end
|
||||
|
||||
function World:playLoadedEntitySounds()
|
||||
|
Reference in New Issue
Block a user