1 2
6 7 8
Experienced Forum User, Site Admin, Skilled player (1152)
Joined: 4/17/2010
Posts: 10779
Location: RU
Hey guys please look into that thread: "TASVideos Lua" project
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting. If TASing is meta-play, TASVideos Movie Rules are meta-meta-play!
Experienced Forum User
Joined: 2/19/2007
Posts: 424
Location: UK
I have ported my comparison script to super mario bros., and the result can be found here: http://folk.uio.no/sigurdkn/smbghost.zip It works the same way as the super mario world version: You first create a dump file for each TAS you want to compare with by using smbrecord.lua, which produces a file ghost.dump. Rename this file to something meaningful, and repeat for as many TASes you want. I included some example dumps in the zip file. Once you have the dump files, you can compare them with any TAS by using smbplayer.lua. It consists of a short configuration section at the top followed by lots of things you don't need to care about afterwards. Open up smbplayer.lua and edit the line with ghost_dumps = { ... } to indicate the dumps you want to use. Then just load the script in fceux together with the fm2 you want to play. There are some other options at the top of smbplayer.lua too, such as whether to show the status line, how to display the offsets, etc. These are also the same as in super mario world. The level transition detection could perhaps be improved a bit (the address changes at a different time than when one gains control, and there is a variable delay between these (perhaps due to the frame rule?)). Edit: Here is a video comparing the 5 most recent super mario bros any% tases: Link to video
Experienced Forum User, Site Admin, Skilled player (1152)
Joined: 4/17/2010
Posts: 10779
Location: RU
Can I detect the time the botton is held down? OS facilities maybe?
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting. If TASing is meta-play, TASVideos Movie Rules are meta-meta-play!
Active player, Experienced Forum User (259)
Joined: 4/15/2010
Posts: 197
Location: England
feos wrote:
Can I detect the time the botton is held down? OS facilities maybe?
Something like this? :)
Language: Lua

local frame_before = movie.framecount() local pad_counter = 0 gui.register(function() if movie.framecount ~= frame_before then if joypad.get(1).A then -- Or whatever button pad_counter = pad_counter + 1 else pad_counter = 0 end frame_before = movie.framecount() end gui.text(0, 0, pad_counter) end)
That counts how many frames you've pressed a button. Replace movie.framecount() with os.time() for real time difference. I only tested on snes9x. EDIT: I just realised I probably misinterpreted your post completely. It's past midnight for me. :(
Retired smw-96, smw any%
Active player, Experienced Forum User (484)
Joined: 11/2/2010
Posts: 359
I do not know if this is where this belongs but I figured why not. I have been trying to find inspiration for a new run and found the Famicom game Mini Putt [ROM name Mini Putt (J).nes] and wanted to see if I could get a perfect hole in one on each course. The first two courses were simple but from there it becomes slightly more complex. I figured I could try to find ways to do it but then figured that since there are only so many variables that can be controlled why do the work when I could get a machine to do it. The problem is I have no idea how to work lua and don't know where to start. So here is my question. Is there a way in lua to do a loop where you: 1) Go to the frame where the ball is actually shot (a pre-known number, frame 601 for the first hole) 2) Use the cheat function (or equivalent) to assign specific values from a vector into the ram address. In this case it would be the memory write for the power of the swing (0557), the x-position for the angle of the shot (0097 and 008B) and the y-position for the angle of the shot (0099 and 008C). 3) Frame advance through until a certain ram criteria is met (if 0031 is equal to 1), and then output whether or not a certain value met (if 008A is equal to 1 or not). Either advice or an example of a similar function would be extremely helpful because I am interested in this but have no idea where to begin. MATLAB is the only programming language I know currently (yay Mechanical Engineer education) so I wrote an example loop of what I would roughly like to be done with the bot seen here. The values in the matrices are dummy values as the real vectors would be much larger and would simply clutter the code.
Experienced Forum User
Joined: 5/24/2004
Posts: 262
I've decided that megaman is too easy:
Language: lua

started = 0; while (true) do health = memory.readbyte(0x006A); gui.text(2, 10, "Hardcore mode"); if health == 28 then started = 1; end; if started == 1 and health < 28 then FCEU.softreset(); started = 0; end; FCEU.frameadvance(); end;
Experienced Forum User, Site Admin, Skilled player (1152)
Joined: 4/17/2010
Posts: 10779
Location: RU
I wrote a function converting 1-byte number to 8-bit binary view (the number is still DEC though, it's just to observe bits). I know there are some custom libraries for bitwise operations, but since emulua has them internally, I don't think our people use those libs. And that's an addition. I'd be glad to see that implemented in emulua internally too! EDIT: supports zero Num now.
Language: lua

function ToBin8(Num,Switch) -- 1 byte to binary converter by feos, 2012 -- Switch: "s" for string, "n" for number if Num > 0 then Bin = "" while Num > 0 do Bin = (Num % 2)..Bin Num = math.floor(Num / 2) end Low = string.format("%04d",(Bin % 10000)) High = string.format("%04d",math.floor(Bin / 10000)) if Switch == "s" then return High.." "..Low elseif Switch == "n" then return Bin else return "Wrong Switch parameter!\nUse \"s\" or \"n\"." end else if Switch == "s" then return "0000 0000" elseif Switch == "n" then return 0 else return "Wrong Switch parameter!\nUse \"s\" or \"n\"." end end end
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting. If TASing is meta-play, TASVideos Movie Rules are meta-meta-play!
Experienced Forum User, Skilled player (1829)
Joined: 4/20/2005
Posts: 2160
Location: Norrköping, Sweden
I'm having some problems loading a savestate using Lua in BizHawk. I have a script that looks like this:
statename="lagpause.State"

savestate.save(statename)
savestate.load(statename)
The savestate.save works, but savestate.load returns the error "LuaInterface.LuaScriptException: cannot resume non-suspended coroutine". Anyone know what I'm doing wrong?
Emulator Coder, Experienced Forum User
Joined: 8/12/2008
Posts: 42
Andypro wrote:
I've decided that megaman is too easy:
Language: lua

started = 0; while (true) do health = memory.readbyte(0x006A); gui.text(2, 10, "Hardcore mode"); if health == 28 then started = 1; end; if started == 1 and health < 28 then FCEU.softreset(); started = 0; end; FCEU.frameadvance(); end;
This is fscking badass.
** FceuX SDL Developer/Maintainer ** get the latest source http://sourceforge.net/p/fceultra/code/
Post subject: Huh, another lua script from me. What are the odds?
Editor, Experienced Forum User, Skilled player (1105)
Joined: 9/27/2008
Posts: 1078
I didn't like the superimpose option in TAS Editor, so I made my own script to fix things. Enjoy having complete keyboard control that allows you to toggle input on or off. EDIT: Seems to interfere with a few things, such as marker naming. Trying a fix... Download TASEditor_XOR_mix.lua
Language: lua

--[[ Leeland Kirwan (FatRatKnight), 2013 Allows user input to "mix" with TAS Editor using XOR logic. If Recording is checked, this script will do its intended job. Tap a P1 key to toggle input. If "All" is selected, will use other player keys for related player. If an individual player is selected, uses P1 controls. You can hold down a key to affect multiple frames, toggling the key on each frame. For reference, Superimpose uses OR logic, and does not allow user input to clear stored input. A great inconvience for those wishing to use the keyboard to toggle individual input rather than mouse. ]]-- local z= "none" local btnval= {A = 0x01, B = 0x02, select= 0x04, start= 0x08, up= 0x10, down= 0x20, left = 0x40, right= 0x80} local plval= {["1P"]= 1, ["2P"]= 2, ["3P"]= 3, ["4P"]= 4} local OldJoy= {{},{},{},{}} --***************************************************************************** local function InputToggle() --***************************************************************************** --Needs readonly mode to work, but won't interfere too much otherwise. --Toggles inputs recorded in TAS Editor. if not taseditor.engaged() then return end -- Escape local frame= emu.framecount() local plSel= plval[taseditor.getrecordermode()] local plLow = plSel or 1 -- Get the for loop range! local plHigh= plSel or 4 -- Hardcoded 4 doesn't appear harmful... local P1joy= nil -- If one player, get P1. if plSel then P1joy= joypad.getimmediate(1) end -- Otherwise, get all. local changed= false -- Flag, so I don't interfere too much for pl= plLow, plHigh do local pad= taseditor.getinput(frame,pl) local joy= P1joy or joypad.getimmediate(pl) -- Pick out the joypad local mask= 0 -- Convert messy table to numbers for btn,pressed in pairs(joy) do if pressed and not OldJoy[pl][btn] then mask= bit.bor(mask,btnval[btn]) end end taseditor.submitinputchange(frame,pl,bit.bxor(pad,mask)) OldJoy[pl]= joy -- To avoid repeated triggers changed= changed or (mask ~= 0) -- If the bitmask did something, apply! end if changed then taseditor.applyinputchanges() end end taseditor.registerauto(InputToggle) --***************************************************************************** while true do --***************************************************************************** -- Exists to detect frame advances, and thus clear the OldJoy array. for i= 1, 4 do OldJoy[i]= {} end -- Retrigger keys emu.frameadvance() end
Experienced Forum User, Site Admin, Skilled player (1152)
Joined: 4/17/2010
Posts: 10779
Location: RU
FCEUX now finally has readword, best for 2-byte positions, even if bytes are not near each other.
memory.readword(int addressLow, [int addressHigh])
memory.readwordunsigned(int addressLow, [int addressHigh])
Get an unsigned word from the RAM at the given address. Returns a 16-bit value regardless of emulator. The value will always be positive. If you only provide a single parameter (addressLow), the function treats it as address of little-endian word. if you provide two parameters, the function reads the low byte from addressLow and the high byte from addressHigh, so you can use it in games which like to store their variables in separate form (a lot of NES games do).
memory.readwordsigned(int addressLow, [int addressHigh])
The same as above, except the returned value is signed, i.e. its most significant bit will serve as the sign.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting. If TASing is meta-play, TASVideos Movie Rules are meta-meta-play!
Editor, Experienced Forum User, Skilled player (1829)
Joined: 6/15/2005
Posts: 3185
feos wrote:
Get an unsigned word from the RAM at the given address. Returns a 16-bit value regardless of emulator. The value will always be positive.
Could the value be zero?
Experienced Forum User, Site Admin, Skilled player (1152)
Joined: 4/17/2010
Posts: 10779
Location: RU
I assure you it won't be -0.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting. If TASing is meta-play, TASVideos Movie Rules are meta-meta-play!
Experienced Forum User
Joined: 10/23/2009
Posts: 544
Location: Where?
qFox wrote:
Here's a super mario jump script: v1: http://lua.pastey.net/92550 v2: http://lua.pastey.net/92579 (improved landing detection and positioning of results) screenshot: The prediction wraps around (that's why you see a few dots on the left). Make sure you have started the game (so press start at the title screen!) because otherwise you'll see crap.(
Hello, I'm currently looking to do something on a NES game and VBA that looks almost exactly like this, but it's for a ball of a sport game... Does someone have this lua so I can study it and implement to my scripts, or provide me with an another script that does the same thing than this? I need also to know what I'll need in order to do this feature(Adresses) Thank you.
Experienced Forum User
Joined: 10/23/2009
Posts: 544
Location: Where?
I'm encounting a problem with my gui.ine(thingy) thingy: What I see on the screen is the hitbox of the ball(That I drew with 4 gui.line)... of the next frame. So I see where the ball will be on the camera on the next screen. I need first to be able to see where the ball in the screen I'm seeing, not in the next frame... I tried with gui.register, the problem still occurs. I've tried with emu.registerbefore... I don't know why the script itself won't work. Any help is greatly appreciated.
Experienced Forum User, Site Admin, Skilled player (1152)
Joined: 4/17/2010
Posts: 10779
Location: RU
Sounds like you need a 1 frame delay from real memory state. Try this:
Language: lua

while (true) do -- your gui.line and stuff here FCEU.frameadvance() end
Without registering anything.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting. If TASing is meta-play, TASVideos Movie Rules are meta-meta-play!
Experienced Forum User
Joined: 10/23/2009
Posts: 544
Location: Where?
feos wrote:
Sounds like you need a 1 frame delay from real memory state. Try this:
Language: lua

while (true) do -- your gui.line and stuff here FCEU.frameadvance() end
Without registering anything.
My script now looks like this:
Language: lua

function 1()--Function to put textes on screen function 2()--Function to draw hit boxes function 3()Function to draw boxes again function 4()FUnction to draw a line while true do --My functions are called here, nothing more FCEU.frameadvance() end
But it still one frame early. Nothing changed I've tried with emu.frameadvance() too, but no change... Between, what is the difference between emu.frameadvance() and FCEU.frameaadvance() ?
Editor, Experienced Forum User, Skilled player (1105)
Joined: 9/27/2008
Posts: 1078
I prefer gui.register for a lot of things.
Language: lua

local function Fn() gui.text(12,12,"Hello world") end gui.register(Fn)
Another way you can try it is:
Language: lua

gui.register(function() gui.text(14,14,"Hello again, world") end)
These code blocks should run just fine as is. Something you're probably not used to is the fact I'm not using in those code blocks at all are the while true do [...] emu.frameadvance() end loop that you're used to. It doesn't even exist in the code blocks above. Since the while true loop doesn't exist, the script doesn't get locked somewhere in a loop. It falls through, hits the end of the script, and finishes safely without a crash. Except for one thing: It registered a function for FCEUX to run whenever it updates the display. That function will be called repeatedly for you, no need to worry. That should take care of your "one frame late" problem, since the function is called when FCEUX want to update the display, instead of some odd emulation timing involving emu.frameadvance(). EDIT: Oh, your lua display was a frame early? Well then...
Language: lua

local OldValue= 0 while true do gui.text(12,12,OldValue) -- This displays what the value was a frame ago. OldValue= memory.readbyte(0x0000) -- Because it's updated after I show the text. emu.frameadvance() end
Slightly complicates things when you're adding an intentional delay.
Experienced Forum User
Joined: 10/23/2009
Posts: 544
Location: Where?
I think I've realized something important: I've enabled the auto skip lag frames, so I were skipping a frame since the games lags every 2 frames(30 FPS?) I think I need one other delay. Do I simply put a emu.frameadvance() before the one already present? EDIT: I've tried the difference with skip lag off: doing your thing improve the position of the boxes. I need one more delay and it should be perfect. I'll try adding a new emu.frameadvance nowé. EDIT: It's works better with skipping lag frames since during lag frames there is some important address that goes crazy. :P But I still think I need one more frame delay.
Editor, Experienced Forum User, Skilled player (1105)
Joined: 9/27/2008
Posts: 1078
Adding one frame of delay is simple enough. Adding two frames or more usually requires a table and functions specifically built for it. An extremely messy way to add two frames of delay would be the following:
Language: lua

local OldVal_TwoFramesAgo= 0 local OldVal_OneFrameAgo= 0 while true do gui.text(15,15,OldVal_TwoFramesAgo) OldVal_TwoFramesAgo= OldVal_OneFrameAgo OldVal_OneFrameAgo= memory.readbyte(0x0000) emu.frameadvance() end
The extremely messy way requires five lines every time you want to grab just one more value. It's extremely messy. Also, loadstates will show you stuff from before the load until enough frames pass. Less messy sorts of ways would require making a few functions specifically to handle these things for you:
Language: lua

local ReadTheseAddresses= {0x0000,0x0005,0x0103,0x0244} -- and so on local MemoryHistory= {} local function StoreStuff() local fc= emu.framecount() MemoryHistory[fc]= {} for i= 1, #ReadTheseAddresses do local addr= ReadTheseAddresses[i] MemoryHistory[fc][addr]= memory.readbyte(addr) end end local function ReadOldByte(address,FramesInPast) local t= MemoryHistory[emu.framecount() - FramesInPast] if t then return t[address] end end while true do StoreStuff() gui.text(15,15,ReadOldByte(0x0000,2) or "nil") emu.frameadvance() end
But at least you'll have a complete history of select memory addresses. If the value hasn't been read up by the lua script, ReadOldByte should return nil, which needs to be checked for to avoid other errors. Also, it's just one more line to add for each address you want to check, as well as a quick addition to a list, rather than five (or more) lines per address you want to look at. These are actually more general techniques than anything specific for emulation. It's less to do with the functions handed to you by FCEUX or other emulators and more to do with knowing what you can do in lua. It takes a lot of practice understanding lua as a whole before you can come up with an arbitrary way of delaying the display as infinitely as you like. Then again, knowing what functions are available takes a bit of memorization as well. I've used emu.framecount and memory.readbyte here. In any case, if you can read and understand the code here, especially with my lack of comments in there, that might help give some idea what lua can do. And you'll also know what to change in my sample code to get any amount of delay you like. For TASing, you usually want the most up-to-date internal stuff displayed, even if it's wildly out of sync with the game's display. If you plan to make a few videos, syncing up the lua with the game's display does have advantages, though.
Experienced Forum User
Joined: 10/23/2009
Posts: 544
Location: Where?
Alright, I'll try when I'll have time.
Experienced Forum User
Joined: 10/23/2009
Posts: 544
Location: Where?
Alright, it's me again, I wrote a new script for a another purpose just for fun, and I stumbled on something. I can't seem to be able to make "ballXc" a real value(and not a nil value). Same goes with p3Xc and p4Xc... Also, there is something wrong with the color for the first function... I don't know why. I'm puzzled since I've checked like 10 times and I couldn't tell what is wrong... If you're not in the mood to help, that's okay! ^^ I wrote this since I think I made a stupid mistake that shouldn't take a lot of time for you to debug it. Here is the script:
Language: lua

function pixel(x,xc,y,yc,color) gui.pixel(xc+x,yc-y,color) end function correction(screen,x,name) if screen == 0 then name = x end if screen == 1 then name = x + 255 end end while true do --Player 1: --Coordinates: p1X = memory.readbyte(0x00A6) p1Y = memory.readbyte(0x00D0) p1Z = memory.readbyte(0x00BB) --Others things: p1m = memory.readbyte(0x0447)--Power meter --Player 2: --Coordinates: p2X = memory.readbyte(0x00A5) p2Y = memory.readbyte(0x00CF) p2Z = memory.readbyte(0x00BA) --Others things: --p2m = memory.readbyte(0x0447) --Player 3: --Coordinates: p3X = memory.readbyte(0x00A7) correction(p3s,p3X,p3Xc) p3Y = memory.readbyte(0x00D1) p3Z = memory.readbyte(0x00BC) --Others things: p3m = memory.readbyte(0x0449) p3s = memory.readbyte(0x00AE)--Screen location (0 = Left, 1 = right(+255)) --Player 4: --Coordinates: p4X = memory.readbyte(0x00A8) correction(p4s,p4X,p4Xc) p4Y = memory.readbyte(0x00D2) p4Z = memory.readbyte(0x00BD) --Others things: p4m = memory.readbyte(0x044A) p4s = memory.readbyte(0x00AF) --Ball --Coordinates ballX = memory.readbyte(0x00A9) correction(balls,ballX,ballXc) ballY = memory.readbyte(0x00D3) ballZ = memory.readbyte(0x00BE) --Others: balls = memory.readbyte(0x00B0) ---------------------------------------------------------------------------------- gui.drawbox(110,160,255,246)--The box where the field will be. --The field: --X1___________X2 <--------------- Y1 --| | --X3___________X4 <--------------- Y2 --Notes: --Net height: 59 --Net X: 188 --Up:119 (Y1) --Down:28 (Y2) --Up right: 75+255 (X2) --Down Right: 98+255 (X4) --Up Left: 69(X1) --Down Left: 46 (X2) X1 = 110 + 34.5/1.3 X2 = 110 + 165/1.3 X3 = 110 + 23/1.3 X4 = 110 + 176.5/1.3 Y1 = 130 + 59.5/1.3 Y2 = 130 + 105/1.3 N1 = 110 + 104.5/1.3 gui.line(X1,Y1,X2,Y1,"purple") gui.line(X1,Y1,X3,Y2,"purple") gui.line(X2,Y1,X4,Y2,"purple") gui.line(X3,Y2,X4,Y2,"purple") --Net: gui.line(N1,Y1,N1,Y2, "Black") ----------------------------------------------------------------------------- --Second Radar gui.drawbox(0,160,110,246) --Radar for Z position gui.line(10,174.5,10,220,"black")--Vertical line #1 gui.line(10,174.5,15,174.5,"black")--Up horizontal line gui.line(10,220,15,220,"black")--Down horizontal line --Ball gui.pixel(15,234-ballZ/2,"blue") --Radar for Y & X position gui.line(30,220,95.25,220,"black")--Horizontal line gui.line(65,220,65,205.25,"black")--Net --Ball pixel(ballXc/4,12.75,ballY/4,220,blue) --Players pixel(p1X/4,12.75,p1Y/4,220,red) pixel(p2X/4,12.75,p2Y/4,220,red) pixel(p3Xc/4,12.75,p3Y/4,220,red) pixel(p4Xc/4,12.75,p4Y/4,220,red) emu.frameadvance() end
Here is the same code, but written with no function. That one does what I want it to do. I felt there were a lot of repetition, so I made functions in order to reduce lines...
Language: lua

--Notes: --Net height: 59 --Net X: 188 --Up:119 --Down:28 --Up right: 75+255 --Down Right: 98+255 --Up Left: 69 --Down Left: 46 while true do gui.drawbox(110,160,255,246)--The box where the field will be. --The field: --X1___________X2 <--------------- Y1 --| | --X3___________X4 <--------------- Y2 X1 = 110 + 34.5/1.3 X2 = 110 + 165/1.3 X3 = 110 + 23/1.3 X4 = 110 + 176.5/1.3 Y1 = 130 + 59.5/1.3 Y2 = 130 + 105/1.3 N1 = 110 + 104.5/1.3 gui.line(X1,Y1,X2,Y1,"purple") gui.line(X1,Y1,X3,Y2,"purple") gui.line(X2,Y1,X4,Y2,"purple") gui.line(X3,Y2,X4,Y2,"purple") --Net: gui.line(N1,Y1,N1,Y2, "Black") --Second Radar -- gui.drawbox(0,160,110,246) --Radar for Z position -- gui.line(10,174.5,10,220,"black")--Vertical line #1 -- gui.line(10,174.5,15,174.5,"black")--Up horizontal line --gui.line(10,220,15,220,"black")--Down horizontal line --Ball --BallZ = memory.readbyte(0x00BE)/2 --gui.pixel(15,234-BallZ,"blue") --Radar for Y & X position gui.line(30,220,95.25,220,"black")--Horizontal line gui.line(65,220,65,205.25,"black")--Net --Ball --Y BallY = memory.readbyte(0x00D3)/4 --X if memory.readbyte(0x00B0) == 0 then BallX = memory.readbyte(0x00A9)/4 end if memory.readbyte(0x00B0) == 1 then BallX = memory.readbyte(0x00A9)/4 + 255/4 end gui.pixel(12.75+BallX,220-BallY,"blue") ---------------- --Players --1 --Y p1Y = memory.readbyte(0x00D0)/4 --X p1X = memory.readbyte(0x00A6)/4 gui.line(p1X+12.75,220-p1Y,p1X+12.75,212-p1Y,"red") --2 --Y p2Y = memory.readbyte(0x00CF)/4 --X p2X = memory.readbyte(0x00A5)/4 gui.line(p2X+12.75,220-p2Y,p2X+12.75,212-p2Y,"red") --3 --X if memory.readbyte(0x00AE) == 0 then p3X = memory.readbyte(0x00A7)/4 end if memory.readbyte(0x00AE) == 1 then p3X = memory.readbyte(0x00A7)/4 + 255/4 end --Y p3Y = memory.readbyte(0x00D1)/4 gui.line(p3X+12.75,220-p3Y,p3X+12.75,212-p3Y,"red") --4 --X if memory.readbyte(0x00AF) == 0 then p4X = memory.readbyte(0x00A8)/4 end if memory.readbyte(0x00AF) == 1 then p4X = memory.readbyte(0x00A8)/4 + 255/4 end --Y p4Y = memory.readbyte(0x00D2)/4 gui.line(p4X+12.75,220-p4Y,p4X+12.75,212-p4Y,"red") emu.frameadvance() end
Those two codes should do the same thing... Does someone knows why?
Editor, Experienced Forum User, Skilled player (1105)
Joined: 9/27/2008
Posts: 1078
Language: lua

function correction(screen,x,name) if screen == 0 then name = x end if screen == 1 then name = x + 255 end end
The function modifies name, but name is merely a copy of whatever was passed to the function, and not the same variable from whoever called this function. Once this function implicitly returns, this copy is discarded, and there is no change to whoever passed name to the function. Let's see this snippet...
Language: lua

--Player 3: --Coordinates: p3X = memory.readbyte(0x00A7) correction(p3s,p3X,p3Xc) p3Y = memory.readbyte(0x00D1) p3Z = memory.readbyte(0x00BC)
Perhaps we should try this?
Language: lua

function correction(screen,x) if screen == 0 then return x end if screen == 1 then return x + 255 end end --Elsewhere... Just pretend I copied everything else here. --Player 3: --Coordinates: p3X = memory.readbyte(0x00A7) p3Xc= correction(p3s,p3X) p3Y = memory.readbyte(0x00D1) p3Z = memory.readbyte(0x00BC)
Basically, have the function return something, rather than trying to modify a value passed to it, as a modified value will never be seen by something calling the function. I suppose you could use tables, but that's a whole other mess to get into. The function call, once it finishes, essentially becomes whatever it returns, rather than a function object. Obviously, you're getting a number from memory-readbyte calls rather than the function itself, similar thing here when you use a return statement (or nil, if returning nothing or never using a return statement). This may be a late response, but hopefully this quick glance over your code is enough to answer your question. ... On a side note, it was confusing with the leading whitespace with your function statements. With the end statement that signifies the end of the function, I recommend having zero leading whitespaces, as you're now back at the top level, so to speak. Between that end statement for your first function and the start of the second function, you're not "inside" anything, so there's no need for leading whitespace.
Experienced Forum User, Player (155)
Joined: 7/1/2016
Posts: 263
Can somebody help me with lua script for metroid. I'm trying to show enemy information on top of the enemies. Something like this: I found that enemies coordinates are in addresses 0400 / 0401; 0410 / 0411.. etc But those coordinates not on screen coordinates. It's like "room coordinates". So then i try to fix them. I start with x position. I found that 0050 it's like "in what room you now X coordinate". And 00FD it's like how camera shifted in that room. Ok. But i can't find how game know in what room enemies are. Can somebody help me with this? Like how to find enemy coordinates on screen. I'm pretty stupid
Experienced Forum User, Site Admin, Skilled player (1152)
Joined: 4/17/2010
Posts: 10779
Location: RU
Does this give any insight? http://datacrystal.romhacking.net/wiki/Metroid:RAM_map http://tasvideos.org/ReverseEngineering.html#Objects From how it sounds, you just need camera position and to subtract it from enemy positions.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting. If TASing is meta-play, TASVideos Movie Rules are meta-meta-play!
1 2
6 7 8