Added some of Miau's Lua scripts
This commit is contained in:
parent
ae53895a13
commit
95d2e2b4e7
|
@ -0,0 +1,439 @@
|
|||
SCRIPT_TITLE = "Gradius - Bullet Hell"
|
||||
SCRIPT_VERSION = "1.0"
|
||||
|
||||
require "m_utils"
|
||||
m_require("m_utils",0)
|
||||
|
||||
--[[
|
||||
Gradius - Bullet Hell
|
||||
version 1.0 by miau
|
||||
|
||||
Visit http://morphcat.de/lua/ for the most recent version and other scripts.
|
||||
|
||||
|
||||
Controls
|
||||
Press select to fire a bomb that will destroy all enemy bullets and grant you
|
||||
invincibility for a short period of time.
|
||||
|
||||
Supported roms
|
||||
Gradius (J), Gradius (U), Gradius (E)
|
||||
|
||||
Known bugs
|
||||
- dying from blue bullets doesn't trigger the death sound effect
|
||||
-]]
|
||||
|
||||
--configurable vars
|
||||
local BOMBS_PER_LIFE = 5
|
||||
local HITBOX = {-2, 4, 9, 9} --vic viper's hit box for collision detection with blue bullets
|
||||
--------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
local MAX_EXSPR = 64
|
||||
local timer = 0
|
||||
local spr = {}
|
||||
local exspr = {}
|
||||
local exsprdata = {}
|
||||
local deathtimer = 0
|
||||
local bombtimer = 0
|
||||
local paused = 0
|
||||
local bombs = BOMBS_PER_LIFE
|
||||
local bulletimg = ""
|
||||
|
||||
|
||||
function makebinstr(t)
|
||||
local str = ""
|
||||
for i,v in ipairs(t) do
|
||||
str = str..string.char(v)
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
function initialize()
|
||||
--Transparency doesn't seem to work for gd images, bummer!
|
||||
bulletimg = makebinstr( {
|
||||
0xff, 0xfe, 0, 0x6, 0, 0x6, 0x1, 0xff,
|
||||
0xff, 0xff, 0xff, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0x2, 0x33, 0x6e, 0,
|
||||
0x2, 0x33, 0x6e, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0x2, 0x33, 0x6e, 0, 0x4d, 0xb6, 0xff, 0,
|
||||
0xdb, 0xff, 0xfc, 0, 0x2, 0x33, 0x6e, 0,
|
||||
0, 0, 0, 0, 0x2, 0x33, 0x6e, 0,
|
||||
0x4d, 0xb6, 0xff, 0, 0x4d, 0xb6, 0xff, 0,
|
||||
0xdb, 0xff, 0xfc, 0, 0xdb, 0xff, 0xfc, 0,
|
||||
0x2, 0x33, 0x6e, 0, 0x2, 0x33, 0x6e, 0,
|
||||
0xdb, 0xff, 0xfc, 0, 0xdb, 0xff, 0xfc, 0,
|
||||
0x4d, 0xb6, 0xff, 0, 0x4d, 0xb6, 0xff, 0,
|
||||
0x2, 0x33, 0x6e, 0, 0, 0, 0, 0,
|
||||
0x2, 0x33, 0x6e, 0, 0xdb, 0xff, 0xfc, 0,
|
||||
0x4d, 0xb6, 0xff, 0, 0x2, 0x33, 0x6e, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0x2, 0x33, 0x6e, 0,
|
||||
0x2, 0x33, 0x6e, 0, 0, 0, 0, 0,
|
||||
0, 0, 0 } )
|
||||
|
||||
for i=0,31 do
|
||||
spr[i] = {
|
||||
status=0,
|
||||
id=0,
|
||||
x=0,
|
||||
y=0,
|
||||
timer=-1,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function createexsprite(s)
|
||||
for i=0,MAX_EXSPR-1 do
|
||||
if(exspr[i]==nil) then
|
||||
exspr[i]=s
|
||||
if(exspr[i].id==nil) then
|
||||
exspr[i].id=0
|
||||
end
|
||||
if(exspr[i].x==nil) then
|
||||
exspr[i].x=0
|
||||
end
|
||||
if(exspr[i].y==nil) then
|
||||
exspr[i].y=0
|
||||
end
|
||||
if(exspr[i].vx==nil) then
|
||||
exspr[i].vx=0
|
||||
end
|
||||
if(exspr[i].vy==nil) then
|
||||
exspr[i].vy=0
|
||||
end
|
||||
if(exspr[i].timer==nil) then
|
||||
exspr[i].timer=0
|
||||
end
|
||||
if(exspr[i].ai==nil) then
|
||||
exspr[i].ai=""
|
||||
end
|
||||
return exspr[i]
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function destroyallexsprites()
|
||||
exspr = {}
|
||||
end
|
||||
|
||||
function destroyexsprite(i)
|
||||
exspr[i] = nil
|
||||
end
|
||||
|
||||
function destroysprite(i)
|
||||
memory.writebyte(0x100+i,0x00)
|
||||
memory.writebyte(0x120+i,0x00)
|
||||
memory.writebyte(0x300+i,0x00)
|
||||
end
|
||||
|
||||
|
||||
function drawexsprite(id,x,y)
|
||||
gui.gdoverlay(x, y, bulletimg)
|
||||
end
|
||||
|
||||
|
||||
function getvicdistance(x,y)
|
||||
return getdistance(vic.x+4,vic.y+8,x,y)
|
||||
end
|
||||
|
||||
function doexspriteai(s)
|
||||
if(s.ai=="Stray") then
|
||||
if(s.timer==0) then
|
||||
s.vx = -3
|
||||
s.vy = AND(timer,0x0F) / 8 - 1
|
||||
end
|
||||
elseif(s.ai=="AimOnce") then
|
||||
if(s.timer==0) then
|
||||
s.vx,s.vy = get_vdir(s,vic)
|
||||
s.vx = s.vx * 2
|
||||
s.vy = s.vy * 2
|
||||
--s.vy = AND(timer,0x0F) / 8 - 1
|
||||
end
|
||||
elseif(s.ai=="AimDelayed") then
|
||||
if(s.timer>=30 and s.timer<=33) then
|
||||
local x,y = get_vdir(s,vic)
|
||||
s.vx = (x+s.vx)
|
||||
s.vy = (y+s.vy)
|
||||
end
|
||||
elseif(s.ai=="AimRight") then
|
||||
if(s.timer==0) then
|
||||
s.vx,s.vy = get_vdir(s,vic)
|
||||
s.vx = s.vx * 2.5
|
||||
s.vy = s.vy * 1.5
|
||||
end
|
||||
elseif(s.ai=="AimLeft") then
|
||||
if(s.timer==0) then
|
||||
s.vx,s.vy = get_vdir(s,vic)
|
||||
s.vx = s.vx * 1.5
|
||||
s.vy = s.vy * 2.5
|
||||
end
|
||||
elseif(s.ai=="BossPattern1") then
|
||||
if(s.timer==0) then
|
||||
s.vx = math.random(-100,0)/50
|
||||
s.vy = math.random(-100,0)/70
|
||||
elseif(s.timer>=30 and s.timer <=35) then
|
||||
s.vx=s.vx/1.1
|
||||
s.vy=s.vy/1.1
|
||||
elseif(s.timer==70) then
|
||||
local x,y = get_vdir(s,vic)
|
||||
s.vx = x*3
|
||||
s.vy = y*3
|
||||
end
|
||||
elseif(s.ai=="LimitedLifeSpan") then
|
||||
if(s.timer>120) then
|
||||
s.x=999 --results in death
|
||||
end
|
||||
end
|
||||
|
||||
if(s.timer>600) then --delete extended sprites after 10 seconds in case one gets stuck on screen
|
||||
s.x=999
|
||||
end
|
||||
end
|
||||
|
||||
function doboss1ai(s)
|
||||
if(s.timer>80 and s.timer<320 and AND(s.timer,63)==0) then
|
||||
createexsprite({x=s.x,y=s.y,ai="BossPattern1"})
|
||||
createexsprite({x=s.x,y=s.y,ai="BossPattern1"})
|
||||
createexsprite({x=s.x,y=s.y,ai="BossPattern1"})
|
||||
createexsprite({x=s.x,y=s.y,ai="BossPattern1"})
|
||||
createexsprite({x=s.x,y=s.y,ai="BossPattern1"})
|
||||
createexsprite({x=s.x,y=s.y,ai="BossPattern1"})
|
||||
createexsprite({x=s.x,y=s.y,ai="BossPattern1"})
|
||||
end
|
||||
if(s.timer>320 and s.timer<520) then --pattern2 a
|
||||
if(math.mod(s.timer,27)<=9 and AND(s.timer,3)==3) then
|
||||
createexsprite({x=s.x,y=s.y,vx=-0.2,ai="AimDelayed"})
|
||||
end
|
||||
end
|
||||
if(s.timer>320 and s.timer<520) then --pattern2 b
|
||||
if(AND(s.timer,63)==0) then
|
||||
createexsprite({x=s.x,y=s.y,vx=-0.7,vy=-1.6})
|
||||
createexsprite({x=s.x,y=s.y,vx=-1.1,vy=-0.8})
|
||||
createexsprite({x=s.x,y=s.y,vx=-1.2,vy=-0})
|
||||
createexsprite({x=s.x,y=s.y,vx=-1.1,vy=0.8})
|
||||
createexsprite({x=s.x,y=s.y,vx=-0.7,vy=1.6})
|
||||
end
|
||||
elseif(s.timer>520) then
|
||||
s.timer = 60
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function dospriteai(s)
|
||||
if(s.id==0x85) then --Fan
|
||||
if(s.timer==30) then
|
||||
createexsprite({x=s.x,y=s.y,ai="Stray"})
|
||||
end
|
||||
elseif(s.id==0x86) then --Jumper
|
||||
if(AND(s.timer,127)==40) then
|
||||
createexsprite({x=s.x,y=s.y,vx=-1.5,vy=-0.5})
|
||||
createexsprite({x=s.x,y=s.y,vx=-1,vy=-1.1})
|
||||
createexsprite({x=s.x,y=s.y,vx=0,vy=-1.4})
|
||||
createexsprite({x=s.x,y=s.y,vx=1,vy=-1.1})
|
||||
createexsprite({x=s.x,y=s.y,vx=1.5,vy=-0.5})
|
||||
end
|
||||
elseif(s.id==0x88) then --Rugul
|
||||
if(AND(s.timer,63)==30) then
|
||||
createexsprite({x=s.x,y=s.y,ai="Stray"})
|
||||
end
|
||||
elseif(s.id==0x84 or s.id==0x9C) then --Fose, Uska(?)
|
||||
if(AND(s.timer,63)==30) then
|
||||
createexsprite({x=s.x,y=s.y,vx=0,vy=-2})
|
||||
elseif(AND(s.timer,63)==60) then
|
||||
createexsprite({x=s.x,y=s.y,vx=0,vy=2})
|
||||
end
|
||||
elseif(s.id==0x89 or s.id==0x8C) then --Rush
|
||||
if(AND(timer,63)==5) then
|
||||
createexsprite({x=s.x,y=s.y,vx=-1,vy=-1})
|
||||
end
|
||||
elseif(s.id==0x96) then --Moai
|
||||
elseif(s.id==0x97) then --Mother and Child
|
||||
if(AND(timer,7)==0) then
|
||||
local t = s.timer/15
|
||||
createexsprite({x=s.x+16,y=s.y+16,vx=math.sin(t)-1,vy=math.cos(t),ai="LimitedLifeSpan"})
|
||||
end
|
||||
elseif(s.id==0x8B) then --Zabu
|
||||
if(s.timer==5) then
|
||||
createexsprite({x=s.x,y=s.y,vx=0.5,ai="AimDelayed"})
|
||||
end
|
||||
elseif(s.id==0x92 or s.id==0x93 or s.id==0x87 or s.id==0x91) then --Dee-01, Ducker
|
||||
--if(s.timer==5) then
|
||||
local t = AND(s.timer,127)
|
||||
if(t>60 and t<79 and AND(s.timer,3)==3) then
|
||||
--createexsprite({x=s.x,y=s.y,ai="AimOnce"})
|
||||
createexsprite({x=s.x,y=s.y,ai="AimOnce"})
|
||||
end
|
||||
elseif(s.id==0x98) then --boss...
|
||||
doboss1ai(s)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function updatevars()
|
||||
paused = memory.readbyte(0x0015)
|
||||
if(paused==1) then
|
||||
return
|
||||
end
|
||||
--load original sprites from ram
|
||||
for i=0,31 do
|
||||
--if(i==0 or memory.readbyte(0x0300+i)~=0) then
|
||||
if(memory.readbyte(0x0300+i)~=spr[i].id) then
|
||||
spr[i].timer = 0
|
||||
end
|
||||
spr[i].status=memory.readbyte(0x0100+i) --1=alive, 2=dead
|
||||
spr[i].id=memory.readbyte(0x0300+i)
|
||||
spr[i].x=memory.readbyte(0x0360+i)
|
||||
spr[i].y=memory.readbyte(0x0320+i)
|
||||
spr[i].timer=spr[i].timer+1
|
||||
if(spr[i].id==0) then
|
||||
spr[i].timer = 0
|
||||
else
|
||||
dospriteai(spr[i])
|
||||
end
|
||||
|
||||
if(i>3 and bombtimer>0 and getvicdistance(spr[i].x+4,spr[i].y+4)<30) then
|
||||
if(spr[i].id~=0x29 and spr[i].id~=0x01 and spr[i].id~=0x99 and spr[i].id~=0x98 and spr[i].id~=0x94 and spr[i].id~=0x97 and spr[i].id~=0x96 and spr[i].id~=0x1E) then
|
||||
--excluded: hidden bonus (0x29), power ups and moai bullets (0x01), boss (0x99+0x98), tentacle (0x94), mother (0x97), moai (0x96), gate (0x1E)
|
||||
destroysprite(i)
|
||||
end
|
||||
end
|
||||
--end
|
||||
end
|
||||
vic = spr[0]
|
||||
|
||||
|
||||
|
||||
|
||||
if(deathtimer>0) then
|
||||
if(deathtimer==120) then
|
||||
destroyallexsprites()
|
||||
deathtimer = 0
|
||||
bombs = BOMBS_PER_LIFE
|
||||
else
|
||||
if(deathtimer==1) then
|
||||
--this is part of what gradius does to kill vic viper...
|
||||
--faster and without the annoying sound effect. who cares!
|
||||
memory.writebyte(0x4C,0x78)
|
||||
memory.writebyte(0x0100,0x02) --status = dead
|
||||
memory.writebyte(0x0160,0x00)
|
||||
memory.writebyte(0x0140,0x00)
|
||||
memory.writebyte(0x1B,0xA0)
|
||||
memory.writebyte(0x0120,0x2D) --chr?--
|
||||
end
|
||||
deathtimer = deathtimer + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local jp = joypad.get(1)
|
||||
if(jp.select and jp.select~=last_select and bombs>0) then
|
||||
bombtimer = 1
|
||||
bombs = bombs - 1
|
||||
destroyallexsprites()
|
||||
--destroy bullets
|
||||
for i=1,31 do
|
||||
if(spr[i].id<4 and spr[i].id~=1) then
|
||||
destroysprite(i)
|
||||
end
|
||||
end
|
||||
end
|
||||
last_select = jp.select
|
||||
|
||||
|
||||
if(last_vic_status~=vic.status) then
|
||||
if(vic.status==2) then --vic died in the original game, start death timer to destroy all extended sprites
|
||||
deathtimer = 1
|
||||
end
|
||||
end
|
||||
last_vic_status = vic.status
|
||||
|
||||
--calculations on extended sprites
|
||||
for i=0,MAX_EXSPR-1 do
|
||||
if(exspr[i]~=nil) then
|
||||
if(bombtimer>0 and getvicdistance(exspr[i].x+4,exspr[i].y+4)<25) then
|
||||
destroyexsprite(i)
|
||||
else
|
||||
doexspriteai(exspr[i])
|
||||
exspr[i].timer = exspr[i].timer + 1
|
||||
exspr[i].x=exspr[i].x+exspr[i].vx
|
||||
exspr[i].y=exspr[i].y+exspr[i].vy
|
||||
if(exspr[i].x>255 or exspr[i].x<0 or exspr[i].y>255 or exspr[i].y<0) then
|
||||
--destroy exsprite
|
||||
exspr[i]=nil
|
||||
break
|
||||
end
|
||||
--collision check with vic viper
|
||||
if(deathtimer==0 and vic.status==1 and exspr[i].x>=vic.x+HITBOX[1] and exspr[i].x<=vic.x+HITBOX[3]
|
||||
and exspr[i].y>=vic.y+HITBOX[2] and exspr[i].y<=vic.y+HITBOX[4]) then
|
||||
deathtimer = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
function render()
|
||||
--bcbox(vic.x-2, vic.y+4, vic.x+9, vic.y+9, "#ffffff")
|
||||
|
||||
gui.text(0, 8, string.format("bombs %d",bombs));
|
||||
--gui.text(0, 8, string.format("Lives %d",memory.readbyte(0x0020)));
|
||||
--gui.text(0, 28, string.format("bombtimer %d",bombtimer));
|
||||
|
||||
--[[for i=1,31 do
|
||||
if(spr[i].id~=0) then
|
||||
gui.text(spr[i].x, spr[i].y, string.format("%X",spr[i].id));
|
||||
end
|
||||
end--]]
|
||||
|
||||
for i=0,MAX_EXSPR-1 do
|
||||
if(exspr[i]~=nil) then
|
||||
drawexsprite(exspr[i].id,exspr[i].x,exspr[i].y)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if(bombtimer>0) then
|
||||
if(bombtimer<12) then
|
||||
memory.writebyte(0x11,0xFF) --monochrome screen
|
||||
else
|
||||
memory.writebyte(0x11,0x1E)
|
||||
end
|
||||
bombtimer = bombtimer + 1
|
||||
for i=0,64 do
|
||||
local x = vic.x+4+math.sin(i)*bombtimer*4 + math.random(0,12)
|
||||
local y = vic.y+8+math.cos(i)*bombtimer*4 + math.random(0,12)
|
||||
local c = 255-bombtimer
|
||||
local cs = string.format("#%02x%02x00",c,c)
|
||||
bcpixel(x,y,cs)
|
||||
bcpixel(x-1,y,cs)
|
||||
bcpixel(x+1,y,cs)
|
||||
bcpixel(x,y+1,cs)
|
||||
bcpixel(x,y-1,cs)
|
||||
|
||||
x = vic.x+4+math.sin(i)*(20+math.sin(bombtimer/5))
|
||||
y = vic.y+8+math.cos(i)*(20+math.sin(bombtimer/5))
|
||||
bcpixel(x,y,cs)
|
||||
bcpixel(x-1,y,cs)
|
||||
bcpixel(x,y-1,cs)
|
||||
end
|
||||
if(bombtimer==180) then
|
||||
bombtimer=0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
initialize()
|
||||
vic = spr[0]
|
||||
while(true) do
|
||||
updatevars()
|
||||
render()
|
||||
EMU.frameadvance()
|
||||
timer = timer + 1
|
||||
end
|
|
@ -0,0 +1,730 @@
|
|||
SCRIPT_TITLE = "Mega Man 2 LASER EYES"
|
||||
SCRIPT_VERSION = "1.0"
|
||||
|
||||
require "m_utils"
|
||||
m_require("m_utils",0)
|
||||
|
||||
--[[
|
||||
Mega Man 2 LASER EYES
|
||||
version 1.0 by miau
|
||||
|
||||
Visit http://morphcat.de/lua/ for the most recent version and other scripts.
|
||||
|
||||
|
||||
Controls
|
||||
Press select to fire a laser from Mega Man's eyes aimed at the closest object.
|
||||
Left-click to drag and drop objects.
|
||||
Middle-clicking instantly moves Mega Man to the cursor position.
|
||||
|
||||
Supported roms
|
||||
Rockman 2 - Dr Wily no Nazo (J), Mega Man 2 (U), Mega Man 2 (E)
|
||||
|
||||
Known bugs
|
||||
- shooting lasers at bosses is glitchy, do it at your own risk
|
||||
- eyes might turn black for a short period of time after screen transition
|
||||
- some objects have duplicate IDs which will result in wrong names being shown for them
|
||||
|
||||
-]]
|
||||
|
||||
--configurable vars
|
||||
local show_info = false --show sprite info on startup
|
||||
local show_cursor = false --set this to true when recording a video
|
||||
|
||||
--sound effects to use for various script events, nil to disable
|
||||
local SFX_LASER = 0x25
|
||||
local SFX_EXPLOSION = 0x2B
|
||||
local SFX_TARGET = nil --0x39 --0x21
|
||||
--------------------------------------------------------------------------------------------
|
||||
--List of sound effects
|
||||
--0x21 press
|
||||
--0x22 peeewwwwwww
|
||||
--0x23 metal blade
|
||||
--0x24 mega buster
|
||||
--0x25 sniper armor shot?
|
||||
--0x26 hit1
|
||||
--0x27 air shooter
|
||||
--0x28 energy
|
||||
--0x29 touch ground
|
||||
--0x2A wily thing
|
||||
--0x2B destroy1
|
||||
--0x2C ??
|
||||
--0x2D reflected shot
|
||||
--0x2E ?? (metal blade-like noise channel usage, short)
|
||||
--0x2F menu selector
|
||||
--0x30 mega man appear
|
||||
--0x31 leaf shield
|
||||
--0x32 menu open
|
||||
--0x33 ?? (short, low noise)
|
||||
--0x34 gate open
|
||||
--0x35 atomic fire charge 1
|
||||
--0x36 atomic fire charge 2
|
||||
--0x37 atomic fire charge 2
|
||||
--0x38 atomic fire shot ?
|
||||
--0x39 prop-top leap
|
||||
--0x3A mega man disappearing
|
||||
--0x3B diving into water
|
||||
--0x3C appearing platform
|
||||
--0x3D wily stage lava drops
|
||||
--0x3E wily stage lava drops
|
||||
--0x3F ?? (similar to 0x27)
|
||||
--0x40 ?? (short noise)
|
||||
--0x41 death
|
||||
--0x42 e-tank/1up
|
||||
--0x43 ?? (short noise in fixed intervals)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
local sprdb = {} --enemy names source: http://megaman.wikia.com
|
||||
sprdb[0x00] = {name="Squirt"}
|
||||
sprdb[0x01] = {name="Squirt"} --spawned by Lantern Fish
|
||||
sprdb[0x04] = {name="M-445"}
|
||||
sprdb[0x07] = {name="Snapper Controller",invincible=true}
|
||||
sprdb[0x08] = {name="Snapper"}
|
||||
sprdb[0x0A] = {name="Crabbot"}
|
||||
sprdb[0x0C] = {name="Croaker"}
|
||||
sprdb[0x0D] = {name="Croaker (tiny)"}
|
||||
sprdb[0x0E] = {name="",invincible=true} --bubble...underwater mega man
|
||||
sprdb[0x0F] = {name="Lantern Fish"}
|
||||
sprdb[0x13] = {name="Platform"}
|
||||
sprdb[0x15] = {name="Beam"}
|
||||
sprdb[0x16] = {name="Bubble Bat"}
|
||||
sprdb[0x17] = {name="Robo-Rabbit"}
|
||||
sprdb[0x18] = {name="Carrot"} --or mega man being hit
|
||||
sprdb[0x1D] = {name="Mecha Monkey"}
|
||||
sprdb[0x1E] = {name="Atomic Chicken Controller",invincible=true}
|
||||
sprdb[0x1F] = {name="Atomic Chicken"}
|
||||
--sprdb[0x1B] = {name="Climbing Mega Man"} --or hot dog fire
|
||||
--sprdb[0x1C] = {name=""} --or hot dog fire controller?
|
||||
sprdb[0x21] = {name="Telly Spawn Point",invincible=true}
|
||||
sprdb[0x22] = {name="Telly"}
|
||||
sprdb[0x23] = {name="Hothead"} --or Mega Buster
|
||||
sprdb[0x24] = {name="Tackle Fire"}
|
||||
--sprdb[0x27] = {name="Light Control"}
|
||||
--sprdb[0x28] = {name="Light Control"}
|
||||
sprdb[0x29] = {name="Cogwheel"}
|
||||
sprdb[0x2A] = {name="Pierobot"}
|
||||
sprdb[0x2B] = {name="Prop-Top Controller",invincible=true}
|
||||
sprdb[0x2C] = {name="Prop-Top"}
|
||||
sprdb[0x2E] = {name="Hot Dog"}
|
||||
sprdb[0x2F] = {name="Gate"}
|
||||
sprdb[0x30] = {name="Press"}
|
||||
sprdb[0x31] = {name="Blocky"}
|
||||
sprdb[0x32] = {name="Big Fish Controller",invincible=true}
|
||||
--sprdb[0x33] = {name=""} --Bubble Lead
|
||||
sprdb[0x34] = {name="Neo Met"}
|
||||
sprdb[0x35] = {name="Bullet"} --Sniper Armor/Sniper Joe
|
||||
sprdb[0x36] = {name="Fan Fiend"} --or Metal Blade
|
||||
sprdb[0x37] = {name="Pipi Controller",invincible=true} --or Flash weapon (Time Stopper) controller(?)
|
||||
sprdb[0x38] = {name="Pipi"}
|
||||
sprdb[0x3A] = {name="Pipi Egg"} --or Item-3(?)
|
||||
sprdb[0x3B] = {name="Pipi Egg Shell"}
|
||||
sprdb[0x3C] = {name="Child Pipi"}
|
||||
sprdb[0x3D] = {name="Lightning Lord"}
|
||||
sprdb[0x3E] = {name="Thunder Chariot"}
|
||||
--sprdb[0x3F] = {name="Lightning Bolt"} --or "splash"... (mega man diving into water)
|
||||
sprdb[0x3F] = {invincible=true}
|
||||
sprdb[0x40] = {name="Air Tikki"}
|
||||
sprdb[0x41] = sprdb[0x40]
|
||||
sprdb[0x44] = {name="Air Tikki Horn"}
|
||||
sprdb[0x45] = {name="Gremlin"}
|
||||
sprdb[0x46] = {name="Spring Head"}
|
||||
sprdb[0x47] = {name="Mole Controller",invincible=true}
|
||||
sprdb[0x48] = {name="Mole (rising)"}
|
||||
sprdb[0x49] = {name="Mole (falling)"}
|
||||
sprdb[0x4B] = {name="Crazy Cannon"}
|
||||
sprdb[0x4D] = {name="Bullet (Crazy Cannon)"}
|
||||
sprdb[0x4E] = {name="Sniper Armor"}
|
||||
sprdb[0x4F] = {name="Sniper Joe"}
|
||||
sprdb[0x50] = {name="Squirm"}
|
||||
sprdb[0x51] = {name="Squirm Pipe"}
|
||||
|
||||
sprdb[0x5C] = {name="Metal Blade"}
|
||||
sprdb[0x5D] = {name="Air Shooter"}
|
||||
sprdb[0x5E] = {name="Crash Bomb"}
|
||||
|
||||
--[[sprdb[0x60] = {name="Bubble Man"}
|
||||
sprdb[0x61] = sprdb[0x60]
|
||||
sprdb[0x62] = sprdb[0x60]
|
||||
sprdb[0x63] = {name="Metal Man"} --or Falling Blocks (Dragon) (id2:80)
|
||||
sprdb[0x64] = sprdb[0x63] --or Falling Blocks (Dragon).. Dragon Controller? (id2:80)
|
||||
sprdb[0x65] = sprdb[0x63] --or Dragon Body (id2:8B)
|
||||
sprdb[0x66] = {name="Air Man"} --or Dragon Bottom (id2:8B)
|
||||
sprdb[0x67] = sprdb[0x66]
|
||||
sprdb[0x68] = sprdb[0x66]
|
||||
sprdb[0x69] = {name="Crash Man"}
|
||||
sprdb[0x6A] = sprdb[0x69] --running or wily boss no.2 (id2:8B/CB/83/C3/80)
|
||||
sprdb[0x6B] = sprdb[0x69] --jumping
|
||||
sprdb[0x70] = {name="Dragon"} --(id2:8B)
|
||||
sprdb[0x71] = {name="Big Fish"} --Wily Boss 3 (id2:83)
|
||||
--]]
|
||||
|
||||
sprdb[0x76] = {name="Large Life Energy",invincible=true}
|
||||
sprdb[0x77] = {name="Small Life Energy",invincible=true}
|
||||
sprdb[0x78] = {name="Large Weapon Energy",invincible=true}
|
||||
sprdb[0x79] = {name="Small Weapon Energy",invincible=true}
|
||||
sprdb[0x7A] = {name="E-Tank",invincible=true}
|
||||
sprdb[0x7B] = {name="1UP",invincible=true}
|
||||
|
||||
|
||||
local eyes = {}
|
||||
eyes.open = {
|
||||
{0,0,0,0,0,1,1,0,1,0,0,0,0},
|
||||
{0,0,0,0,0,1,1,0,1,0,0,0,0},
|
||||
}
|
||||
eyes.running = {
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0,0,1,1,0,1,0,0,0,0},
|
||||
{0,0,0,0,0,1,1,0,1,0,0,0,0},
|
||||
}
|
||||
eyes.shooting = {
|
||||
{0,0,0,0,0,0,0,0,0,1,1,0,1},
|
||||
{0,0,0,0,0,0,0,0,0,1,1,0,1},
|
||||
}
|
||||
eyes.ladder = {
|
||||
{0,0,0,0,0,0,0,1,1,0,0,0,0},
|
||||
{0,0,0,0,0,0,0,1,1,0,0,0,0},
|
||||
}
|
||||
eyes.closed = {
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,0,1,1,1,1,0,1,1,0,0,0},
|
||||
}
|
||||
eyes.none = {}
|
||||
|
||||
local mmeyes = eyes.open
|
||||
local timer = 0
|
||||
local spr = {}
|
||||
local last_inp = {}
|
||||
local inp = {}
|
||||
local laser = {timer=0}
|
||||
local last_laser = 0
|
||||
|
||||
|
||||
|
||||
--very limited and hacky particle engine following
|
||||
local P_MAX = 150
|
||||
local particle = {p={}}
|
||||
|
||||
function particle.laserai(pi)
|
||||
local function checkcollision(px,py,rx,ry)
|
||||
if(px>=rx-8 and px<=rx+8 and py>=ry-8 and py<=ry+8) then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,31 do
|
||||
if(spr[i].a and is_enemy(i)) then
|
||||
local px = particle.p[pi].x
|
||||
local py = particle.p[pi].y
|
||||
local px2 = particle.p[pi].x+particle.p[pi].vx*6
|
||||
local py2 = particle.p[pi].y+particle.p[pi].vy*6
|
||||
local rx = spr[i].x+spr[i].hx*256
|
||||
local ry = spr[i].y
|
||||
if(checkcollision(px,py,rx,ry) or checkcollision(px2,py2,rx,ry)) then
|
||||
--if(spr[i].hp>5) then
|
||||
-- memory.writebyte(0x06C0+i,spr[i].hp-5)
|
||||
--else
|
||||
memory.writebyte(0x06C0+i,1)
|
||||
play_sfx(SFX_EXPLOSION)
|
||||
particle.explosion(spr[i].x+spr[i].hx*256,spr[i].y)
|
||||
destroy_sprite(i)
|
||||
--end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function particle.create(new)
|
||||
for i=0,P_MAX-1 do
|
||||
if(particle.p[i]==nil) then
|
||||
particle.p[i]=new
|
||||
if(particle.p[i].x==nil) then
|
||||
particle.p[i].x=0
|
||||
end
|
||||
if(particle.p[i].y==nil) then
|
||||
particle.p[i].y=0
|
||||
end
|
||||
if(particle.p[i].vx==nil) then
|
||||
particle.p[i].vx=0
|
||||
end
|
||||
if(particle.p[i].vy==nil) then
|
||||
particle.p[i].vy=0
|
||||
end
|
||||
if(particle.p[i].timer==nil) then
|
||||
particle.p[i].timer=0
|
||||
end
|
||||
if(particle.p[i].lspan==nil) then
|
||||
particle.p[i].lspan=60
|
||||
end
|
||||
if(particle.p[i].color==nil) then
|
||||
particle.p[i].color="#FFFFFF"
|
||||
end
|
||||
return i
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function particle.explosion(x,y) --faster than using particle.create
|
||||
local j = 0
|
||||
for i=0,P_MAX-1 do
|
||||
if(particle.p[i]==nil) then
|
||||
local vx = math.random(-50,50)/30
|
||||
local vy = math.random(-50,50)/30
|
||||
local color = "#FF0000"
|
||||
particle.p[i] = {}
|
||||
particle.p[i].x = x
|
||||
particle.p[i].y = y
|
||||
particle.p[i].vx = vx
|
||||
particle.p[i].vy = vy
|
||||
particle.p[i].color = color
|
||||
particle.p[i].lspan = math.random(20,40)
|
||||
particle.p[i].timer=0
|
||||
if(j==40) then
|
||||
return
|
||||
end
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function particle.destroy(i)
|
||||
particle.p[i] = nil
|
||||
end
|
||||
|
||||
|
||||
function particle.update()
|
||||
for i=0,P_MAX-1 do
|
||||
if(particle.p[i]) then
|
||||
if(particle.p[i].timer >= particle.p[i].lspan) then
|
||||
particle.destroy(i)
|
||||
else
|
||||
if(particle.p[i].aifunc) then
|
||||
particle.p[i].aifunc(i)
|
||||
end
|
||||
if(particle.p[i]) then
|
||||
particle.p[i].x = particle.p[i].x + particle.p[i].vx
|
||||
particle.p[i].y = particle.p[i].y + particle.p[i].vy
|
||||
particle.p[i].timer = particle.p[i].timer + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function particle.render(xdisp,ydisp)
|
||||
local j=0
|
||||
for i=0,P_MAX-1 do
|
||||
if(particle.p[i]) then
|
||||
bcline2(particle.p[i].x-xdisp,particle.p[i].y-ydisp, particle.p[i].x-xdisp+particle.p[i].vx*6,particle.p[i].y+particle.p[i].vy*6-ydisp, particle.p[i].color)
|
||||
if(particle.p[i].aifunc) then
|
||||
bcline2(particle.p[i].x-xdisp,particle.p[i].y+1-ydisp, particle.p[i].x-xdisp+particle.p[i].vx*6,particle.p[i].y+particle.p[i].vy*6+1-ydisp, particle.p[i].color)
|
||||
end
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function initialize()
|
||||
for i=0,31 do
|
||||
spr[i] = {
|
||||
a=0,
|
||||
id=0,
|
||||
id2=0,
|
||||
x=0,
|
||||
y=0,
|
||||
hp=0,
|
||||
--timer=-1,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function unselect_all()
|
||||
for i=0,31 do
|
||||
spr[i].selected=false
|
||||
spr[i].moving = false
|
||||
end
|
||||
end
|
||||
|
||||
function getx16(s)
|
||||
return s.hx*256+s.x
|
||||
end
|
||||
|
||||
function get_target()
|
||||
--closest target
|
||||
local closest = nil
|
||||
local dmin = 9999
|
||||
for i=1,31 do
|
||||
if(spr[i].a and is_enemy(i) and spr[i].seltimer>=10 and
|
||||
( (spr[i].sx>=megaman.sx and megaman.dir==1)
|
||||
or (spr[i].sx<=megaman.sx and megaman.dir==-1)
|
||||
or megaman.dir==0)) then
|
||||
local d = getdistance(megaman.sx,megaman.sy,spr[i].sx,spr[i].sy)
|
||||
if(d<dmin) then
|
||||
dmin = d
|
||||
closest = i
|
||||
end
|
||||
end
|
||||
end
|
||||
return closest
|
||||
end
|
||||
|
||||
|
||||
function destroy_sprite(i)
|
||||
memory.writebyte(0x0400+i,0)
|
||||
memory.writebyte(0x0420+i,0)
|
||||
spr[i]={}
|
||||
end
|
||||
|
||||
function is_enemy(i)
|
||||
if(i==0) then
|
||||
return false
|
||||
end
|
||||
if(spr[i].a) then
|
||||
local id = spr[i].id
|
||||
if(sprdb[id]) then
|
||||
if(sprdb[id].invincible) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function play_sfx(n)
|
||||
if(n) then
|
||||
memory.writebyte(0x66,0x01)
|
||||
memory.writebyte(0x0580,n)
|
||||
end
|
||||
end
|
||||
|
||||
function update_vars()
|
||||
--paused = memory.readbyte(0x0015)
|
||||
--if(paused==1) then
|
||||
-- return
|
||||
--end
|
||||
|
||||
scroll_x = memory.readbyte(0x1F)
|
||||
scroll_hx = memory.readbyte(0x20)
|
||||
|
||||
particle.update()
|
||||
|
||||
inp = input.get()
|
||||
|
||||
--load original sprites from ram
|
||||
for i=0,31 do
|
||||
--if(i==0 or memory.readbyte(0x0300+i)~=0) then
|
||||
if(memory.readbyte(0x0300+i)~=spr[i].id) then
|
||||
spr[i].timer = 0
|
||||
end
|
||||
spr[i].id=memory.readbyte(0x0400+i)
|
||||
spr[i].id2=memory.readbyte(0x0420+i)
|
||||
spr[i].hx=memory.readbyte(0x0440+i)
|
||||
spr[i].x=memory.readbyte(0x0460+i)
|
||||
spr[i].y=memory.readbyte(0x04A0+i)
|
||||
spr[i].sx=AND(spr[i].x+255-scroll_x,255) --screen position
|
||||
spr[i].sy=spr[i].y
|
||||
spr[i].hp=memory.readbyte(0x06C0+i)
|
||||
spr[i].a=(memory.readbyte(0x0420+i)>=0x80)
|
||||
if(spr[i].a==false) then
|
||||
spr[i].seltimer=nil
|
||||
end
|
||||
|
||||
if(spr[i].a) then
|
||||
if(inp.xmouse>=spr[i].sx-8 and inp.xmouse<=spr[i].sx+8 and inp.ymouse>=spr[i].sy-8 and inp.ymouse<=spr[i].sy+8) then
|
||||
spr[i].hover = true
|
||||
spr[i].clicked = inp.leftclick
|
||||
if(inp.leftclick and last_inp.leftclick==nil) then
|
||||
unselect_all()
|
||||
spr[i].selected=true
|
||||
end
|
||||
else
|
||||
spr[i].hover = false
|
||||
if(inp.leftclick==nil) then
|
||||
spr[i].clicked = false
|
||||
end
|
||||
end
|
||||
|
||||
--auto-target
|
||||
if(is_enemy(i)) then
|
||||
if(spr[i].seltimer==nil) then
|
||||
spr[i].seltimer=1
|
||||
else
|
||||
spr[i].seltimer = spr[i].seltimer + 1
|
||||
end
|
||||
end
|
||||
|
||||
if(spr[i].selected) then
|
||||
--[[if(inp.delete) then
|
||||
destroy_sprite(i)
|
||||
elseif(inp.pagedown) then
|
||||
memory.writebyte(0x0400+i,spr[i].id-1)
|
||||
elseif(inp.pageup) then
|
||||
memory.writebyte(0x0400+i,spr[i].id+1)
|
||||
end-]]
|
||||
|
||||
if(spr[i].clicked) then
|
||||
if(inp.xmouse~=last_inp.xmouse or inp.ymouse~=last_inp.ymouse) then
|
||||
spr[i].moving = true
|
||||
end
|
||||
else
|
||||
spr[i].moving = false
|
||||
end
|
||||
end
|
||||
|
||||
if(spr[i].moving) then
|
||||
local x = inp.xmouse+scroll_x
|
||||
memory.writebyte(0x0460+i,inp.xmouse+scroll_x)
|
||||
memory.writebyte(0x04A0+i,inp.ymouse)
|
||||
memory.writebyte(0x0440+i,scroll_hx+math.floor(x/256))
|
||||
end
|
||||
|
||||
end
|
||||
--end
|
||||
end
|
||||
|
||||
megaman = spr[0]
|
||||
if(megaman.id2==0x80) then
|
||||
megaman.dir=-1
|
||||
else
|
||||
megaman.dir=1
|
||||
end
|
||||
if(megaman.id==0x1B) then
|
||||
megaman.dir = 0
|
||||
end
|
||||
|
||||
|
||||
if(inp.middleclick) then --change mega man's coordinates
|
||||
local x = inp.xmouse+scroll_x
|
||||
memory.writebyte(0x0460,x)
|
||||
memory.writebyte(0x04A0,inp.ymouse)
|
||||
memory.writebyte(0x0440,scroll_hx+math.floor(x/256))
|
||||
end
|
||||
|
||||
--LASER!!!
|
||||
jp = joypad.read(1)
|
||||
if(jp.select and (last_jp.select==nil or timer-last_laser>22)) then
|
||||
local t = get_target()
|
||||
local vx,vy
|
||||
play_sfx(SFX_LASER)
|
||||
if(t) then
|
||||
vx,vy = getvdir(megaman.sx,megaman.sy-3,spr[t].sx,spr[t].sy)
|
||||
vx = vx * 10
|
||||
vy = vy * 10
|
||||
else
|
||||
if(megaman.dir==0) then
|
||||
vx = 0
|
||||
vy = -10
|
||||
else
|
||||
vx = megaman.dir*10
|
||||
vy = 0
|
||||
end
|
||||
end
|
||||
last_laser = timer
|
||||
|
||||
particle.create({x=getx16(megaman),y=megaman.y-3,vx=vx,vy=vy,color="#FF0000",aifunc=particle.laserai})
|
||||
end
|
||||
|
||||
if(inp.xmouse<83 and inp.ymouse<18) then
|
||||
if(inp.leftclick and last_inp.leftclick==nil) then
|
||||
if(show_info) then
|
||||
show_info = false
|
||||
else
|
||||
show_info = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
last_jp = jp
|
||||
last_inp = inp
|
||||
end
|
||||
|
||||
function render()
|
||||
|
||||
if(show_info) then
|
||||
gui.text(0,8,"Sprite Info: ON")
|
||||
else
|
||||
gui.text(0,8,"Sprite Info: OFF")
|
||||
end
|
||||
if(inp.xmouse<83 and inp.ymouse<18) then
|
||||
if(show_info) then
|
||||
gui.drawbox(0,9,77,17,"red")
|
||||
else
|
||||
gui.drawbox(0,9,83,17,"red")
|
||||
end
|
||||
end
|
||||
|
||||
particle.render(scroll_x+scroll_hx*256,0)
|
||||
|
||||
--LASER EYES!!!
|
||||
--TODO: prevent play_sfx from playing sounds during title screen/stage select
|
||||
if(memory.readbyte(0x580) == 0x0D) then --title screen tune is being played
|
||||
megaman.sx=211
|
||||
megaman.sy=131
|
||||
megaman.dir = -1
|
||||
mmeyes = eyes.open
|
||||
|
||||
--lasers during title screen
|
||||
if(AND(timer,7)==0 and math.random(0,1)==0) then
|
||||
--play_sfx(SFX_LASER)
|
||||
local vx,vy=getvdir(megaman.sx,megaman.sy-3,0,math.random(30,220))
|
||||
vx=vx*10
|
||||
vy=vy*10
|
||||
particle.create({x=megaman.sx+6,y=megaman.sy-3,vx=vx,vy=vy,color="#FF0000",aifunc=LaserAI})
|
||||
mmeyes = eyes.none
|
||||
end
|
||||
elseif(megaman.a) then --sprite active
|
||||
local f = memory.readbyte(0x06A0)*256 + memory.readbyte(0x0680)
|
||||
local frame = memory.readbyte(0x06A0)
|
||||
local ftimer = memory.readbyte(0x0680)
|
||||
if(memory.readbyte(0x69)~=0x0E) then --menu opened or "stage intro" tune
|
||||
mmeyes = eyes.none
|
||||
elseif(megaman.id==0x00) then --BLINK! change occurs on next frame
|
||||
if(f >= 0xA01) then
|
||||
mmeyes = eyes.closed
|
||||
elseif(f>=0x001) then
|
||||
mmeyes = eyes.open
|
||||
end
|
||||
elseif(megaman.id==0x01 or megaman.id==0x03 or megaman.id==0x05 or megaman.id==0x07 or megaman.id==0x0B or megaman.id==0x11 or megaman.id==0x13) then
|
||||
mmeyes = eyes.shooting
|
||||
elseif(megaman.id==0x04 or megaman.id==0x0C or megaman.id==0x0D or megaman.id==0x10) then
|
||||
mmeyes = eyes.open
|
||||
elseif(megaman.id==0x08 or megaman.id==0x09 or megaman.id==0x14) then
|
||||
if((f>=0x201 and f<=0x300) or (f>=0x001 and f<=0x100)) then
|
||||
mmeyes = eyes.running
|
||||
else
|
||||
mmeyes = eyes.open
|
||||
end
|
||||
elseif(megaman.id==0x18) then --getting hurt
|
||||
mmeyes = eyes.closed
|
||||
elseif(megaman.id==0x1C or megaman.id==0x1E) then --mega buster, other weapons
|
||||
mmeyes = eyes.ladder
|
||||
else--if(megaman.id==0x1A or megaman.id==0x1B) then --respawning after death, climbing a ladder
|
||||
mmeyes = eyes.none
|
||||
end
|
||||
|
||||
--if(megaman.hp==0) then
|
||||
-- mmeyes = eyes.none
|
||||
--end
|
||||
else
|
||||
mmeyes = eyes.none
|
||||
end
|
||||
|
||||
if(mmeyes ~= eyes.none) then
|
||||
local eyecolor = "#FF0000"
|
||||
if(timer-last_laser<5) then
|
||||
eyecolor = "#FFFFFF"
|
||||
end
|
||||
if(megaman.dir==-1) then
|
||||
for y=1,4 do
|
||||
if(mmeyes[y]) then
|
||||
for x=1,14 do
|
||||
if(mmeyes[y][15-x]==1) then
|
||||
bcpixel(megaman.sx-9+x,megaman.sy-5+y,eyecolor)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for y=1,4 do
|
||||
if(mmeyes[y]) then
|
||||
for x=1,14 do
|
||||
if(mmeyes[y][x]==1) then
|
||||
bcpixel(megaman.sx-5+x,megaman.sy-5+y,eyecolor)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
for i=0,31 do
|
||||
if(spr[i].a) then
|
||||
local x,y
|
||||
local boxcolor
|
||||
if(spr[i].clicked) then
|
||||
boxcolor="#AA5500"
|
||||
elseif(spr[i].hover) then
|
||||
boxcolor="#FFCCAA"
|
||||
else
|
||||
boxcolor=nil
|
||||
end
|
||||
x = spr[i].sx
|
||||
y = spr[i].sy
|
||||
if(boxcolor) then
|
||||
bcbox(x-9,y-9,x+9,y+9,boxcolor)
|
||||
end
|
||||
|
||||
if(spr[i].seltimer) then
|
||||
if(spr[i].seltimer<30) then
|
||||
local b=30-spr[i].seltimer
|
||||
local c = (30-spr[i].seltimer)*8
|
||||
bcbox(x-9-b,y-9-b,x+9+b,y+9+b,string.format("#CC%02X%02X",c,c))
|
||||
if(spr[i].seltimer==23) then
|
||||
play_sfx(SFX_TARGET)
|
||||
end
|
||||
elseif(spr[i].seltimer>90 or AND(timer,7)>2) then
|
||||
bcbox(x-9,y-9,x+9,y+9,"red")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if(show_info and (spr[i].hover or spr[i].clicked or spr[i].seltimer)) then
|
||||
--bctext(AND(spr[i].x+255-scroll_x,255), spr[i].y, i);
|
||||
if(i==0) then
|
||||
bctext(x, y, "Blue Bomber")
|
||||
bctext(x, y+8, "("..spr[i].sx..","..spr[i].sy..")")
|
||||
bctext(x, y+16, "HP "..spr[i].hp)
|
||||
elseif(i>4) then
|
||||
if(sprdb[spr[i].id] and sprdb[spr[i].id].name --[[and i>4--]]) then
|
||||
bctext(x, y, sprdb[spr[i].id].name)
|
||||
else
|
||||
bctext(x, y, "("..spr[i].id..")")
|
||||
end
|
||||
bctext(x, y+8, "("..spr[i].sx..","..spr[i].sy..")")
|
||||
if(spr[i].hp~=0) then
|
||||
bctext(x, y+16, "HP "..spr[i].hp)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(show_cursor) then
|
||||
local col2
|
||||
if(inp.leftclick) then
|
||||
col2 = "#FFAA00"
|
||||
elseif(inp.rightclick) then
|
||||
col2 = "#0099EE"
|
||||
elseif(inp.middleclick) then
|
||||
col2 = "#AACC00"
|
||||
else
|
||||
col2 = "white"
|
||||
end
|
||||
drawcursor(inp.xmouse,inp.ymouse,"black",col2)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
initialize()
|
||||
|
||||
while(true) do
|
||||
update_vars()
|
||||
render()
|
||||
EMU.frameadvance()
|
||||
timer = timer + 1
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
-- Zapper Fun
|
||||
-- quick and dirty script that shows zapper position and fire button presses in FCEUX
|
||||
-- Written by miau
|
||||
-- http://morphcat.de/lua/
|
||||
|
||||
local Z_LSPAN = 20 --life span (in frames) of white box
|
||||
local Z_LSPAN_CLICK = 30 --life span of red box
|
||||
local Z_MAX = 60 --maximum amount of boxes on screen
|
||||
|
||||
local zbuf = {}
|
||||
local zindex = 1
|
||||
local timer = 0
|
||||
local lastclick = zapper.read().click
|
||||
local lastx = zapper.read().x
|
||||
local lasty = zapper.read().y
|
||||
|
||||
function zapper_addcoord(x,y,click)
|
||||
zbuf[zindex] = {t=timer,x=x,y=y,click=click}
|
||||
zindex = zindex + 1
|
||||
if(zindex>Z_MAX) then
|
||||
zindex = 1
|
||||
end
|
||||
end
|
||||
|
||||
function box(x1,y1,x2,y2,color1,color2)
|
||||
if(x1>=0 and y1>=0 and x2<=255 and y2<=255) then
|
||||
gui.drawbox(x1, y1, x2, y2, color1, color2)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
while(true) do
|
||||
local x = zapper.read().xmouse
|
||||
local y = zapper.read().ymouse
|
||||
local click = zapper.read().click
|
||||
--gui.text(0, 8, string.format("x=%d",x));
|
||||
--gui.text(0, 18, string.format("y=%d",y));
|
||||
--gui.text(0, 28, string.format("click=%d",click));
|
||||
if(click==1 and click~=lastclick) then
|
||||
zapper_addcoord(x,y,1)
|
||||
elseif(x~=lastx or y~=lasty) then
|
||||
zapper_addcoord(x,y,0)
|
||||
end
|
||||
lastclick=click
|
||||
lastx=x
|
||||
lasty=y
|
||||
box(x-3, y-3, x+3, y+3, "white", 0)
|
||||
|
||||
for i=1,Z_MAX do
|
||||
if(zbuf[i]) then
|
||||
ltime = timer-zbuf[i].t
|
||||
if(zbuf[i].click==0) then
|
||||
if(ltime<Z_LSPAN) then
|
||||
boxsize = (zbuf[i].t-timer+Z_LSPAN) / (Z_LSPAN/3)
|
||||
c = "white"
|
||||
box(zbuf[i].x-boxsize, zbuf[i].y-boxsize, zbuf[i].x+boxsize, zbuf[i].y+boxsize, c, 0)
|
||||
end
|
||||
elseif(zbuf[i].click==1) then
|
||||
if(ltime<Z_LSPAN_CLICK) then
|
||||
boxsize = (timer-zbuf[i].t) / (Z_LSPAN_CLICK/10)
|
||||
c = "red"
|
||||
box(zbuf[i].x-boxsize, zbuf[i].y-boxsize, zbuf[i].x+boxsize, zbuf[i].y+boxsize, c, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
FCEU.frameadvance()
|
||||
timer = timer + 1
|
||||
end
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
--Used for scripts written by Miau such as Gradius-BulletHell
|
||||
|
||||
--[[
|
||||
A Compilation of general-purpose functions.
|
||||
|
||||
-]]
|
||||
M_UTILS_VERSION = 0
|
||||
|
||||
--initialization
|
||||
if(FCEU) then
|
||||
EMU = FCEU
|
||||
elseif(snes9x) then
|
||||
EMU = snes9x
|
||||
elseif(gens) then
|
||||
EMU = gens
|
||||
end
|
||||
if(EMU == nil) then
|
||||
error("Unsupported environment. This script runs on Lua-capable emulators only - FCEUX, Snes9x or Gens.")
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--[[ m_require
|
||||
"require" with version checking
|
||||
|
||||
Similar to the approach in Xk's x_functions.lua, but supports loading and automatic version checking of
|
||||
"compatible" modules, too. A central version checking function does have its advantages.
|
||||
|
||||
A compatible module looks like this:
|
||||
if(REQUIRED_MODULE_VERSION==0) then --global variable = the second parameter of m_require
|
||||
error("This module isn't backwards compatible to version 0.")
|
||||
end
|
||||
module("modulename")
|
||||
MODULE_VERSION = 3
|
||||
function test()
|
||||
end
|
||||
return _M
|
||||
|
||||
using it in your code:
|
||||
m_require("modulefile.lua",3) --second parameter being > MODULE_VERSION would raise an error
|
||||
modulename.test()
|
||||
-]]
|
||||
function m_require(module,requiredver)
|
||||
if(module==nil or module=="m_utils") then
|
||||
if(M_UTILS_VERSION>=requiredver) then
|
||||
return true
|
||||
else
|
||||
error("\n\nThis script requires m_utils version "..requiredver..".\n"..
|
||||
"Your m_utils.lua is version "..M_UTILS_VERSION.."\n"..
|
||||
"Check http://morphcat.de/lua/ for a newer version.")
|
||||
end
|
||||
else
|
||||
--give the module the possibility to be backwards compatible
|
||||
--not very elegant, but there seems to be no other way using require
|
||||
REQUIRED_MODULE_VERSION = requiredver
|
||||
local ret = require(module)
|
||||
if(requiredver==nil) then --got no version checking to do
|
||||
return ret
|
||||
elseif(ret==nil or ret==false) then
|
||||
error("Could not load module "..module.." or module invalid.")
|
||||
elseif(type(ret)~="table") then
|
||||
error("Invalid module "..module..", doesn't return itself.")
|
||||
elseif(ret.MODULE_VERSION==nil) then
|
||||
error("Invalid module "..module..", missing version information.")
|
||||
elseif(ret.MODULE_VERSION < requiredver) then
|
||||
error("\n\nThis script requires "..module.." version "..requiredver..".\n"..
|
||||
"Your "..module.." module is version "..ret.MODULE_VERSION..".\n"..
|
||||
"If it's one of miau's Lua modules check\n"..
|
||||
"http://morphcat.de/lua/ for a newer version.\n")
|
||||
else
|
||||
return ret
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--drawing functions with bounds checking
|
||||
function bcbox(x1,y1,x2,y2,color1)
|
||||
if(x1>=0 and y1>=0 and x2<=255 and y2<=255) then
|
||||
gui.drawbox(x1, y1, x2, y2, color1, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function bcpixel(x,y,color)
|
||||
if(x>=0 and y>=0 and x<=255 and y<=255) then
|
||||
gui.drawpixel(x,y,color)
|
||||
end
|
||||
end
|
||||
|
||||
function bcline(x1,y1,x2,y2,color)
|
||||
if(x1>=0 and y1>=0 and x2<=255 and y2<=255
|
||||
and x2>=0 and y2>=0 and x1<=255 and y1<=255) then
|
||||
gui.drawline(x1, y1, x2, y2, color)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--bc + clipping, just make sure x2,y2 is the point that will most likely leave the screen first
|
||||
function bcline2(x1,y1,x2,y2,color)
|
||||
if(x1>=0 and y1>=0 and x1<=255 and y1<=255) then
|
||||
if(x2>255 or y2>255 or x2<0 or y2<0) then
|
||||
local vx,vy=getvdir(x1,y1,x2,y2)
|
||||
--TODO: replace brute force-y method with line intersection formula
|
||||
if(math.abs(vx)==1 or math.abs(vy)==1) then
|
||||
local x=x1
|
||||
local y=y1
|
||||
while(x<254 and x>1 and y<254 and y>1) do
|
||||
x = x + vx
|
||||
y = y + vy
|
||||
end
|
||||
x = math.floor(x)
|
||||
y = math.floor(y)
|
||||
--logf(" ("..x1..","..y1..")-("..x..","..y..")\r\n")
|
||||
gui.drawline(x1,y1,x,y,color)
|
||||
end
|
||||
else
|
||||
gui.drawline(x1,y1,x2,y2,color)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function bctext(x,y,text)
|
||||
if(x>=0 and y>=0 and x<=255 and y<=255) then
|
||||
--make sure the text is always visible or else... possible memory leaks(?) and crashes on FCEUX <= 2.0.3
|
||||
local len=string.len(text)*8+1
|
||||
if(x+len > 255) then
|
||||
x = 255-len
|
||||
end
|
||||
if(x < 0) then
|
||||
x = 0
|
||||
end
|
||||
|
||||
if(y > 222) then --NTSC
|
||||
y=222
|
||||
end
|
||||
gui.text(x, y, text)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function getdistance(x1,y1,x2,y2)
|
||||
return math.floor(math.sqrt((x1-x2)^2+(y1-y2)^2))
|
||||
end
|
||||
|
||||
--returns direction vector of a line
|
||||
function getvdir(srcx,srcy,destx,desty)
|
||||
local x1 = srcx
|
||||
local x2 = destx
|
||||
local y1 = srcy
|
||||
local y2 = desty
|
||||
local xc = x2-x1
|
||||
local yc = y2-y1
|
||||
if(math.abs(xc)>math.abs(yc)) then
|
||||
yc = yc/math.abs(xc)
|
||||
xc = xc/math.abs(xc)
|
||||
elseif(math.abs(yc)>math.abs(xc)) then
|
||||
xc = xc/math.abs(yc)
|
||||
yc = yc/math.abs(yc)
|
||||
else
|
||||
if(xc<0) then
|
||||
xc=-1
|
||||
elseif(xc>0) then
|
||||
xc=1
|
||||
else
|
||||
xc=0
|
||||
end
|
||||
if(yc<0) then
|
||||
yc=-1
|
||||
elseif(yc>0) then
|
||||
yc=1
|
||||
else
|
||||
yc=0
|
||||
end
|
||||
end
|
||||
|
||||
return xc,yc
|
||||
end
|
||||
|
||||
|
||||
local m_cursor = {
|
||||
{1,0,0,0,0,0,0,0},
|
||||
{1,1,0,0,0,0,0,0},
|
||||
{1,2,1,0,0,0,0,0},
|
||||
{1,2,2,1,0,0,0,0},
|
||||
{1,2,2,2,1,0,0,0},
|
||||
{1,2,2,2,2,1,0,0},
|
||||
{1,2,2,2,2,2,1,0},
|
||||
{1,2,1,1,1,1,1,1},
|
||||
{1,1,0,0,0,0,0,0},
|
||||
{1,0,0,0,0,0,0,0},
|
||||
}
|
||||
function drawcursor(px,py,col1,col2)
|
||||
if(px>0 and py>0 and px<256-8 and py<256-10) then
|
||||
for y=1,10 do
|
||||
if(m_cursor[y]) then
|
||||
for x=1,8 do
|
||||
if(m_cursor[y][x]==1) then
|
||||
gui.drawpixel(px+x,py+y,col1)
|
||||
elseif(m_cursor[y][x]==2) then
|
||||
gui.drawpixel(px+x,py+y,col2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--debug functions
|
||||
function logf(s)
|
||||
local fo = io.open("E:/emu/nes/fceux-2.0.4.win32-unofficial/lua/log.txt", "ab")
|
||||
if(fo~=nil) then
|
||||
fo:write(s)
|
||||
fo:close()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function logtable(a)
|
||||
for i,v in pairs(a) do
|
||||
if(type(v)=="table") then
|
||||
printarrrec(v)
|
||||
else
|
||||
if(v==false) then
|
||||
v="false"
|
||||
elseif(v==true) then
|
||||
v="true"
|
||||
end
|
||||
logf(i.." = "..v.."\r\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue