Lua script for MMZ3 (U) on VBA 23.6
Language: lua
local box = {
width = 15,
height = 3,
};
local enemies = {
-- 0x3004F34,
-- 0x3004FF8,
-- 0x30050BC,
-- 0x3005180,
0x03005244,
0x03005308,
0x03005490,
0x030053CC,
0x03005554,
0x03005618,
0x030056DC,
0x030057A0,
0x03005864,
0x03005928,
-- 0x30059EC,
-- 0x3005AB0,
};
local lastDash = 255;
print("MMZ3 - Memory viewer script for VBA, created by zhangsongcui");
function drawCharge(pos, val, y, text)
if val < 5 then
return false;
end
local headEquip = memory.readbyte(0x020366C4);
local maxVal = 120;
-- if headEquip == 4 then -- Q-Charge1
-- maxVal = 100;
-- elseif headEquip == 5 then -- Q-Charge2
-- maxVal = 80;
-- elseif headEquip == 6 then -- Q-Charge3
-- maxVal = 60;
-- end
local var = math.min(maxVal, val);
gui.box(
pos.X - box.width,
pos.Y - box.height + y,
pos.X + box.width,
pos.Y + box.height + y,
nil, "black");
gui.box(
pos.X - box.width,
pos.Y - box.height + y,
pos.X - box.width * (1 - var / maxVal * 2),
pos.Y + box.height + y,
var < maxVal / 3 and "white" or (var < maxVal and "green" or "yellow"), "clear");
gui.text(pos.X - box.width - 17, pos.Y - box.height + y, text);
gui.text(pos.X + box.width + 3, pos.Y - box.height + y, val);
return true;
end
function drawRemain(pos, val, y, maxVal, text)
if val <= 0 then
return false;
end
gui.box(
pos.X - box.width,
pos.Y - box.height + y,
pos.X + box.width,
pos.Y + box.height + y,
nil, "black");
gui.box(
pos.X - box.width,
pos.Y - box.height + y,
pos.X - box.width * (1 - val / maxVal * 2),
pos.Y + box.height + y,
"white", "clear");
gui.text(pos.X - box.width - 17, pos.Y - box.height + y, text);
gui.text(pos.X + box.width + 3, pos.Y - box.height + y, val);
return true;
end
gui.register(function()
gui.opacity(.8);
local rng = memory.readlong(0x0202F608);
if rng == 0 then
return; -- 游戏还没开始
end
gui.text(2, 10, string.format(" RNG: 0x%08X (0x%08X)", rng, (rng * 0x000343FD + 0x00269EC3) % 0x80000000));
gui.text(82, 152, "Ingame Time: " .. memory.readlong(0x02030168));
local isPlaying = memory.readword(0x02031130) ~= 0x03C0; -- 主角血条下面的 Z 字
if not isPlaying then
lastDash = 255;
return;
end
local camera = {
X = memory.readlongsigned(0x020302B8),
Y = memory.readlongsigned(0x020302BC),
};
local hero = {
X = (memory.readlongsigned(0x02037FF4) - camera.X) / 0x0100 + 120,
Y = (memory.readlongsigned(0x02037FF8) - camera.Y) / 0x0100 + 80,
SpeedX = memory.readwordsigned(0x02037FFC),
SpeedY = memory.readwordsigned(0x02038000),
HP = memory.readbyte(0x02038044),
Invisible = memory.readbyte(0x02038034),
Charge1 = memory.readbyte(0x0203807C),
Charge2 = memory.readbyte(0x0203807D),
Dash = memory.readbyte(0x020380B0),
};
if hero.HP <= 0 then
return;
end
for i, enemy in pairs(enemies) do
local hp = memory.readbyte(enemy);
if hp > 0 then
local x = (memory.readlong(enemy - 0x50) - camera.X) / 0x0100 + 120;
local y = (memory.readlong(enemy - 0x4C) - camera.Y) / 0x0100 + 80;
gui.text(x, y, hp);
end
end
gui.text(2, 18, string.format("WpnUse: [%d, %d, %d, %d]", memory.readword(0x0203017C), memory.readword(0x0203017E), memory.readword(0x02030180), memory.readword(0x02030182)));
gui.text(2, 26, string.format(" Speed: (%+.1f, %+.1f)", hero.SpeedX / 0x100, hero.SpeedY / 0x100));
if hero.Dash == _G.lastDash then
hero.Dash = 255;
else
_G.lastDash = hero.Dash;
end
local dy = 4;
local offsety = 7;
if drawCharge(hero, hero.Charge1, dy, 'Crg1') then dy = dy + offsety end;
if drawCharge(hero, hero.Charge2, dy, 'Crg2') then dy = dy + offsety end;
if drawRemain(hero, hero.Invisible, dy, 90, 'Invi') then dy = dy + offsety end;
if hero.Dash ~= 255 and drawRemain(hero, hero.Dash, dy, 27, 'Dash') then dy = dy + offsety end;
gui.text(hero.HP > 9 and 7 or 8, 35, hero.HP, "red");
local boss = {
X = (memory.readlongsigned(0x0203BDF4) - camera.X) / 0x0100 + 120,
Y = (memory.readlongsigned(0x0203BDF8) - camera.Y) / 0x0100 + 80,
HP = memory.readword(0x0203BE44),
Invisible = memory.readbyte(0x0203BE34),
InvisibleLevel = memory.readbyte(0x0203BE36),
};
if boss.HP > 0 then
if memory.readword(0x02031168) ~= 0x03C0 then -- 指定右侧 Boss 血条下的 W 图标显示
-- Boss 战
gui.text(boss.HP > 9 and 226 or 228, 4, boss.HP, "red", "black");
else
-- 中 Boss 战
gui.text(boss.X, boss.Y, boss.HP, "red", "black");
end
drawRemain(boss, boss.Invisible, 5, 90, "Invi");
if (boss.Invisible > 0) then
gui.text(boss.X - box.width - 17, boss.Y + 9, "Invi Level: " .. boss.InvisibleLevel);
end
end
local bossAnother = { -- 蓝精灵
X = (memory.readlongsigned(0x0203BD10) - camera.X) / 0x0100 + 120,
Y = (memory.readlongsigned(0x0203BD14) - camera.Y) / 0x0100 + 80,
HP = memory.readword(0x0203BD60),
Invisible = memory.readbyte(0x0203BD50),
InvisibleLevel = memory.readbyte(0x0203BD52),
};
if bossAnother.HP > 0 then
if boss.HP == 0 then -- 这个是本尊
gui.text(bossAnother.HP > 9 and 226 or 228, 0, bossAnother.HP, "red", "black");
end
drawRemain(bossAnother, bossAnother.Invisible, 6, 90, "Invi");
if (bossAnother.Invisible > 0) then
gui.text(bossAnother.X - box.width - 17, bossAnother.Y + 11, "Invi Level: " .. bossAnother.InvisibleLevel);
end
end
end)