Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
A bunch of dumb BizHawk hacks I've made for Super Metroid.
autoShineActivated=false
autoFireActivated=false
autoDamageBoostActivated=false
assistantUI = forms.newform(200, 120, "SMAssist")
autoShineActivated = forms.checkbox(assistantUI,'Auto Shinespark Crouch',1,1)
autoFireActivated = nil --not in there yet
autoDamageBoostActivated = forms.checkbox(assistantUI,'Auto Damage Boost',1,23)
homingMissileActivated = forms.checkbox(assistantUI,'Homing Missile',1,45)
local camx = 0x000911
local camy = 0x000915
local function getProjType(i)
local projTypeFlagsRaw=mainmemory.read_u16_le(0xC18+(i*2))
local projTypeFlags={}
projTypeFlags.Live=bit.band(projTypeFlagsRaw,0x8000)==0x8000 --Kejardon seems unsure of whether it actually means "live"
projTypeFlags.Missile=bit.band(projTypeFlagsRaw,0x0100)==0x0100
projTypeFlags.SuperMissile=bit.band(projTypeFlagsRaw,0x0200)==0x0200
projTypeFlags.PowerBomb=bit.band(projTypeFlagsRaw,0x0300)==0x0300
projTypeFlags.Bomb=bit.band(projTypeFlagsRaw,0x0500)==0x0500
projTypeFlags.Beam=not (projTypeFlags.Missile or projTypeFlags.SuperMissile)
if projTypeFlags.PowerBomb or projTypeFlags.Bomb then
projTypeFlags.Missile=false
end
local beamType=bit.band(projTypeFlagsRaw,0xf)
local beamTypeTable={
{"Wave"}, --1
{"Ice"},
{"Wave","Ice"},
{"Spazer"},
{"Wave","Spazer"},
{"Ice","Spazer"},
{"Wave","Ice","Spazer"},
{"Plasma"},
{"Wave","Plasma"},
{"Ice","Plasma"},
{"Wave","Ice","Plasma"}
}
if projTypeFlags.Beam then
local beamTypeFlagTable=beamTypeTable[beamType]
if beamTypeFlagTable then
for k,v in pairs(beamTypeFlagTable) do
projTypeFlags[v]=true
end
end
end
return projTypeFlags
end
local function getNearestEnemy(x1,y1)
local x2 = 0
local y2 = 0
local oend = 20
local base = 0xF7A
local closestDistance=10000000000
local whichEnemyCoords={x=-30000,y=-30000}
for i = 0, oend, 1 do
if i > 0 then
base = 0xF7A + (i * 0x40)
else
base = 0xF7A
end
x2 = mainmemory.read_u16_le(base) - mainmemory.read_u16_le(camx)
y2 = mainmemory.read_u16_le(base+ 4) - mainmemory.read_u16_le(camy)
if x2~=0 and y2~=0 then
local distance=math.sqrt((x2-x1)^2+(y2-y1)^2)
if distance<closestDistance then
whichEnemyCoords={x=x2,y=y2}
closestDistance=distance
end
end
end
return whichEnemyCoords
end
local function homeProjectile(i)
local projxbase = 0xB64
local projybase = 0xB78
local x = mainmemory.read_u16_le(projxbase + (i*2)) - mainmemory.read_u16_le(camx)
local y = mainmemory.read_u16_le(projybase + (i*2)) - mainmemory.read_u16_le(camy)
local enemyCoords=getNearestEnemy(x,y)
local Left,Up,Down,Right=false,false
if enemyCoords.x~=-30000 then
if enemyCoords.x<x then Left=true elseif enemyCoords.x>x then Right=true end
if enemyCoords.y<y then Up=true elseif enemyCoords.y>y then Down=true end
local direction=mainmemory.readbyte(0x0C04+i)
if direction<0x10 then
local newdirection=direction
if Left then
if Up then
newdirection=8
elseif Down then
newdirection=6
else
newdirection=7
end
elseif Right then
if Up then
newdirection=1
elseif Down then
newdirection=3
else
newdirection=2
end
elseif Up then
newdirection=0
elseif Down then
newdirection=4
end
mainmemory.writebyte(0x0C04+i,newdirection)
end
end
end
local function homingMissile()
local x
local y
local xrad
local yrad
local projtype
local oend = 8
local projxbase = 0xB64
local projybase = 0xB78
local projxrbase = 0xBB4
local projyrbase = 0xBC8
local projectiles={}
for i = 0, oend, 1 do
projtype=getProjType(i)
if projtype.Missile then
homeProjectile(i)
end
end
return projectiles
end
local function enemies()
local x = 0
local y = 0
local xrad = 0
local yrad = 0
local oend = 20
local base = 0xF7A
local enemies={}
for i = 0, oend, 1 do
if i > 0 then
base = 0xF7A + (i * 0x40)
else
base = 0xF7A
end
x = mainmemory.read_u16_le(base) - mainmemory.read_u16_le(camx)
y = mainmemory.read_u16_le(base+ 4) - mainmemory.read_u16_le(camy)
xrad = mainmemory.read_u8(0x0F82 + (i * 0x40))
yrad = mainmemory.read_u8(0x0F84 + (i * 0x40))
hp = mainmemory.read_u16_le(base + 0x12)
table.insert(enemies,{x1=(x + (xrad * -1)),y1=(y + (yrad * -1)),x2=(x+xrad),y2=(y+yrad),hp=hp})
end
return enemies
end
function samusPositionState(stateFlagsRaw)
local crouchFlags={38,114,112,132}
local jumpFlags={76,104,106,20,22,80}
local movingFlags={8,16,14}
local morphFlags={28,29,30,48,64}
if stateFlagsRaw==24 or stateFlagsRaw==130 then return 3 end --spin jump, 130 is wall jump'd
if stateFlagsRaw==164 or stateFlagsRaw==162 then return 4 end --landing
for k,v in ipairs(crouchFlags) do
if stateFlagsRaw==v then return 1 end
end
for k,v in ipairs(jumpFlags) do
if stateFlagsRaw==v then return 2 end
end
for k,v in ipairs(movingFlags) do
if stateFlagsRaw==v then return 5 end
end
for k,v in ipairs(morphFlags) do
if stateFlagsRaw==v then return 6 end
end
return 0
end
local function getSamusState()
local stateFlagsRaw=memory.read_u8(0x0A1C)-1
local stateFlags={}
stateFlags.Left=bit.band(stateFlagsRaw,1)==1
if stateFlags.Left then stateFlagsRaw=stateFlagsRaw-1 end
if stateFlagsRaw==78 then stateFlags.DamageBoost=true return stateFlags end
if stateFlagsRaw==82 then stateFlags.Hurt=true return stateFlags end
if stateFlagsRaw==128 then stateFlags.ScrewAttack=true return stateFlags end
if stateFlagsRaw==198 then stateFlags.ShineSparkStart=true return stateFlags end
if stateFlagsRaw==200 then stateFlags.ShineSparkSideways=true return stateFlags end
if stateFlagsRaw==202 then stateFlags.ShineSparkUp=true return stateFlags end
if stateFlagsRaw==204 then stateFlags.ShineSparkDiagonal=true return stateFlags end
local position=samusPositionState(stateFlagsRaw)
if position==0 then
stateFlags.AimUp=bit.band(stateFlagsRaw,4)==4
stateFlags.LookUp=bit.band(stateFlagsRaw,2)==2
stateFlags.AimDown=stateFlags.AimUp and stateFlags.LookUp
if stateFlags.AimDown then
stateFlags.LookUp=false
stateFlags.AimUp=false
end
stateFlags.TurningAround=bit.band(stateFlagsRaw,32)==32
elseif position==1 then
stateFlags.Crouch=true
stateFlags.AimDown=stateFlagsRaw==114
stateFlags.AimUp=stateFlagsRaw==112
stateFlags.LookUp=stateFlagsRaw==132
stateFlags.TurningAround=bit.band(stateFlagsRaw,32)==32
elseif position==2 then
stateFlags.Jump=true
stateFlags.AimDown=stateFlagsRaw==106
stateFlags.AimUp=stateFlagsRaw==104
stateFlags.LookUp=stateFlagsRaw==20
stateFlags.LookDown=stateFlagsRaw==22
stateFlags.Moving=stateFlagsRaw==80
elseif position==3 then
stateFlags.SpinJump=true
stateFlags.WallJump=stateFlagsRaw==130
elseif position==4 then
stateFlags.Landing=true
stateFlags.Left=not stateFlags.Left
elseif position==5 then
stateFlags.Moving=true
elseif position==6 then
stateFlags.Morph=true
if stateFlagsRaw==48 then stateFlags.Freefall=true return stateFlags end
if stateFlags.Left then stateFlags.Left=false stateFlags.Moving=true end
stateFlags.Left=stateFlagsRaw==64 or stateFlagsRaw==30
stateFlags.Moving=stateFlags.Moving or stateFlagsRaw==30
end
return stateFlags
end
local function autoShoot(keys)
--IGNORE IS BAD
end
damageBoostCounter=0
local function autoDamageBoost()
local samusState=getSamusState()
if samusState.Hurt then
gui.text(1,1,'OUCH!')
local buttonToPress={}
buttonToPress['A']=1
buttonToPress['B']=1
if damageBoostCounter>0 then buttonToPress[samusState.Left and "Right" or "Left"]=1 end
joypad.set(buttonToPress,1)
damageBoostCounter=damageBoostCounter+1
elseif samusState.DamageBoost then
local buttonToPress={}
buttonToPress[samusState.Left and "Left" or "Right"]=1
buttonToPress['A']=1
buttonToPress['B']=1
joypad.set(buttonToPress,1)
end
end
local function autoBoost()
local speedbooster=memory.read_u8(0x0B3F)
if speedbooster>=4 then
joypad.set({Down=1},1)
end
end
while true do
if forms.ischecked(autoShineActivated) then
autoBoost()
end
if forms.ischecked(autoDamageBoostActivated) then
autoDamageBoost()
end
if forms.ischecked(homingMissileActivated) then
homingMissile()
end
emu.frameadvance()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment