--[[
This script draws the position of the elementals during the final fight with
Malkil in Ironsword: Wizards & Warriors II on a canvas. Kuros's position
also is drawn. To keep it compact, coordinates on the canvas are scaled to
half the value in the game. By default, the area drawn is 1.5 by 1.25
screens large and focused around the middle peak of Icefire Mountain.
Keys are defined that allow you to toggle each elemental on/off, restore
Kuros to full health or full magic (so you do not need separate cheats), and
clear the canvas. There are toggles for the health restoration, magic
restoration, and canvas clearing to be done automatically.
Mostly by Dacicus in May 2018 but with input processing code copied from
another script, original author unknown.
--]]
-- Default values of options for cheats
local manual_restore_kuros_health = false
local manual_restore_kuros_magic = false
local manual_clear_canvas = false
local auto_restore_kuros_health = false
local auto_restore_kuros_magic = false
local auto_clear_canvas = false
-- Default to automatically clear the canvas every 1800 frames
local auto_clear_canvas_frames = 1800
-- Default options for drawing the elementals
local draw_earth = true
local draw_fire = true
local draw_water = true
local draw_wind = true
-- Key definitions to toggle the above options, same order as above
local keyboard_shortcuts = {"G", "H", "J", "B", "N", "M", "NumberPad0", "NumberPad1", "NumberPad2", "NumberPad3"}
-- Script start-up message
console.writeline("Press " .. keyboard_shortcuts[1] .. " to restore health.")
console.writeline("Press " .. keyboard_shortcuts[2] .. " to restore magic.")
console.writeline("Press " .. keyboard_shortcuts[3] .. " to clear canvas.")
console.writeline("Press " .. keyboard_shortcuts[4] .. " to automatically restore health each frame.")
console.writeline("Press " .. keyboard_shortcuts[5] .. " to automatically restore magic each frame.")
console.writeline("Press " .. keyboard_shortcuts[6] .. " to automatically clear canvas every " .. auto_clear_canvas_frames .. " frames.")
console.writeline("Press " .. keyboard_shortcuts[7] .. " to draw/hide earth elemental.")
console.writeline("Press " .. keyboard_shortcuts[8] .. " to draw/hide fire elemental.")
console.writeline("Press " .. keyboard_shortcuts[9] .. " to draw/hide water elemental.")
console.writeline("Press " .. keyboard_shortcuts[10] .. " to draw/hide wind elemental.")
-- Some other variables and default values
local camera_x, camera_y
local dots_x_offset = 0x80
local dots_y_offset = 0x80
local start_frame = emu.framecount()
local frames_since_cleared = 0
local boss_is_loaded = false
local boss_offsets_found = 0
local earth_offset, fire_offset, water_offset, wind_offset
-- Initialize the canvas
local cnv = gui.createcanvas(0x180, 0x140)
cnv.Clear(0xFF000000)
-- Input variables
local old_input, current_input, new_input = {}, {}, {}
function get_new_input()
old_input = current_input
current_input = input.get()
new_input = {}
for k,v in pairs(current_input) do
new_input[k] = not(old_input[k])
end
end
function process_new_input()
if new_input[keyboard_shortcuts[1]] then
manual_restore_kuros_health = true
console.writeline("Restoring full health.")
end
if new_input[keyboard_shortcuts[2]] then
manual_restore_kuros_magic = true
console.writeline("Restoring full magic.")
end
if new_input[keyboard_shortcuts[3]] then
manual_clear_canvas = true
console.writeline("Clearing canvas.")
end
if new_input[keyboard_shortcuts[4]] then
auto_restore_kuros_health = not(auto_restore_kuros_health)
console.write("Auto restore full health: ")
if auto_restore_kuros_health then
console.writeline("Enabled.")
else
console.writeline("Disabled.")
end
end
if new_input[keyboard_shortcuts[5]] then
auto_restore_kuros_magic = not(auto_restore_kuros_magic)
console.write("Auto restore full magic: ")
if auto_restore_kuros_magic then
console.writeline("Enabled.")
else
console.writeline("Disabled.")
end
end
if new_input[keyboard_shortcuts[6]] then
auto_clear_canvas = not(auto_clear_canvas)
console.write("Use timer to clear canvas: ")
if auto_clear_canvas then
console.writeline("Enabled. Resetting timer.")
start_frame = emu.framecount()
frames_since_cleared = 0
else
console.writeline("Disabled.")
end
end
if new_input[keyboard_shortcuts[7]] then
draw_earth = not(draw_earth)
if draw_earth then
console.writeline("Drawing earth elemental.")
else
console.writeline("Hiding earth elemental.")
end
end
if new_input[keyboard_shortcuts[8]] then
draw_fire = not(draw_fire)
if draw_fire then
console.writeline("Drawing fire elemental.")
else
console.writeline("Hiding fire elemental.")
end
end
if new_input[keyboard_shortcuts[9]] then
draw_water = not(draw_water)
if draw_water then
console.writeline("Drawing water elemental.")
else
console.writeline("Hiding water elemental.")
end
end
if new_input[keyboard_shortcuts[10]] then
draw_wind = not(draw_wind)
if draw_wind then
console.writeline("Drawing wind elemental.")
else
console.writeline("Hiding wind elemental.")
end
end
end
function restore_kuros_health()
if manual_restore_kuros_health or auto_restore_kuros_health then
memory.write_u8(0x006A, 0xFF)
end
if manual_restore_kuros_health then
manual_restore_kuros_health = false
end
end
function restore_kuros_magic()
if manual_restore_kuros_magic or auto_restore_kuros_magic then
memory.write_u8(0x006B, 0xFF)
end
if manual_restore_kuros_magic then
manual_restore_kuros_magic = false
end
end
function draw_kuros_pos_dots()
local kuros_x = memory.read_u8(0x0213) + memory.read_u8(0x0226) * 0x100
local kuros_y = memory.read_u8(0x024C) + memory.read_u8(0x025F) * 0x100
kuros_x = kuros_x / 2
kuros_y = kuros_y / 2
cnv.DrawRectangle(kuros_x - dots_x_offset, kuros_y - dots_y_offset, 1, 1, "yellow")
end
function is_boss_loaded()
if (memory.read_u8(0x00C6) == 1) then
boss_is_loaded = true
else
boss_is_loaded = false
boss_offsets_found = 0
end
end
function find_boss_offsets()
for i = 0x0B, 0x12 do
if (memory.read_u8(0x02BE + i) == 0x1D) then
earth_offset = i
boss_offsets_found = bit.bor(boss_offsets_found, 0x01)
elseif (memory.read_u8(0x02BE + i) == 0x1C) then
fire_offset = i
boss_offsets_found = bit.bor(boss_offsets_found, 0x02)
elseif (memory.read_u8(0x02BE + i) == 0x1B) then
water_offset = i
boss_offsets_found = bit.bor(boss_offsets_found, 0x04)
elseif (memory.read_u8(0x02BE + i) == 0x1A) then
wind_offset = i
boss_offsets_found = bit.bor(boss_offsets_found, 0x08)
end
end
end
-- Label the location RAM offset over the enemy, projectile, etc.
-- Note that this draws to the screen, not to the canvas.
-- Can be used to find offsets for things not drawn by default.
function draw_enemy_pos_string()
local enemy_x_pos, enemy_y_pos
for i = 1, 0x12 do
enemy_x_pos = memory.read_u8(0x0213 + i) + memory.read_u8(0x0226 + i) * 0x100 - camera_x
enemy_y_pos = memory.read_u8(0x024C + i) + memory.read_u8(0x025F + i) * 0x100 - camera_y
gui.drawText(enemy_x_pos, enemy_y_pos, string.format("%02x", i))
end
end
function draw_enemy_pos_dots()
local enemy_x_pos, enemy_y_pos
-- Draw the elementals if the offset has been found and if health is not 0
if draw_earth and bit.check(boss_offsets_found, 0) and (memory.read_u8(0x00CB) ~= 0) then
enemy_x_pos = memory.read_u8(0x0213 + earth_offset) + memory.read_u8(0x0226 + earth_offset) * 0x100
enemy_y_pos = memory.read_u8(0x024C + earth_offset) + memory.read_u8(0x025F + earth_offset) * 0x100
enemy_x_pos = enemy_x_pos / 2
enemy_y_pos = enemy_y_pos / 2
cnv.DrawRectangle(enemy_x_pos - dots_x_offset, enemy_y_pos - dots_y_offset, 1, 1, "brown")
end
if draw_fire and bit.check(boss_offsets_found, 1) and (memory.read_u8(0x00CA) ~= 0) then
enemy_x_pos = memory.read_u8(0x0213 + fire_offset) + memory.read_u8(0x0226 + fire_offset) * 0x100
enemy_y_pos = memory.read_u8(0x024C + fire_offset) + memory.read_u8(0x025F + fire_offset) * 0x100
enemy_x_pos = enemy_x_pos / 2
enemy_y_pos = enemy_y_pos / 2
cnv.DrawRectangle(enemy_x_pos - dots_x_offset, enemy_y_pos - dots_y_offset, 1, 1, "red")
end
if draw_water and bit.check(boss_offsets_found, 2) and (memory.read_u8(0x00C9) ~= 0) then
enemy_x_pos = memory.read_u8(0x0213 + water_offset) + memory.read_u8(0x0226 + water_offset) * 0x100
enemy_y_pos = memory.read_u8(0x024C + water_offset) + memory.read_u8(0x025F + water_offset) * 0x100
enemy_x_pos = enemy_x_pos / 2
enemy_y_pos = enemy_y_pos / 2
cnv.DrawRectangle(enemy_x_pos - dots_x_offset, enemy_y_pos - dots_y_offset, 1, 1, "blue")
end
if draw_wind and bit.check(boss_offsets_found, 3) and (memory.read_u8(0x00C8) ~= 0) then
enemy_x_pos = memory.read_u8(0x0213 + wind_offset) + memory.read_u8(0x0226 + wind_offset) * 0x100
enemy_y_pos = memory.read_u8(0x024C + wind_offset) + memory.read_u8(0x025F + wind_offset) * 0x100
enemy_x_pos = enemy_x_pos / 2
enemy_y_pos = enemy_y_pos / 2
cnv.DrawRectangle(enemy_x_pos - dots_x_offset, enemy_y_pos - dots_y_offset, 1, 1, "white")
end
cnv.Refresh()
boss_offsets_found = 0
end
function clear_enemy_pos_canvas()
if manual_clear_canvas then
cnv.Clear(0xFF000000)
manual_clear_canvas = false
end
if auto_clear_canvas then
if (emu.framecount() ~= start_frame) then
frames_since_cleared = frames_since_cleared + 1
end
if (frames_since_cleared > auto_clear_canvas_frames) then
cnv.Clear(0xFF000000)
frames_since_cleared = 0
end
end
end
while true do
camera_x = memory.read_u16_le(0x0053)
camera_y = memory.read_u16_le(0x0055)
get_new_input()
process_new_input()
restore_kuros_health()
restore_kuros_magic()
if boss_is_loaded then
draw_kuros_pos_dots()
find_boss_offsets()
-- draw_enemy_pos_string()
draw_enemy_pos_dots()
clear_enemy_pos_canvas()
else
is_boss_loaded()
end
emu.frameadvance()
end