diff --git a/docs/item locations.txt b/docs/item locations.txt index 420b843..b750e2f 100644 --- a/docs/item locations.txt +++ b/docs/item locations.txt @@ -48,6 +48,7 @@ finished the rocket. +5 HP. initial descent. +5 HP. + ** MISSILE EXPANSIONS ** These each give +5 Max Missile Launcher Ammo. Your max ammo carries over to the Super Missile Launcher. You'll have 30 missile ammo if you find them all, @@ -75,6 +76,89 @@ concealing a chest containing this massive expansion of 24 Misisles. +----------------- +- 3-01 Weapons - +----------------- + + - Polar Star +You find this weapon at the very beginning of the game. It's not the strongest +weapon, but it's definitely one of the easiest to use and useful in a wide +variety of situations. Keep it when Curly asks you to trade in the Sand Zone +if you want the Snake or Spur weapons later. + + - Machine Gun +Given to you by Curly Brace if you trade her the Polar Star. Keep the Polar +Star when she asks you by choosing "No" if you want the Snake or Spur later in +the game. The Machine Gun is still an excellent weapon, though, and perfect +for your first time through the game as it's not only the easiest Polar Star +trade-off weapon to obtain but Level 3 allows you to float upwards in the +air as long as you have ammo, vastly increasing your mobility. It has an ammo +count of 100 but auto-recharges, and the recharge rate vastly skyrockets once +you get the Turbocharge key item which only works with the Machine Gun. + + - Snake +Obtained by keeping the Polar Star when Curly asks you to trade and then giving +both the Polar Star and Fireball weapons to Chaba (the Gaudi shopkeep in the +Labyrinth) when you reach him. It's unique in that it's the only weapon in the +game capable of passing through walls. It's very similar to the Wave Beam in +early Metroid games. + + - Spur +Unique weapon considered by many to be the ultimate weapon in the game, and it +probably should be considering how long you have to keep the Polar Star if you +want this. You'll need to get the Booster 2.0 and fly back into the very first +area of the game--before the Mimiga Village--and revisit the hermit weaponsmith +with your original Polar Star to earn the Spur. Instead of levelling up +through crystals, it "gains levels" the longer you keep the shot button held +down, and is the only weapon that has a different effect at MAX level compared +to Level 3. + + - Missile Launcher +You recieve this early in the game, in the Egg Corridor. It's the only weapon +with limited ammo that doesn't automatically replenish, but it's also very +powerful. Easy to use, mostly works like a longer-ranged and more powerful +version of the Polar Star. + + - Super Missile Launcher +Found in the Boulder Chamber, this is an upgrade to your Missile Launcher which +basically makes every aspect of it better, though it takes a bit more EXP to +level up. Besides raw damage, the most noticeable upgrade from the standard +Missile Launcher is the velocity of the missiles, or the speed at which they +travel across the screen. Also, the missiles launched by this weapon are gold +in color. + + - Fireball +Given to you by Santa (the Mimiga with a strange name, not the Christmas guy) +in the Bushlands for helping him get back into his house. This can be a decent +alternative to the Polar Star or Machine Gun early in the game, as it's the +only weapon other than the Polar Star you'll find with truly unlimited ammo for +awhile. It shoots balls of plasma that bounce around along the ground, great +for grounded enemies and for use around slopes, and its rapidity mixed with its +good power for its point in the game makes it good against many bosses. + + - Bubbline (aka Bubbler) +A very unique hidden weapon obtainable by taking a Jelly Juice jar back to the +assembly hall in Mimiga Village and putting out the fireplace there. It's +called the Bubbler in the English fan-translation of the PC version of Cave +Story. It has a lot of potential use at Level 3 but is otherwise pretty under- +whelming. It has an ammo supply of 100 which regenerates on its own slowly. + + - Blade +Very powerful weapon given to you by King at a certain point in the story. Its +rapidity is very low (except for rapid releases of Level 1 or 2 shots in a +strong enemy or boss's face) and it has a short range, but the damage is huge +and it has infinite ammo. + + - Nemesis +Special weapon of great strength that can be obtained by trading King's Blade +to Mister Little. The weapon is unique in that levelling it up outright causes +it to weaken in every possible way, and it only takes 1 exp to level it up both +levels. Luckily, this also means that taking a hit from just about anything +will guarantee resetting it to Level 1, at which point it's at its strongest. +Overall, it's probably a more similar weapon to the Polar Star than anything +else, even the weapons that you actually trade the Polar Star for. Infinite +ammo. + ** KEY ITEMS ** diff --git a/src/main.lua b/src/main.lua index 04d181c..562270f 100644 --- a/src/main.lua +++ b/src/main.lua @@ -20,17 +20,7 @@ function logNotice(...) _log(3, 'NOTICE: ', ...) end function logInfo(...) _log(4, 'INFO: ', ...) end function logDebug(...) _log(5, 'DEBUG: ', ...) end -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 randomizer = require 'randomizer'() local background local font local screen @@ -46,78 +36,7 @@ function love.load() end function love.directorydropped(path) - -- Mount. - local mountPath = 'mounted-data' - assert(lf.mount(path, mountPath)) - local dirStage = '/' .. mountPath - do - local items = lf.getDirectoryItems(dirStage) - local containsData = _.contains(items, 'data') - if containsData then - dirStage = dirStage .. '/data' - end - end - do - local items = lf.getDirectoryItems(dirStage) - local containsStage = _.contains(items, 'Stage') - if containsStage then - dirStage = dirStage .. '/Stage' - else - status = "Could not find \"data\" subfolder.\n\nMaybe try dropping your Cave Story \"data\" folder in directly?" - return - end - end - - -- Offer tribute to RNGesus. - local seed = tostring(os.time()) - math.randomseed(seed) - logNotice(('Offering seed "%s" to RNGesus'):format(seed)) - - -- Create TscFile objects. - local tscFiles = {} - for _, filename in ipairs(TSC_FILES) do - local path = dirStage .. '/' .. filename - local TscFile = require 'tsc_file' - tscFiles[filename] = TscFile(path) - end - - -- Create ItemDeck. - local ItemDeck = require 'item_deck' - local itemDeck = ItemDeck() - - -- Place random weapon in either First Cave or Hermit Gunsmith. - local firstArea = _.sample({'Cave.tsc', 'Pole.tsc'}) - tscFiles[firstArea]:replaceItem(itemDeck:getWeapon()) - - -- Replace all items. - for _, tscFile in pairs(tscFiles) do - while tscFile:hasUnreplacedItems() do - tscFile:replaceItem(itemDeck:getAny()) - end - end - - 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 - - -- Unmount. - assert(lf.unmount(path)) - print("\n") - - -- Update status - status = [[Randomized data successfully created! - -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! - -Then play and have a fun!]] + status = randomizer:randomize(path) end function love.keypressed(key) diff --git a/src/randomizer.lua b/src/randomizer.lua new file mode 100644 index 0000000..d928cf8 --- /dev/null +++ b/src/randomizer.lua @@ -0,0 +1,105 @@ +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 + +function C:randomize(path) + 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) + self:_shuffleItems(tscFiles) + self:_writeModifiedData(tscFiles) + self:_unmountDirectory(path) + return [[Randomized data successfully created! + +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! + +Then play and have a fun!]] +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 = _.sample({'Cave.tsc', 'Pole.tsc'}) + tscFiles[firstArea]:replaceItem(itemDeck:getWeapon()) + + -- Replace all items. + for _, tscFile in pairs(tscFiles) do + while tscFile:hasUnreplacedItems() do + tscFile:replaceItem(itemDeck:getAny()) + end + end +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:_unmountDirectory(path) + assert(lf.unmount(path)) + print("\n") +end + +return C