1
0
Fork 0
mirror of https://github.com/notwa/mm synced 2024-11-12 22:29:03 -08:00
mm/Lua/cheat menu.lua

357 lines
10 KiB
Lua
Raw Normal View History

2016-01-12 15:54:42 -08:00
require "lib.setup"
require "boilerplate"
2016-01-13 07:56:18 -08:00
require "addrs"
2015-05-03 16:46:09 -07:00
require "classes"
require "menu classes"
2015-11-14 16:30:04 -08:00
require "menu input handlers"
2015-05-07 15:27:26 -07:00
require "messages"
2015-11-12 09:09:14 -08:00
require "flag manager"
2015-11-12 09:09:14 -08:00
-- TODO: make OoT versions for most of these menus
2015-11-14 14:59:37 -08:00
--[[ control schemes:
normal: (alt_input = false; eat_input = false)
L opens the menu
L selects menu items
D-Pad navigates up/down items and left/right through pages
2015-11-14 16:30:04 -08:00
alternate: (alt_input = true; eat_input = false)
2015-11-14 14:59:37 -08:00
L+R opens/closes the menu
L goes back a menu (or closes)
R selects menu items
2015-11-14 16:30:04 -08:00
L+Z hides the menu without closing (FIXME: interferes with back button)
2015-11-14 14:59:37 -08:00
D-Pad navigates
greedy: (alt_input = false; eat_input = true)
2015-11-14 16:42:50 -08:00
L opens/closes the menu
2015-11-14 16:30:04 -08:00
while the menu is open, the game receives no inputs
D-Pad/Joystick/C-Buttons navigate through items and pages
2015-11-14 16:42:50 -08:00
A select menu items
2015-11-14 16:30:04 -08:00
B/R go back a menu (or closes)
Z hides the menu without closing
2015-11-14 14:59:37 -08:00
TODO: joystick, a/b button etc
2015-11-14 16:30:04 -08:00
greedy alt: (alt_input = true; eat_input = true)
same as greedy but pauses the game while in menu
(enables run_while_paused)
2015-11-14 14:59:37 -08:00
--]]
2015-11-14 13:46:04 -08:00
local run_while_paused = true
2015-11-14 14:59:37 -08:00
local alt_input = true
2015-11-14 16:30:04 -08:00
local eat_input = true
2015-11-14 14:59:37 -08:00
2016-01-12 15:54:42 -08:00
local fn = oot and 'data/cm oot save.lua' or 'data/cm mm save.lua'
2015-11-15 08:05:33 -08:00
local saved = deserialize(fn) or {}
local function save()
serialize(fn, saved)
end
local fades_killed = false
local function set(f, v)
-- wrapper for addresses that *might* be undefined
if f then f(v) end
end
local function Setter(t)
return function()
for func, value in pairs(t) do
func(value)
2015-11-12 09:09:14 -08:00
end
end
end
2015-05-03 16:46:09 -07:00
local passives = {}
local Passive = Class(Callbacks)
2015-05-03 16:46:09 -07:00
function Passive:init(...)
Callbacks.init(self, ...)
table.insert(passives, self)
end
2015-05-03 16:46:09 -07:00
function Passive:tick()
if self.state then self:tick_on() end
end
function Passive:tick_on()
end
2015-05-03 16:46:09 -07:00
local levitate = Passive()
function levitate:tick_on()
if bit.band(addrs.buttons(), 0x800) > 0 then
self:hold()
end
end
2015-05-03 16:46:09 -07:00
function levitate:hold()
addrs.link_actor.y_vel(10)
end
2015-05-13 11:16:02 -07:00
local supersonic = Passive()
function supersonic:tick_on()
if bit.band(addrs.buttons(), 0x8000) > 0 then
self:hold()
2015-05-13 11:16:02 -07:00
end
end
function supersonic:hold()
addrs.link_actor.lin_vel(20)
end
2015-11-12 09:09:14 -08:00
local infinite_items = Passive()
function infinite_items:tick_on()
for k, v in pairs(addrs.quantities) do
v(69)
end
end
2015-11-14 16:45:36 -08:00
local any_item = Passive()
function any_item:tick_on()
addrs.buttons_enabled(0)
end
local function soft_reset()
2015-11-15 08:41:40 -08:00
if oot then
-- FIXME: Link voids out on title screen.
-- need to load title screen save?
addrs.warp_begin(0x14)
addrs.warp_destination(0x00CD)
addrs.fade_type(0x0B)
addrs.entrance_mod_setter(0xFFF3)
else
addrs.warp_begin(0x14)
addrs.warp_destination(0x1C00)
addrs.fade_type(0x0B)
addrs.entrance_mod_setter(0xFFFA)
end
2015-11-12 09:09:14 -08:00
end
local function save_pos()
2015-11-12 09:09:14 -08:00
local la = addrs.link_actor
saved.pos = {}
local pos = saved.pos
2015-11-12 09:09:14 -08:00
pos.x = la.x()
pos.y = la.y()
pos.z = la.z()
pos.a = la.angle()
-- also save ISG for glitch testers ;)
pos.isg = la.sword_active()
save()
2015-11-12 09:09:14 -08:00
end
local function load_pos()
2015-11-12 09:09:14 -08:00
local la = addrs.link_actor
local pos = saved.pos
if pos == nil then return end
2015-11-12 09:09:14 -08:00
la.x(pos.x)
la.y(pos.y)
la.z(pos.z)
-- also set xyz copies so collision detection doesn't interfere
la.x_copy(pos.x)
la.y_copy(pos.y)
la.z_copy(pos.z)
la.angle(pos.a)
la.sword_active(pos.isg)
end
local function reload_scene()
2015-11-12 09:09:14 -08:00
local ev = addrs.exit_value()
addrs.warp_begin(0x14)
addrs.warp_destination(ev)
end
local function save_scene()
saved.scene = addrs.exit_value()
save()
2015-11-12 09:09:14 -08:00
end
local function load_scene()
if saved.scene == nil then return end
addrs.warp_begin(0x14)
addrs.warp_destination(saved.scene)
end
local function save_scene_pos()
saved.scenepos = {}
local sp = saved.scenepos
sp.scene = addrs.exit_value()
local la = addrs.link_actor
sp.x = la.x()
sp.y = la.y()
sp.z = la.z()
sp.a = la.angle()
--sp.room = la.room_number()
save()
end
local function load_scene_pos()
local sp = saved.scenepos
if sp == nil then return end
2015-11-12 09:09:14 -08:00
addrs.warp_begin(0x14)
addrs.warp_destination(sp.scene)
local fade = fades_killed and 0x0B or 0x01
addrs.fade_type(fade)
2015-11-15 08:29:06 -08:00
local vt = oot and 1 or -4 -- TODO: check if there's a better type for OoT
addrs.voidout_type(vt)
addrs.voidout_x(sp.x)
addrs.voidout_y(sp.y)
addrs.voidout_z(sp.z)
addrs.voidout_angle(sp.a)
addrs.voidout_var(0x0BFF) -- puts camera behind link instead of at entrance
--voidout_room_number(sp.room)
2015-11-12 09:09:14 -08:00
end
local function kill_fades()
local et = addrs.entrance_table
if et == nil then return end
local et_size = 1244
local new_fade = 0x0B -- instant
local fades = new_fade*0x80 + new_fade
for i=0, et_size*4 - 1, 4 do
local a = et.addr + i
if R1(a) ~= 0x80 then -- don't mess up the pointers
-- the lower word works like this:
-- mmIIIIIIIOOOOOOO
-- m = mode; I = fade in; O = fade out (probably).
local mode = bit.band(R2(a+2), 0xC000)
W2(a+2, mode + fades)
end
end
fades_killed = true
end
2015-11-15 17:03:27 -08:00
local function timestop()
-- doesn't set it up quite like the glitch, but this is the main effect
set(addrs.timestop, 4) -- normally -1
2015-11-15 17:03:27 -08:00
end
2015-11-15 08:05:33 -08:00
local time_menu = oot and Menu{
Screen{
Text("Time Menu #1/1"),
2015-11-15 17:03:27 -08:00
Oneshot("Set Time to 06:00", Setter{[addrs.time]=0x4000}),
Oneshot("Set Time to 12:00", Setter{[addrs.time]=0x8000}),
Oneshot("Set Time to 18:00", Setter{[addrs.time]=0xC000}),
Oneshot("Set Time to 00:00", Setter{[addrs.time]=0x0000}),
2015-11-15 08:05:33 -08:00
Text(""),
Back(),
},
} or Menu{
2015-11-12 09:09:14 -08:00
Screen{
Text("Day/Time Menu #1/1"),
2015-11-14 08:59:30 -08:00
Oneshot("Set Day to Zeroth", Setter{[addrs.day]=0, [addrs.days_elapsed]=0}),
Oneshot("Set Day to First", Setter{[addrs.day]=1, [addrs.days_elapsed]=1}),
Oneshot("Set Day to Second", Setter{[addrs.day]=2, [addrs.days_elapsed]=2}),
Oneshot("Set Day to Final", Setter{[addrs.day]=3, [addrs.days_elapsed]=3}),
Oneshot("Set Day to New", Setter{[addrs.day]=4, [addrs.days_elapsed]=4}),
2016-11-10 18:32:56 -08:00
Oneshot("Set Time to 00:00", Setter{[addrs.time]=0x0000, [addrs.day_night]=1}),
Oneshot("Set Time to 03:00", Setter{[addrs.time]=0x2000, [addrs.day_night]=1}),
Oneshot("Set Time to 06:00", Setter{[addrs.time]=0x4000, [addrs.day_night]=0}),
Oneshot("Set Time to 09:00", Setter{[addrs.time]=0x6000, [addrs.day_night]=0}),
Oneshot("Set Time to 12:00", Setter{[addrs.time]=0x8000, [addrs.day_night]=0}),
Oneshot("Set Time to 15:00", Setter{[addrs.time]=0xA000, [addrs.day_night]=0}),
Oneshot("Set Time to 18:00", Setter{[addrs.time]=0xC000, [addrs.day_night]=1}),
Oneshot("Set Time to 21:00", Setter{[addrs.time]=0xE000, [addrs.day_night]=1}),
2015-11-12 09:09:14 -08:00
Text(""),
Oneshot("Time flow: Fast", Setter{[addrs.time_speed]=2}),
Oneshot("Time flow: Normal", Setter{[addrs.time_speed]=0}),
Oneshot("Time flow: Slow (iSoT)", Setter{[addrs.time_speed]=-2}),
Oneshot("Time flow: Stopped", Setter{[addrs.time_speed]=-3}),
Oneshot("Time flow: Backwards", Setter{[addrs.time_speed]=-5}),
2015-11-14 19:16:13 -08:00
Oneshot("Disable time flow (Scene)", Setter{[addrs.scene_time_speed]=0}),
2015-11-15 17:03:27 -08:00
Oneshot("Timestop glitch", timestop),
2015-11-12 09:09:14 -08:00
Text(""),
Back(),
},
}
2015-11-10 05:59:03 -08:00
globalize{
Setter = Setter,
Passive = Passive,
reload_scene = reload_scene,
}
local warp_menu = require(mm and "menus.warp" or "menus.warp oot")
2015-11-12 09:23:46 -08:00
local progress_menu = require "menus.progress"
local playas_menu = require "menus.playas"
2015-05-03 16:46:09 -07:00
local main_menu = Menu{
Screen{
2015-05-26 08:43:23 -07:00
Text("Main Menu #1/2"),
Toggle("D-Up to Levitate", levitate),
2015-05-13 11:16:02 -07:00
Toggle("A to Run Fast", supersonic),
2015-11-12 09:09:14 -08:00
Toggle("Infinite Items", infinite_items),
2015-11-14 16:45:36 -08:00
Toggle("Use Any Item", any_item),
2015-11-12 09:09:14 -08:00
Text(""),
2016-01-12 15:54:42 -08:00
Oneshot("Have Everything", Setter{[dofile]="setup hundred.lua"}),
2015-11-12 09:09:14 -08:00
LinkTo("Set Progress...", progress_menu),
Text(""),
Oneshot("Escape Cutscene", Setter{[addrs.cutscene_status_2]=3}),
2015-11-12 09:09:14 -08:00
Text(""),
2015-11-10 05:59:03 -08:00
LinkTo("Play as...", playas_menu),
--Oneshot("Store Epona", Setter{[addrs.stored_epona]=1}),
2015-11-12 09:09:14 -08:00
Oneshot("Kill Link", Setter{[addrs.hearts]=0}),
Text(""),
2015-05-03 16:46:09 -07:00
Back(),
},
Screen{
2015-05-26 08:43:23 -07:00
Text("Main Menu #2/2"),
2015-11-12 09:09:14 -08:00
LinkTo("Warp to...", warp_menu),
LinkTo("Set Day/Time...", time_menu),
Text(""),
Oneshot("Store Position", save_pos),
Oneshot("Restore Position", load_pos),
Text(""),
Oneshot("Reload Scene", reload_scene),
Oneshot("Store Scene", save_scene),
Oneshot("Restore Scene", load_scene),
Text(""),
Oneshot("Store Scene & Position", save_scene_pos),
Oneshot("Restore Scene & Position", load_scene_pos),
2015-11-12 09:09:14 -08:00
Text(""),
Oneshot("Kill Transitions", kill_fades),
2015-11-12 09:09:14 -08:00
Text(""),
2015-11-14 11:22:41 -08:00
Oneshot("Soft Reset (Warp to Title)", soft_reset),
Text(""),
2015-05-03 16:46:09 -07:00
Back(),
},
}
2015-11-14 16:30:04 -08:00
local input = InputHandler()
input = JoyWrapper(input)
2015-05-26 08:43:23 -07:00
local handle = MenuHandler(main_menu, T_TL)
local was_paused = false
2015-05-03 16:46:09 -07:00
while mm or oot do
local ctrl, pressed = input:update()
2015-11-14 16:30:04 -08:00
if eat_input then
local old_menu = handle.menu
handle_eat_input(handle, ctrl, pressed)
if alt_input and handle.menu ~= old_menu then
run_while_paused = true
if old_menu == nil then
was_paused = client.ispaused()
client.pause()
end
if handle.menu == nil and not was_paused then
client.unpause()
end
2015-11-14 16:30:04 -08:00
end
elseif alt_input then
2015-11-14 14:59:37 -08:00
handle_alt_input(handle, ctrl, pressed)
else
2015-11-14 16:30:04 -08:00
for _, v in ipairs{'left', 'right', 'up', 'down'} do
ctrl[v] = ctrl['d_'..v]
pressed[v] = pressed['d_'..v]
end
2015-11-14 14:59:37 -08:00
ctrl.enter = ctrl.L
pressed.enter = pressed.L
2015-11-14 16:30:04 -08:00
handle:update(ctrl, pressed)
2015-11-14 14:59:37 -08:00
end
2015-05-03 16:46:09 -07:00
for i, passive in ipairs(passives) do
passive:tick()
end
2015-11-14 13:46:04 -08:00
if run_while_paused then
emu.yield()
gui.cleartext()
else
emu.frameadvance()
end
end