mirror of
https://github.com/CorsixTH/CorsixTH.git
synced 2025-07-23 04:13:01 +02:00
Merge pull request #2735 from tobylane/mapoverlay
Add level file overlays
This commit is contained in:
@@ -635,15 +635,15 @@ function App:loadCampaign(campaign_file)
|
||||
campaign_info.winning_text_table)
|
||||
|
||||
if self:loadLevel(level_info.path, nil, level_info.name,
|
||||
level_info.map_file, level_info.briefing, nil, _S.errors.load_level_prefix, campaign_info) then
|
||||
level_info.map_file, level_info.briefing, nil, _S.errors.load_level_prefix, campaign_info) and self.world then
|
||||
-- The new world needs to know which campaign to continue on.
|
||||
self.world.campaign_info = campaign_info
|
||||
end
|
||||
|
||||
-- Play the level advance movie from a position where this campaign will end at 12
|
||||
if campaign_info.movie then
|
||||
local n = math.max(1, 12 - #campaign_info.levels)
|
||||
self.moviePlayer:playAdvanceMovie(n)
|
||||
-- Play the level advance movie from a position where this campaign will end at 12
|
||||
if campaign_info.movie then
|
||||
local n = math.max(1, 12 - #campaign_info.levels)
|
||||
self.moviePlayer:playAdvanceMovie(n)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -769,7 +769,7 @@ function App:_loadLevel(level, difficulty, level_name, level_file, level_intro,
|
||||
local new_map = Map(self)
|
||||
local map_objects, errors = new_map:load(level, difficulty, level_name, level_file, level_intro, map_editor)
|
||||
if not map_objects then
|
||||
self.world.ui:addWindow(UIInformation(self.ui, { errors }))
|
||||
self.ui:addWindow(UIInformation(self.ui, { errors }))
|
||||
return
|
||||
end
|
||||
-- If going from another level, save progress.
|
||||
|
@@ -197,7 +197,7 @@ end
|
||||
|
||||
function UINewGame:startGame(difficulty)
|
||||
if self.ui.app:loadLevel(1, difficulty, nil, nil, nil, nil,
|
||||
_S.errors.load_level_prefix, nil) then
|
||||
_S.errors.load_level_prefix, nil) and self.ui.app.world then
|
||||
self.ui.app.moviePlayer:playAdvanceMovie(1)
|
||||
|
||||
-- Initiate campaign progression. The UI above may now have changed.
|
||||
|
@@ -774,7 +774,14 @@ errors = {
|
||||
full_in_demo = "Sorry, you can't open a full game save with the demo files loaded. Please update your TH Data folder setting.",
|
||||
},
|
||||
music = "There are playback issues with one or more files in your music directory. Problematic files will be disabled in the jukebox. See the console window for more information.",
|
||||
missing_corsixth_file = "Warning: Could not find file %s, try reinstalling CorsixTH.",
|
||||
missing_th_data_file = "Warning: Could not find file %s, the Theme Hospital data is incomplete.",
|
||||
missing_level_file = "Error: Could not find the chosen level file.",
|
||||
overlay = {
|
||||
incorrect_difficulty = "Overlay difficulty must be easy, full or hard. Current value is ",
|
||||
incorrect_level_number = "Overlay level number must be 1-12. Current value is ",
|
||||
missing_setting = "No difficulty and level number given in overlay field of custom level.",
|
||||
},
|
||||
cannot_restart_missing_files = "Sorry, but this level cannot be restarted because of missing files %s or %s.",
|
||||
}
|
||||
|
||||
|
@@ -167,32 +167,26 @@ the original game levels are considered.
|
||||
!param map_file (string) The path to the map file as supplied by the config file.
|
||||
!param level_intro (string) If loading a custom level this message will be shown as soon as the level
|
||||
has been loaded.
|
||||
!return objects (table) The loaded map objects if successfully loaded
|
||||
!return errors (string) A localised error message if objects were not successfully loaded
|
||||
]]
|
||||
function Map:load(level, difficulty, level_name, map_file, level_intro, map_editor)
|
||||
local objects, _
|
||||
local objects
|
||||
if not difficulty then
|
||||
difficulty = "full"
|
||||
end
|
||||
-- Load CorsixTH base configuration for all levels.
|
||||
-- We want to load the file again each time.
|
||||
local function file (filename)
|
||||
local f = assert(loadfile(filename))
|
||||
return f()
|
||||
end
|
||||
|
||||
local result = file(self.app:getFullPath({"Lua", "base_config.lua"}))
|
||||
local base_config = result
|
||||
-- Load CorsixTH base configuration for all levels.
|
||||
local base_config = loadfile(self.app:getFullPath({"Lua", "base_config.lua"}))
|
||||
if not base_config then
|
||||
return nil, _S.errors.missing_corsixth_file:format("base_config.lua")
|
||||
end
|
||||
base_config = base_config()
|
||||
assert(base_config, "No base config has been loaded!")
|
||||
|
||||
if type(level) == "number" then
|
||||
local errors, data
|
||||
-- Playing the original campaign.
|
||||
-- Add TH's base config if possible, otherwise our own config
|
||||
-- roughly corresponds to "full".
|
||||
errors, base_config = self:loadMapConfig(difficulty .. "00.SAM", base_config)
|
||||
-- If it couldn't be loaded the new difficulty level is full no matter what.
|
||||
if errors then
|
||||
difficulty = "full"
|
||||
end
|
||||
self.difficulty = difficulty
|
||||
local errors, data, _, result
|
||||
self.level_number = level
|
||||
data, errors = self:getRawData(map_file)
|
||||
if data then
|
||||
@@ -207,22 +201,19 @@ function Map:load(level, difficulty, level_name, map_file, level_intro, map_edit
|
||||
local demo_path = self.app:getFullPath({"Levels", "demo.level"})
|
||||
errors, result = self:loadMapConfig(demo_path, base_config, true)
|
||||
if errors then
|
||||
print("Warning: Could not find the demo configuration, try reinstalling the game")
|
||||
return nil, _S.errors.missing_corsixth_file:format("demo.level")
|
||||
end
|
||||
self.difficulty = "full"
|
||||
self.level_config = result
|
||||
else
|
||||
local level_no = level
|
||||
if level_no < 10 then
|
||||
level_no = "0" .. level
|
||||
errors, result = self:_loadOriginalCampaignLevel(difficulty, level, base_config)
|
||||
if errors then
|
||||
return nil, errors
|
||||
end
|
||||
-- Override with the specific configuration for this level
|
||||
_, result = self:loadMapConfig(difficulty .. level_no .. ".SAM", base_config)
|
||||
-- Finally load additional CorsixTH config per level
|
||||
local level_path = self.app:getFullPath({"Levels", "original" .. level_no .. ".level"})
|
||||
_, result = self:loadMapConfig(level_path, result, true)
|
||||
self.level_config = result
|
||||
end
|
||||
elseif map_editor then
|
||||
local _
|
||||
-- We're being fed data by the map editor.
|
||||
self.level_name = "MAP EDITOR"
|
||||
self.level_number = "MAP EDITOR"
|
||||
@@ -236,10 +227,9 @@ function Map:load(level, difficulty, level_name, map_file, level_intro, map_edit
|
||||
return nil, errors
|
||||
end
|
||||
end
|
||||
assert(base_config, "No base config has been loaded!")
|
||||
|
||||
self.level_config = base_config
|
||||
else
|
||||
local _, result
|
||||
-- We're loading a custom level.
|
||||
self.level_name = level_name
|
||||
self.level_intro = level_intro
|
||||
@@ -252,10 +242,9 @@ function Map:load(level, difficulty, level_name, map_file, level_intro, map_edit
|
||||
else
|
||||
return nil, errors
|
||||
end
|
||||
assert(base_config, "No base config has been loaded!")
|
||||
errors, result = self:loadMapConfig(level, base_config, true)
|
||||
if errors then
|
||||
print(errors)
|
||||
return nil, errors
|
||||
end
|
||||
self.level_config = result
|
||||
end
|
||||
@@ -279,6 +268,46 @@ function Map:load(level, difficulty, level_name, map_file, level_intro, map_edit
|
||||
return objects
|
||||
end
|
||||
|
||||
-- A set of the TH campaign levels with additional CorsixTH config files, found in CorsixTH/Levels.
|
||||
local additional_config = list_to_set({"05", "07", "08", 11, 12})
|
||||
|
||||
--! Load further level configurations for the main campaign.
|
||||
--!param difficulty (string)
|
||||
--!param level_number (integer)
|
||||
--!param config (table) The level config created so far
|
||||
--!return error (string) Localised error message if error happens
|
||||
--!return config (table) Level config, if loaded successfully
|
||||
function Map:_loadOriginalCampaignLevel(difficulty, level_number, config)
|
||||
local errors
|
||||
if level_number < 10 then
|
||||
level_number = "0" .. level_number
|
||||
end
|
||||
-- Add TH's base config if possible, otherwise our own config,
|
||||
-- which roughly corresponds to "full".
|
||||
local filename_diff = difficulty .. "00.SAM"
|
||||
errors, config = self:loadMapConfig(filename_diff, config)
|
||||
if errors then
|
||||
return _S.errors.missing_th_data_file:format(filename_diff)
|
||||
end
|
||||
self.difficulty = difficulty
|
||||
-- Load the Theme Hospital configuration for this difficulty and level
|
||||
local filename_th_data = difficulty .. level_number .. ".SAM"
|
||||
errors, config = self:loadMapConfig(filename_th_data, config)
|
||||
if errors then
|
||||
return _S.errors.missing_th_data_file:format(filename_th_data)
|
||||
end
|
||||
if additional_config[level_number] then
|
||||
-- Load additional CorsixTH config per level.
|
||||
local filename_cth = "original" .. level_number .. ".level"
|
||||
local level_path = self.app:getFullPath({"Levels", filename_cth})
|
||||
errors, config = self:loadMapConfig(level_path, config, true)
|
||||
if errors then
|
||||
return _S.errors.missing_corsixth_file:format(filename_cth)
|
||||
end
|
||||
end
|
||||
return nil, config
|
||||
end
|
||||
|
||||
--! Get the difficulty of the level. Custom levels and campaign always have medium difficulty.
|
||||
--!return (int) difficulty of the level, 1=easy, 2=medium, 3=hard.
|
||||
function Map:getDifficulty()
|
||||
@@ -352,13 +381,17 @@ function Map:save(filename)
|
||||
self.th:save(filename)
|
||||
end
|
||||
|
||||
--[[! Loads map configurations from files. Returns nil as first result
|
||||
if no configuration could be loaded and config as second result no matter what.
|
||||
-- A set of the level difficulties. Full is default
|
||||
local correct_difficulties = list_to_set({"easy", "full", "hard"})
|
||||
|
||||
--[[! Loads map configurations from files.
|
||||
!param filename (string) The absolute path to the config file to load
|
||||
!param config (string) If a base config already exists and only some values should be overridden
|
||||
this is the base config
|
||||
!param custom If true The configuration file is searched for where filename points, otherwise
|
||||
it is assumed that we're looking in the theme_hospital_install path.
|
||||
!return error The specific localised error message, if error occurred
|
||||
!return config The successfully loaded config
|
||||
]]
|
||||
function Map:loadMapConfig(filename, config, custom)
|
||||
local function iterator()
|
||||
@@ -368,7 +401,7 @@ function Map:loadMapConfig(filename, config, custom)
|
||||
return self.app.fs:readContents("Levels", filename):gmatch"[^\r\n]+"
|
||||
end
|
||||
end
|
||||
if self.app.fs:readContents("Levels", filename) or io.open(filename) then
|
||||
if filename and (self.app.fs:readContents("Levels", filename) or io.open(filename)) then
|
||||
for line in iterator() do
|
||||
if line:sub(1, 1) == "#" then
|
||||
local parts = {}
|
||||
@@ -403,9 +436,34 @@ function Map:loadMapConfig(filename, config, custom)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If the level file overlay field gives a difficulty and number (from the TH campaign),
|
||||
-- try to load that on top of the config loaded so far.
|
||||
if config.overlay then
|
||||
local difficulty, level_number = config.overlay.difficulty, config.overlay.level_number
|
||||
local errors
|
||||
config.overlay = nil -- Prevent recursive loop
|
||||
|
||||
if difficulty and level_number then
|
||||
-- Validate the difficulty and level number
|
||||
if not correct_difficulties[difficulty] then
|
||||
return _S.errors.overlay.incorrect_difficulty .. difficulty
|
||||
end
|
||||
if type(level_number) ~= "number" or level_number < 1 or level_number > 12 then
|
||||
return _S.errors.overlay.incorrect_level_number .. level_number
|
||||
end
|
||||
-- Load difficulty and level from Theme Hospital and CorsixTH configs
|
||||
errors, config = self:_loadOriginalCampaignLevel(difficulty, level_number, config)
|
||||
if errors then
|
||||
return errors
|
||||
end
|
||||
else
|
||||
return _S.errors.overlay.missing_setting
|
||||
end
|
||||
end
|
||||
return nil, config
|
||||
else
|
||||
return "Error: Could not find the configuration file, only 'Base Config' will be loaded for this level.", config
|
||||
return _S.errors.missing_level_file
|
||||
end
|
||||
end
|
||||
|
||||
|
Reference in New Issue
Block a user