mirror of
https://github.com/cave-story-randomizer/cave-story-randomizer
synced 2025-03-22 09:59:23 +00:00
Item Randomizer works! Need full database though!!
This commit is contained in:
parent
768895badc
commit
510be9a9a1
|
@ -1,3 +1,7 @@
|
|||
Cave Story Randomizer
|
||||
=====================
|
||||
|
||||
Issues
|
||||
------
|
||||
|
||||
- Bubbler (and other weapons?) can't break blocks in the First Cave.
|
||||
|
|
41
src/conf.lua
Normal file
41
src/conf.lua
Normal file
|
@ -0,0 +1,41 @@
|
|||
if io then
|
||||
io.stdout:setvbuf("no")
|
||||
end
|
||||
|
||||
local seed = os.time()
|
||||
math.randomseed(seed)
|
||||
|
||||
function love.conf(t)
|
||||
t.window = {
|
||||
title = "Cave Story Randomizer",
|
||||
-- icon = 'icon.png',
|
||||
width = 640,
|
||||
height = 480,
|
||||
resizable = false,
|
||||
}
|
||||
t.version = '11.1'
|
||||
t.console = false
|
||||
t.identity = 'CaveStoryRandomizer'
|
||||
t.accelerometerjoystick = false
|
||||
t.gammacorrect = false
|
||||
|
||||
-- t.releases = {
|
||||
-- -- This is the name of the zip archive which contains your game.
|
||||
-- title = 'Cave Story Randomizer',
|
||||
-- -- This is the name of your game's executable.
|
||||
-- package = 'Cave Story Randomizer',
|
||||
-- loveVersion = '11.1',
|
||||
-- version = nil,
|
||||
-- author = 'shru',
|
||||
-- email = nil,
|
||||
-- description = nil,
|
||||
-- homepage = 'https://shru.itch.io/cave-story-randomizer',
|
||||
-- -- MacOS needs this.
|
||||
-- identifier = 'CaveStoryRandomizer',
|
||||
-- excludeFileList = {
|
||||
-- -- '.+%.ase',
|
||||
-- },
|
||||
-- compile = false,
|
||||
-- releaseDirectory = 'releases',
|
||||
-- }
|
||||
end
|
|
@ -1,5 +1,21 @@
|
|||
return {
|
||||
-- Weapons
|
||||
-- wXXX = {
|
||||
-- name = "",
|
||||
-- map = "",
|
||||
-- getText = "",
|
||||
-- command = "",
|
||||
-- displayCmd = "",
|
||||
-- kind = "weapon",
|
||||
-- },
|
||||
wBubbler = {
|
||||
name = "Bubbler",
|
||||
map = "Comu",
|
||||
getText = "Got the =Bubbler=!",
|
||||
command = "<AM+0007:0100",
|
||||
displayCmd = "<GIT0007",
|
||||
kind = "weapon",
|
||||
},
|
||||
wPolar = {
|
||||
name = "Polar Star",
|
||||
map = "Pole",
|
||||
|
@ -12,10 +28,21 @@ return {
|
|||
iPanties = {
|
||||
name = "Curly's Panties",
|
||||
map = "CurlyS",
|
||||
-- getText = "Found =Curly's Underwear=.",
|
||||
getText = "Found =Curly's Panties=.",
|
||||
getText = "Found =Curly's Underwear=.",
|
||||
-- getText = "Found =Curly's Panties=.", -- Grrr
|
||||
command = "<IT+0035",
|
||||
displayCmd = "<GIT1035",
|
||||
kind = "item",
|
||||
},
|
||||
}
|
||||
|
||||
-- #0200
|
||||
-- <KEY<FLJ1640:0201<FL+1640<SOU0022<CNP0200:0021:0000
|
||||
-- <MSGOpened the chest.<NOD<GIT0002<AM+0002:0000<CLR
|
||||
-- <CMU0010Got the =Polar Star=!<WAI0160<NOD<GIT0000<CLO<RMU
|
||||
-- <MSG
|
||||
-- From somewhere, a transmission...<FAO0004<NOD<TRA0018:0501:0002:0000
|
||||
|
||||
-- #0420
|
||||
-- <KEY<DNP0420<MSG<GIT1035<IT+0035
|
||||
-- Found Curly's Panties.<NOD<END
|
||||
|
|
|
@ -4,11 +4,9 @@ local ITEM_DATA = require 'database.items'
|
|||
|
||||
function C:new()
|
||||
self._left = {}
|
||||
self._indexMap = {}
|
||||
for k, v in pairs(ITEM_DATA) do
|
||||
local item = _.clone(v)
|
||||
table.insert(self._left, item)
|
||||
self._indexMap[item] = #self._left
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -26,18 +24,19 @@ end
|
|||
function C:_getItem(filterFn)
|
||||
-- Filter down to only applicable items.
|
||||
local applicable = {}
|
||||
for _, item in ipairs(self._left) do
|
||||
local indexMap = {}
|
||||
for index, item in ipairs(self._left) do
|
||||
if filterFn(item) then
|
||||
table.insert(applicable, item)
|
||||
indexMap[item] = index
|
||||
end
|
||||
end
|
||||
assert(#applicable >= 1, 'No applicable items!')
|
||||
|
||||
-- Select an item.
|
||||
local selected = _.sample(applicable)
|
||||
local index = self._indexMap[selected]
|
||||
local index = indexMap[selected]
|
||||
table.remove(self._left, index)
|
||||
self._indexMap[selected] = nil
|
||||
|
||||
return selected
|
||||
end
|
||||
|
|
62
src/main.lua
62
src/main.lua
|
@ -1,5 +1,3 @@
|
|||
io.stdout:setvbuf("no")
|
||||
|
||||
require 'lib.strict'
|
||||
|
||||
Class = require 'lib.classic'
|
||||
|
@ -8,7 +6,7 @@ Serpent = require 'lib.serpent'
|
|||
|
||||
lf = love.filesystem
|
||||
|
||||
local LOG_LEVEL = 5
|
||||
local LOG_LEVEL = 4
|
||||
local function _log(level, prefix, text, ...)
|
||||
if LOG_LEVEL >= level then
|
||||
print(prefix .. text, ...)
|
||||
|
@ -20,9 +18,16 @@ function logNotice(...) _log(3, 'NOTICE: ', ...) end
|
|||
function logInfo(...) _log(4, 'INFO: ', ...) end
|
||||
function logDebug(...) _log(5, 'DEBUG: ', ...) end
|
||||
|
||||
local TSC_FILES = {
|
||||
'Pole.tsc',
|
||||
}
|
||||
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
|
||||
|
||||
-- function love.load()
|
||||
-- -- readPXM('Pole.pxm')
|
||||
|
@ -32,32 +37,42 @@ local TSC_FILES = {
|
|||
-- end
|
||||
|
||||
function love.directorydropped(path)
|
||||
-- Mount
|
||||
assert(lf.mount(path, 'data'))
|
||||
local items = lf.getDirectoryItems('/data')
|
||||
-- Mount.
|
||||
local mountPath = 'mounted-data'
|
||||
assert(lf.mount(path, mountPath))
|
||||
local items = lf.getDirectoryItems('/' .. mountPath)
|
||||
local containsStage = _.contains(items, 'Stage')
|
||||
assert(containsStage)
|
||||
local dirStage = '/data/Stage'
|
||||
local dirStage = '/' .. mountPath .. '/Stage'
|
||||
|
||||
local tscFiles = {}
|
||||
for _, filename in ipairs(TSC_FILES) do
|
||||
local path = dirStage .. '/' .. filename
|
||||
local TscFile = require 'tsc_file'
|
||||
tscFiles[filename] = TscFile(path)
|
||||
|
||||
-- decoded = stringReplace(decoded, ITEM_DATA.wPolar.command, ITEM_DATA.iPanties.command)
|
||||
-- decoded = stringReplace(decoded, ITEM_DATA.wPolar.getText, ITEM_DATA.iPanties.getText)
|
||||
-- decoded = stringReplace(decoded, ITEM_DATA.wPolar.displayCmd, ITEM_DATA.iPanties.displayCmd)
|
||||
end
|
||||
|
||||
-- Create ItemDeck.
|
||||
local ItemDeck = require 'item_deck'
|
||||
local itemDeck = ItemDeck()
|
||||
print(Serpent.line(itemDeck:getWeapon()))
|
||||
print(Serpent.line(itemDeck:getAny()))
|
||||
|
||||
tscFiles['Pole.tsc']:writeTo('Testing.tsc')
|
||||
-- Place random weapon in Hermit Gunsmith.
|
||||
tscFiles['Pole.tsc']:replaceItem(itemDeck:getWeapon())
|
||||
|
||||
-- Unmount
|
||||
-- Replace all items.
|
||||
for _, tscFile in pairs(tscFiles) do
|
||||
while tscFile:hasUnreplacedItems() do
|
||||
tscFile:replaceItem(itemDeck:getAny())
|
||||
end
|
||||
end
|
||||
|
||||
-- Write modified files.
|
||||
for filename, tscFile in pairs(tscFiles) do
|
||||
local path = '/data/Stage/' .. filename
|
||||
tscFile:writeTo(path)
|
||||
end
|
||||
|
||||
-- Unmount.
|
||||
assert(lf.unmount(path))
|
||||
end
|
||||
|
||||
|
@ -66,14 +81,3 @@ function love.keypressed(key)
|
|||
love.event.push('quit')
|
||||
end
|
||||
end
|
||||
|
||||
-- #0200
|
||||
-- <KEY<FLJ1640:0201<FL+1640<SOU0022<CNP0200:0021:0000
|
||||
-- <MSGOpened the chest.<NOD<GIT0002<AM+0002:0000<CLR
|
||||
-- <CMU0010Got the =Polar Star=!<WAI0160<NOD<GIT0000<CLO<RMU
|
||||
-- <MSG
|
||||
-- From somewhere, a transmission...<FAO0004<NOD<TRA0018:0501:0002:0000
|
||||
|
||||
-- #0420
|
||||
-- <KEY<DNP0420<MSG<GIT1035<IT+0035
|
||||
-- Found Curly's Panties.<NOD<END
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
local C = Class:extend()
|
||||
|
||||
-- local MODE_READ_BINARY = 'rb'
|
||||
local MODE_WRITE_BINARY = 'wb'
|
||||
-- https://www.lua.org/manual/5.1/manual.html#5.7
|
||||
-- w+: Update mode, all previous data is erased;
|
||||
-- b: Binary mode, forces Windows to save with Unix endings.
|
||||
MODE_WRITE_ERASE_EXISTING = 'w+b'
|
||||
|
||||
local ITEM_DATA = require 'database.items'
|
||||
|
||||
function C:new(path)
|
||||
logInfo('reading TSC: ' .. path)
|
||||
|
@ -14,16 +18,61 @@ function C:new(path)
|
|||
|
||||
assert(file:close())
|
||||
assert(file:release())
|
||||
|
||||
-- Determine set of items which can be replaced later.
|
||||
self._unreplaced = {}
|
||||
self._mapName = path:match("^.+/(.+)$")
|
||||
for k, v in pairs(ITEM_DATA) do repeat
|
||||
if (v.map .. '.tsc') ~= self._mapName then
|
||||
break -- continue
|
||||
end
|
||||
local item = _.clone(v)
|
||||
table.insert(self._unreplaced, item)
|
||||
until true end
|
||||
self._unreplaced = _.shuffle(self._unreplaced)
|
||||
end
|
||||
|
||||
function C:hasUnreplacedItems()
|
||||
return #self._unreplaced >= 1
|
||||
end
|
||||
|
||||
local function _stringReplace(text, needle, replacement)
|
||||
local i = text:find(needle, 1, true)
|
||||
if i == nil then
|
||||
logWarning(('Unable to replace "%s" with "%s"'):format(needle, replacement))
|
||||
return text
|
||||
end
|
||||
local len = needle:len()
|
||||
local j = i + len - 1
|
||||
assert((i % 1 == 0) and (i > 0) and (i <= j), tostring(i))
|
||||
assert((j % 1 == 0), tostring(j))
|
||||
local a = text:sub(1, i - 1)
|
||||
local b = text:sub(j + 1)
|
||||
return a .. replacement .. b
|
||||
end
|
||||
|
||||
function C:replaceItem(replacement)
|
||||
assert(self:hasUnreplacedItems())
|
||||
local original = table.remove(self._unreplaced)
|
||||
self._text = _stringReplace(self._text, original.command, replacement.command)
|
||||
self._text = _stringReplace(self._text, original.getText, replacement.getText)
|
||||
self._text = _stringReplace(self._text, original.displayCmd, replacement.displayCmd)
|
||||
|
||||
local template = "[%s] %s -> %s"
|
||||
logNotice(template:format(self._mapName, original.name, replacement.name))
|
||||
end
|
||||
|
||||
function C:writeTo(path)
|
||||
local encoded = self:_codec(self._text, 'encode')
|
||||
|
||||
local tmpFile, err = io.open(path, MODE_WRITE_BINARY)
|
||||
local filepath = lf.getSourceBaseDirectory() .. path
|
||||
logInfo('writing TSC to: ' .. filepath)
|
||||
|
||||
local file, err = io.open(filepath, MODE_WRITE_ERASE_EXISTING)
|
||||
assert(err == nil, err)
|
||||
tmpFile:write(encoded)
|
||||
tmpFile:flush()
|
||||
tmpFile:close()
|
||||
file:write(encoded)
|
||||
file:flush()
|
||||
file:close()
|
||||
end
|
||||
|
||||
function C:_codec(text, mode)
|
||||
|
@ -66,18 +115,4 @@ function C:_codec(text, mode)
|
|||
return decoded
|
||||
end
|
||||
|
||||
local function stringReplace(text, needle, replacement)
|
||||
local i = text:find(needle, 1, true)
|
||||
if i == nil then
|
||||
return text
|
||||
end
|
||||
local len = needle:len()
|
||||
local j = i + len - 1
|
||||
assert((i % 1 == 0) and (i > 0) and (i <= j), tostring(i))
|
||||
assert((j % 1 == 0), tostring(j))
|
||||
local a = text:sub(1, i - 1)
|
||||
local b = text:sub(j + 1)
|
||||
return a .. replacement .. b
|
||||
end
|
||||
|
||||
return C
|
||||
|
|
Loading…
Reference in a new issue