You have to tune it yourself if you want to omit some of displayed data.
https://imgur.com/a/dXlMZP4
https://imgur.com/a/hPTHXz7
function u32(addr)
return memory.readu32(addr)
end
function s32(addr)
return memory.reads32(addr)
end
function u8(addr)
return memory.readu8(addr)
end
function float(addr)
return memory.readf(addr)
end
--[[
set *(int*)0x809a094 = 800
set *(int*)0x809a09c = 600
set *(int*)0x809a0c7 = 0x90909090
set *(char*)0x809a0cb = 0x90
]]
local ortho_left = -200
local ortho_right = 1000
local ortho_top = -150
local ortho_bottom = 750
local screen_width = 1024
local screen_height = 768
--[[local ortho_left = 0
local ortho_right = 800
local ortho_top = 0
local ortho_bottom = 600
local screen_width = 800
local screen_height = 600]]
function gui_rectangle(x, y, w, h, s, c1, c2)
gui.rectangle(
math.floor((x - ortho_left) * screen_width / (ortho_right - ortho_left)),
math.floor((y - ortho_top) * screen_height / (ortho_bottom - ortho_top)),
math.floor(w * screen_width / (ortho_right - ortho_left)),
math.floor(h * screen_height / (ortho_bottom - ortho_top)),
s, c1, c2)
end
function gui_text(x, y, s, c1, c2)
gui.text(
math.floor((x - ortho_left) * screen_width / (ortho_right - ortho_left)),
math.floor((y - ortho_top) * screen_height / (ortho_bottom - ortho_top)),
s, c1, c2)
end
-- 80715b1
-- eax = triggers
-- 2 drop duck
-- 3 ?
-- 79 - message hull integrity 25%
-- 7a - message hull integrity 50%
-- 7b - message hull integrity 100%
-- 7d - message no heating 20 secs
-- 7e - message immortality 10 secs
-- 7f - message 4 x fire power 20 secs
-- 80 - message extra cash $2500
-- 81 - message extra cash $5000
-- 82 - message extra cash $10000
-- 83 - drop hull
-- 84 - drop hull
-- 85 - drop hull
-- 86 - drop hull
-- 87 - drop hull
-- 88 - drop $2500
-- 89 - drop $
-- 8a - drop $
-- 8b - drop $
-- 8c - drop chest
-- 8d - drop chest
-- 8e - drop chest
-- 8f - drop chest
-- 90 - drop cooldown
-- 91 - drop x4 fire 20 secs
-- 92 - drop round disc
-- 93 - white flash on whole screen
-- 94 -
-- AC - flame explosion
-- F0 explode with parts level 1
-- F1 explode with parts level 1
function drawcollision(col, color1, color2)
local cnt = math.min(s32(col + 0xac), 10)
if cnt > 0 then
local scalex = float(col + 0x54)
local scaley = float(col + 0x58)
local posx = float(col + 0x8)
local posy = float(col + 0xC)
for i = 0, cnt - 1 do
local x1 = math.floor(posx + scalex * s32(col + 0x6c + i * 0x10))
local y1 = math.floor(posy + scaley * s32(col + 0x70 + i * 0x10))
local x2 = math.floor(posx + scalex * s32(col + 0x74 + i * 0x10))
local y2 = math.floor(posy + scaley * s32(col + 0x78 + i * 0x10))
gui_rectangle(x1, y1, x2 - x1, y2 - y1, 0, color1, color2)
end
end
end
function coords(enemy, idx, idx1, idx2)
--local state = u32(enemy + 0x3c)
--if state ~= 1 then return end
local field_18 = u32(enemy + 0x18)
local score = u32(field_18 + 10 * 4)
--if score == 0 then return end
local width = 5
local height = 5
local field_1C = u32(enemy + 0x1C)
if s32(field_1C + 0xac) <= 0 then return end -- have collision check
local field_1Cv = u32(field_1C)
if field_1Cv ~= 0 then
width = math.floor(s32(field_1Cv + 4) * float(field_1C + 21 * 4))
height = math.floor(s32(field_1Cv + 8) * float(field_1C + 22 * 4))
end
local screenx = float(field_1C + 2 * 4)
local screeny = float(field_1C + 3 * 4)
local field_14 = u32(enemy + 0x14)
if u32(field_14 + 0xAC) ~= 0 then
score = score * 5
end
local hp = s32(enemy + 0x38)
local color = 0x55FFFFFF
local drawbox = true
local addr = field_14
--[[local name
if addr ~= 0 then
addr = u32(addr)
if addr ~= 0 then
name = ''
for i = 0, 47 do
local c = u8(addr + i)
if c == 0 then
break
end
name = name .. string.char(c)
end
if name ~= '' then
--gui_text(math.floor(screenx), math.floor(screeny), string.format("%s", name))
end
end
end]]
local random_delay = float(field_14 + 0x11c)
local enemyDef = u32(field_14)
local man = u32(enemyDef + 0xa4)
if man == 1 then
drawcollision(field_1C, 0x00000000, 0x60FF00FF)
mans = mans + 1
else
drawcollision(field_1C, 0x00000000, 0x600000FF)
end
if score > 0 then
color = 0xFFFF0000
--gui_rectangle(math.floor(screenx), math.floor(screeny), math.floor(screenx + width) - math.floor(screenx), math.floor(screeny + height) - math.floor(screeny), 1, color, 0x00000000)
if hp > 0 then
if u32(field_14 + 0xac) ~= 0 then -- pirate
gui_text(math.floor(screenx), math.floor(screeny), string.format("%d", hp), 0xFF00FF00)
else
--gui_text(math.floor(screenx), math.floor(screeny), string.format("%.0f", random_delay/0.016666))
gui_text(math.floor(screenx), math.floor(screeny), string.format("%d %.0f %d", hp, random_delay/0.016666, score))
end
end
--elseif float(field_14 + 0x74) <= 0 and string.sub(name, 0, 6) == 'b_cash' then
elseif enemyDef ~= 0 and float(enemyDef + 0x70) > 0 then -- bonus
gui_rectangle(math.floor(screenx), math.floor(screeny), math.floor(screenx + width) - math.floor(screenx), math.floor(screeny + height) - math.floor(screeny), 3, 0xFF00FF00, 0x00000000)
else
if hp > 0 and hp ~= 999999 then
gui_rectangle(math.floor(screenx), math.floor(screeny), math.floor(screenx + width) - math.floor(screenx), math.floor(screeny + height) - math.floor(screeny), 1, color, 0x00000000)
gui_text(math.floor(screenx), math.floor(screeny), string.format("%d", hp))
end
end
--gui_text(math.floor(screenx), math.floor(screeny), string.format("%x %d %d %d", enemy, idx, idx1, idx2))
--if drawbox then
--end
if hp > 0 and score > 0 then
-- gui_text(math.floor(screenx), math.floor(screeny), string.format("%d", hp))
end
--print(string.format("%x: %.5f %.5f %d", enemy, screenx, screeny, score))
--print(string.format("%x: %d %d %d", enemy, idx, idx1, idx2))
end
function findWhoGotHit(a0, idx, idx1) -- 8073140
--print(string.format("local list %x", a0))
local ptr = u32(a0 + 0x1C)
local arr, cnt, enemy, i
cnt = s32(ptr)
if cnt > 100000 then
cnt = 100000
end
if cnt > 0 then
arr = u32(ptr + 4)
--print(string.format("%x arr %x", a0, arr))
if arr ~= 0 then
for i = 0, cnt - 1 do
enemy = u32(arr + i * 4)
if enemy ~= 0 then
--print(string.format("enemy %x", enemy))
coords(enemy, idx, idx1, i)
end
end
end
end
end
function checkGlobalList(addr, idx)
local lvlSmth = u32(addr)
if lvlSmth == 0 then
return
end
--print(string.format("global list %x", addr))
local list = u32(lvlSmth + 4)
for i = 1, 100 do
if list == 0 then
break
end
findWhoGotHit(list, idx, i)
list = u32(list + 0x160)
end
end
function checkLayer(layer, idx)
--print(string.format("%d %x", idx, layer))
if u32(layer + 0x34) == 0 then return end
local layerPosX = float(layer + 0x85058)
local layerPosY = float(layer + 0x8505C)
--print(string.format("x=%f y=%f %d %d %d %d", layerPosX, layerPosY, s32(layer + 0x48), s32(layer + 0x4C), s32(layer + 0x50), s32(layer + 0x54)))
for idx2 = s32(layer + 0x4c), s32(layer + 0x54) - 1 do
for idx = s32(layer + 0x48), s32(layer + 0x50) - 1 do
local offs = u32(layer + idx2 * 4 + 0x58 + idx * 0x200)
if offs ~= 0 then
local offs1 = u32(offs + 0xC0)
if offs1 ~= 0 then
local score = s32(offs1 + 0xB4)
if score ~= 0 then
--print(string.format("offs=%x offs1=%x %d", offs, offs1, score))
local tilePosX = s32(offs + 0xD8) - math.floor(layerPosX)
local tilePosY = s32(offs + 0xDC) - math.floor(layerPosY)
local offs2 = u32(offs)
local width = 5
local height = 5
if offs1 ~= 0 then
width = s32(offs2 + 4)
height = s32(offs2 + 8)
end
--print(string.format("%d %d %d %d", tilePosX, tilePosY, width, height))
local hp = s32(offs + 0xe0)
gui_rectangle(tilePosX, tilePosY, width, height, 1, 0xFF00FFFF, 0x00000000)
gui_text(math.floor(tilePosX), math.floor(tilePosY), string.format("%.0f", hp))
end
end
end
end
end
end
function checkLayers()
local layers = u32(0x80e3f5c)
local layersCount = s32(layers)
for i = 0, layersCount - 1 do
local arr = u32(layers + 4)
if arr ~= 0 then
local layer = u32(arr + i * 4)
if layer ~= 0 then
checkLayer(layer, i)
end
end
end
end
-- 80B6900
-- 806DCE0 - register kill
function u321(addr)
local v = u32(addr)
if v == nil then v = 0 end
--print('get', v)
return v
end
--[[
body counter bonuses
>= 5 MULTI KILL 250
>= 10 500 ratio 50
>= 20 1000 ratio 50
>= 30 2500 ratio 83.333333
>= 45 5000 ratio 111.111111
>= 60 7500 ratio 125
]]
function listWeapon(weapon, index, posy)
local weaponType = u32(weapon)
local name = ''
for i = 0, 0x2f do
local code = u8(weaponType + 4 + i)
if code == 0 then break end
name = name .. string.char(code)
end
local level = u32(weapon + 0xc)
local ammo = s32(weapon + 0x18)
local reloadTimer = float(weapon + 0x1c)
local streamList = u32(weapon + 0x8)
local streamCnt = 0
local streamAddr = 0
if streamList ~= 0 then
streamCnt = u32(streamList)
streamAddr = u32(streamList + 4)
if streamAddr == 0 then
streamCnt = 0
end
end
--gui_text(50, posy, string.format("%d %s lvl=%d streams=%d ammo=%d %.1f", index, name, level, streamCnt, ammo, reloadTimer * 60))
local posyb = posy
posy = posy + 15
local dps = 0
for i = 0, streamCnt - 1 do
local stream = u32(streamAddr + 4 * i)
if stream ~= 0 then
local streamType = u32(stream)
if streamType ~= 0 then
local state = s32(streamType + level * 4 + 0xd8)
if state > 0 then
local power = s32(streamType + level * 4 + 0x100)
local shot_delay = float(streamType + level * 4 + 0x128)
local cooldown = float(stream + 4)
gui_text(65, posy, string.format("%d %.0f %.5f", power, cooldown * 60, shot_delay))
posy = posy + 15
dps = dps + power / math.ceil(shot_delay * 60 - 1e-6)
end
end
end
end
gui_text(50, posyb, string.format("%s %d %.2f %d %.0f", name, level, dps, ammo, reloadTimer * 60))
return posy
end
function listWeapons(player)
local weaponsList = u32(player + 0x244)
if weaponsList == 0 then return end
local posy = 60
local cnt = s32(weaponsList)
if cnt >= 0 then
local addr = u32(weaponsList + 4)
if addr ~= 0 then
for i = 0, cnt - 1 do
local weapon = u32(addr + 4 * i)
if weapon ~= 0 then
posy = listWeapon(weapon, i, posy)
end
end
end
end
end
function onPaint()
local player = u32(0x80e492c)
if player == 0 then return end
listWeapons(player)
local posx = float(player + 0x8)
local posy = float(player + 0xc)
drawcollision(player, 0x8000ffff, 0x8000ffff)
local hull_now = float(player + 0x104)
local hull_max = s32(player + 0x100)
local heat_now = float(player + 0x1f4)
local heat_max = s32(player + 0x1f0)
local body_acc = s32(player + 0x288)
local body_del = float(player + 0x28c)
local menu = u32(0x80e326c)
local atarix = u32(menu + 0xd0)
code = 0
if atarix ~= 0 then
for i = 0, 3 do
code = code * 10 + s32(atarix + 0xb4 + i * 4)
end
end
--[[local cursor = u32(menu + 0x884)
local cursorX = -999
local cursorY = -999
if cursor ~= 0 then
cursorX = float(cursor + 0xC0)
cursorY = float(cursor + 0xC4)
end]]
mans = 0
gui_text(120, 0, string.format("money: %d menu: %d %d %04d", u32(player + 0x10C), s32(menu + 0x86c), s32(menu + 0x5d0), code))
gui_text(120, 15, string.format("hull %d/%d %.1f%%", hull_now, hull_max, hull_now * 100 / math.max(hull_max, 1)))
gui_text(120, 30+200*0, string.format("heat %.1f/%d %.1f%% %d %.3f (%.2f %.2f)", heat_now, heat_max, heat_now * 100 / math.max(heat_max, 1), body_acc, body_del, posx, posy))
--gui_text(120, 45, string.format("%x %x %x %x %x", u321(0x811780c), u321(u321(0x811780c)+0xd0), u321(0x0811780c), u321(0x0811780c)+0xbc, u321(u321(0x0811780c)+0xbc)))
--print("===================")
for i = 0, 2 do
checkGlobalList(0x80e497c + 4 * i, i)
end
gui_text(120, 45+200*0, string.format("mans %d", mans))
checkLayers()
gui_rectangle(0, 0, 800, 600, 1, 0xFFFF00FF, 0)
end
--print("===================")
--onPaint()
print(onPaint)
callback.onPaint(onPaint)