cave-story-randomizer/src/randomizer.lua

154 lines
4.4 KiB
Lua
Raw Normal View History

2018-12-19 04:06:41 +00:00
local ItemDeck = require 'item_deck'
local TscFile = require 'tsc_file'
local C = Class:extend()
local TSC_FILES = {}
do
local ITEM_DATA = require 'database.items'
for k, v in pairs(ITEM_DATA) do
local filename = v.map .. '.tsc'
if _.contains(TSC_FILES, filename) == false then
table.insert(TSC_FILES, filename)
end
end
end
local WEAPONS_WHICH_CAN_NOT_BREAK_BLOCKS = {
'wBubbline',
'wFireball',
'wSnake',
}
2018-12-19 04:06:41 +00:00
function C:randomize(path)
resetLog()
2018-12-19 04:06:41 +00:00
local success, dirStage = self:_mountDirectory(path)
if not success then
return "Could not find \"data\" subfolder.\n\nMaybe try dropping your Cave Story \"data\" folder in directly?"
end
self:_seedRngesus()
local tscFiles = self:_createTscFiles(dirStage)
local canNotBreakBlocks = self:_shuffleItems(tscFiles)
2018-12-19 04:06:41 +00:00
self:_writeModifiedData(tscFiles)
if canNotBreakBlocks then
self:_copyModifiedFirstCave()
end
self:_writeLog()
2018-12-19 04:06:41 +00:00
self:_unmountDirectory(path)
return self:_getStatusMessage()
2018-12-19 04:06:41 +00:00
end
function C:_mountDirectory(path)
local mountPath = 'mounted-data'
assert(lf.mount(path, mountPath))
local dirStage = '/' .. mountPath
local items = lf.getDirectoryItems(dirStage)
local containsData = _.contains(items, 'data')
if containsData then
dirStage = dirStage .. '/data'
end
local items = lf.getDirectoryItems(dirStage)
local containsStage = _.contains(items, 'Stage')
if containsStage then
dirStage = dirStage .. '/Stage'
else
return false, ''
end
return true, dirStage
end
function C:_seedRngesus()
local seed = tostring(os.time())
math.randomseed(seed)
logNotice(('Offering seed "%s" to RNGesus'):format(seed))
end
function C:_createTscFiles(dirStage)
local tscFiles = {}
for _, filename in ipairs(TSC_FILES) do
local path = dirStage .. '/' .. filename
tscFiles[filename] = TscFile(path)
end
return tscFiles
end
function C:_shuffleItems(tscFiles)
local itemDeck = ItemDeck()
-- Place random weapon in either First Cave or Hermit Gunsmith.
local firstArea, firstItemKey = unpack(_.sample({
{'Cave.tsc', 'lFirstCave'},
{'Pole.tsc', 'wPolarStar'},
}))
local firstWeapon = itemDeck:getWeapon()
tscFiles[firstArea]:replaceSpecificItem(firstItemKey, firstWeapon)
-- Replace all weapon trades with random weapons
tscFiles['Curly.tsc']:replaceSpecificItem('wMachineGun', itemDeck:getWeapon())
tscFiles['MazeA.tsc']:replaceSpecificItem('wSnake', itemDeck:getWeapon())
tscFiles['Pole.tsc']:replaceSpecificItem('wSpur', itemDeck:getWeapon())
tscFiles['Little.tsc']:replaceSpecificItem('wNemesis', itemDeck:getWeapon())
-- Replace the rest of the items.
2018-12-19 04:06:41 +00:00
for _, tscFile in pairs(tscFiles) do
while tscFile:hasUnreplacedItems() do
tscFile:replaceItem(itemDeck:getAny())
end
end
return _.contains(WEAPONS_WHICH_CAN_NOT_BREAK_BLOCKS, firstWeapon.key)
2018-12-19 04:06:41 +00:00
end
function C:_writeModifiedData(tscFiles)
local sourcePath = lf.getSourceBaseDirectory()
-- Create /data/Stage if it doesn't already exist.
local command = ('mkdir "%s"'):format(sourcePath .. '/data/Stage')
os.execute(command) -- HERE BE DRAGONS!!!
-- Write modified files.
for filename, tscFile in pairs(tscFiles) do
local path = sourcePath .. '/data/Stage/' .. filename
tscFile:writeTo(path)
end
end
function C:_copyModifiedFirstCave()
local cavePxmPath = lf.getSourceBaseDirectory() .. '/data/Stage/Cave.pxm'
local data = lf.read('database/Cave.pxm')
assert(data)
U.writeFile(cavePxmPath, data)
end
function C:_writeLog()
local path = lf.getSourceBaseDirectory() .. '/data/log.txt'
local data = getLogText()
U.writeFile(path, data)
print("\n")
end
2018-12-19 04:06:41 +00:00
function C:_unmountDirectory(path)
assert(lf.unmount(path))
end
function C:_getStatusMessage()
local warnings, errors = countLogWarningsAndErrors()
local line1
if warnings == 0 and errors == 0 then
line1 = "Randomized data successfully created!"
elseif warnings ~= 0 and errors == 0 then
line1 = ("Randomized data was created with %d warning(s)."):format(warnings)
else
return ("Encountered %d error(s) and %d warning(s) when randomizing data!"):format(errors, warnings)
end
local line2 = "Next overwrite the files in your copy of Cave Story with the versions in the newly created \"data\" folder. Don't forget to save a backup of the originals!"
local line3 = "Then play and have a fun!"
local status = ("%s\n\n%s\n\n%s"):format(line1, line2, line3)
return status
2018-12-19 04:06:41 +00:00
end
return C