Last active
February 6, 2017 21:07
-
-
Save Putnam3145/c854c25d4bc6a92f4c40 to your computer and use it in GitHub Desktop.
A bunch of dumb BizHawk hacks I've made for Super Metroid.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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