1 2
6 7 8
13 14
Editor, Expert player (2080)
Joined: 6/15/2005
Posts: 3284
jlun2 wrote:
feos wrote:
The refresh button?
I tried. If I get an error during a refresh, the button doesn't seem to work even after I fix the script. It won't give additional errors however.
Error means that the script is deactivated; clicking the refresh button does nothing and you will need to double-click on the script to reactivate it. Personally, I'd just twice double-click the script (once to deactivate, once to reactivate) to refresh it. Sure, four clicks takes longer than one, but it's like only a half-second longer, and, if you do the refresh-button method, then when you do forget that you can't click the refresh button after an error while testing your script (and you will), each time that it happens costs precious seconds of your time.
Pokota
He/Him
Joined: 2/5/2014
Posts: 779
Desmume lua adventure! Currently trying to put together a script that iteratively taps coordinates on the touch screen (to be tweaked/used with Ace Attorney fingerprinting segments), though with how poorly Desmulua is documented I'm not sure I'm doing it right. According to what my debug line is reporting it's iterating perfectly fine, however I'm not seeing the ui respond with the coordinate press. Neither stylus.set nor stylus.write seem to be working (tested with both 0.9.9 and 0.9.11, neither one is working as expected so I do need another set of eyes here). E: Fixed thanks to zeromus
Language: lua

max_x = 255 max_y = 192 function stylusWriteLoop() for j=0,max_y,5 do for i=0,max_x,5 do pass = {x=i,y=j,touch=1} stylus.set(pass) emu.frameadvance() stylus.write(pass) emu.frameadvance() debuf = i .. "," .. j print(debuf) emu.frameadvance() end end end function main() stylusWriteLoop() return end main()
Adventures in Lua When did I get a vest?
Editor, Emulator Coder
Joined: 8/7/2008
Posts: 1156
"These keys are used with functions beginning with stylus. The key 'x' is an integer from 0 to 255, 'y' is an integer from 0 to 192, and 'touch' is a boolean.". This was well documented. Your code does not contain keys. It contains a table with 3 unnamed values (an array, actually, I think) pass = {x=i,y=j,touch=true}
Pokota
He/Him
Joined: 2/5/2014
Posts: 779
Stylus.set throws an error if I don't pass an array (and the error, for whatever reason, shows up under emu.frameadvance). It sounds/looks like I made the false assumption that the function would automagically read them like arguments (why is this passed as a keyed table rather than as separate arguments?) Keying the values fixed it, thanks. When I read the documentation, I read "keys" and thought "keys on a keyboard" rather than "keys for table indexing." That's what I get for not paying attention to the page title.
Adventures in Lua When did I get a vest?
Editor, Emulator Coder
Joined: 8/7/2008
Posts: 1156
no, Stylus.set throws an error if you pass individual arguments. You keyed the values: you passed a table. Passing an array is nonfunctional. As to why it is passed as a table, I'm not sure, but maybe its for orthogonality with the button setting apis
Pokota
He/Him
Joined: 2/5/2014
Posts: 779
That does make sense from a consistency point of view. With that said, there are two different functions, stylus.set and stylus.write. Both take a table as an argument. There doesn't seem to be much of a difference between the two in execution. Is there a difference I'm not seeing between the two?
Adventures in Lua When did I get a vest?
Editor, Emulator Coder
Joined: 8/7/2008
Posts: 1156
there is no difference
Skilled player (1743)
Joined: 9/17/2009
Posts: 4986
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
How do I print out the lua table from "input.get()" to console? I tried:
Language: lua

local inputs = input.get() if (input.get() ~= nil) then console.log(inputs) end
and it gave the error:
LuaInterface.LuaScriptException: [string "main"]:32: attempt to call field 'get' (a nil value)
Attempting to simply use
Language: lua

console.log(input.get())
gave the error:
"WMouse L": "True"

LuaInterface.LuaScriptException: [string "main"]:33: attempt to call field 'get' (a nil value)
Using an if statement to test for nil makes it give the error, and it doesn't even show the mouse.
Pokota
He/Him
Joined: 2/5/2014
Posts: 779
Which core? Regarding printing out the input table, since you're assigning inputs you'll want to manipulate your inputs table directly instead of comparing against input.get().
Language: lua

local inputs = input.get() if (inputs ~= nil) then console.log(inputs) end
Adventures in Lua When did I get a vest?
Skilled player (1743)
Joined: 9/17/2009
Posts: 4986
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
Pokota wrote:
Which core? Regarding printing out the input table, since you're assigning inputs you'll want to manipulate your inputs table directly instead of comparing against input.get().
Language: lua

local inputs = input.get() if (inputs ~= nil) then console.log(inputs) end
I tried your suggestion, and it gave me:
"WMouse L": "True"

LuaInterface.LuaScriptException: [string "main"]:31: attempt to call field 'get' (a nil value)
Does it work for you? Edit: Placing local inputs = input.get() outside the loop works, but then the variable "inputs" never gets updated later, so it just shows as "WMouse L": "True" over and over instead.
Editor, Emulator Coder
Joined: 8/7/2008
Posts: 1156
so stop assigning another table to the variable 'input' at some other point in your script we can't see
Skilled player (1743)
Joined: 9/17/2009
Posts: 4986
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
^ Thanks! I reduced the code to
Language: lua

while true do local is = input.get() if (is ~= nil) then console.log(is) end emu.frameadvance() end
and it finally works. Very sorry about that.
Post subject: Newbie question about lua.
Joined: 10/23/2009
Posts: 545
Location: Where?
Getting back to lua.. Need to be reminded of something. I'm not sure where my error is for this.
Language: lua

local function position(XY,A,B,C,x,y) --XY: X or Y? + Who? --A: Sprite position mainmemory.readbyte(A) --B: Map position mainmemory.readbyte(B) --C:Map increments mainmemory.readbyte(C) --D:Final position D = A+B+C gui.drawText(x,y,"XY"D) end while true do position(X:,0003,015A,01F2,50,50) emu.frameadvance.() end
Where is my newbie mistake? I have a hard time seeing it, but I believe it's the "XY". Maybe I need to add also 0X before my addresses? What do I have to do if it's 2 bytes instead of one byte? I don't know by looking at the lua functions list.
Editor, Skilled player (1537)
Joined: 7/9/2010
Posts: 1319
niamek wrote:
Getting back to lua.. Need to be reminded of something. I'm not sure where my error is for this. Where is my newbie mistake? I have a hard time seeing it, but I believe it's the "XY".
Maybe you wanted something like this:
Language: lua

local function position(XPosA, YPosA, XPos2A, YPos2A) --A: Sprite position low byte XPos = memory.readbyte(XPosA) YPos = memory.readbyte(YPosA) --B: Sprite pos high byte XPos2 = memory.readbyte(XPosA) YPos2 = memory.readbyte(YPosA) --D:Final position X = XPos + XPos2*256 Y = YPos + YPos2*256 gui.drawText(x-xcam ,y-ycam,"X:"..X.."\n".."Y:"..Y) end end
You gave the ram addresses to D, not the values, and you need to assigne the value from readbyte to a variable. Also give your variables meaningful names. I don't know what it's supposed to do or what your Map positions are, I guessed that they're position and cam related. When you want to make that the drawed text follows the sprite, you need to subtract camera position from object position. And when you want to combine X and Y into one variable you need a table.
Favorite animal: STOCK Gt(ROSA)26Sortm1.1(rtTA,EGFP)Nagy Grm7Tg(SMN2)89Ahmb Smn1tm1Msd Tg(SMN2*delta7)4299Ahmb Tg(tetO-SMN2,-luc)#aAhmb/J YouTube Twitch
Pokota
He/Him
Joined: 2/5/2014
Posts: 779
Language: lua

local function position(XY,A,B,C,x,y) --XY: X or Y? + Who? --A: Sprite position mainmemory.readbyte(A) --B: Map position mainmemory.readbyte(B) --C:Map increments mainmemory.readbyte(C) --D:Final position D = A+B+C gui.drawText(x,y,"XY"D) end while true do position(X:,0003,015A,01F2,50,50) emu.frameadvance.() end
Let's go through this one line at a time, maybe that'll help (since I don't know the context in which this is being used)
Language: lua

local function position(XY,A,B,C,x,y) -- Defining the function to use variables XY, A, B, C, x, and y. No real issues here yet. -- XY = X:, A = 3, B = 345, C = 498 --XY: X or Y? + Who? --A: Sprite position mainmemory.readbyte(A) -- You read from this address but don't do anything with it. --B: Map position mainmemory.readbyte(B) -- You read from this address but don't do anything with it. --C:Map increments mainmemory.readbyte(C) -- You read from this address but don't do anything with it. --D:Final position D = A+B+C -- This is adding the A, B, and C you passed originally as opposed to adding their ram values as you intended. gui.drawText(x,y,"XY"D) -- Concatenation in lua uses the .. operator, so this should throw an error as written. end while true do position(X:,0003,015A,01F2,50,50) -- Remember to declare hex values with the 0x prefix to prevent confusion emu.frameadvance.() -- one too many dots. end
I would also suggest renaming your variables to be more descriptive of what they hold.
Adventures in Lua When did I get a vest?
Joined: 10/23/2009
Posts: 545
Location: Where?
Language: lua

if mainmemory.readbyte(0x0022) == 0 then correctionx = 0 correctiony = -100 mainmemory.readbyte(0x0022) == 1 then correctionx = 70 correctiony = 70 [...] end
So in that portion of my code, apparently there is no unexpected symbol on the 2nd line, but there is one on the 5th line. So I'm really confused. To me there aren't nothing wrong. I tried removing one of the two =, but now it throws me that it expected a "then" near a "=", which is already right after... I need to make differents corrections according to one value. I listed two of them. All the others are made the same way. I'll do maths with correctionx and correctiony.
Skilled player (1743)
Joined: 9/17/2009
Posts: 4986
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
niamek wrote:
So in that portion of my code, apparently there is no unexpected symbol on the 2nd line, but there is one on the 5th line. So I'm really confused. To me there aren't nothing wrong. I tried removing one of the two =, but now it throws me that it expected a "then" near a "=", which is already right after... I need to make differents corrections according to one value. I listed two of them. All the others are made the same way. I'll do maths with correctionx and correctiony.
You need an "elseif" for the second then.
Joined: 10/23/2009
Posts: 545
Location: Where?
That worked! Thanks! But now I have an another trouble. I've used
Language: lua

client.SetGameExtraPadding(0,0,100,0)
so I can put some value on the side of the game screen. But I noticed that with that I'm missing a portion of the screen on the left! So I've looked at the lua function list, and found client.SetClientExtraPadding. I've tried this one too, it looks better, but I can't display other gui.pixeltext on that new space as opposed to the one I had. I've tried this just for fun:
Language: lua

client.SetGameExtraPadding(100,0,100,0)
Now the game itself is stretched. So I was wondering, why does the video is modified when I use that function? According to the description of the function, it shouldn't be touched. Am I missing something? Sorry with all those lua questions.
Skilled player (1743)
Joined: 9/17/2009
Posts: 4986
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
Add gui.DrawNew("native") to draw on the black space outside the game. To draw back on the game space, use gui.DrawNew("emu") which is also default.
Joined: 10/23/2009
Posts: 545
Location: Where?
jlun2 wrote:
Add gui.DrawNew("native") to draw on the black space outside the game. To draw back on the game space, use gui.DrawNew("emu") which is also default.
Hello jlun2, I'm not sure how to use that function. Could you provide me an example? I'm also not sure why a gui function would fix a video problem.
Pokota
He/Him
Joined: 2/5/2014
Posts: 779
CrazyTerabyte wrote:
Pokota wrote:
I'm looking at the lua functions, and there's gui.DrawNew(string name). What sort of shenanigans can I do with this?
It calls "LockLuaSurface()", which is defined at "BizHawk.Client.EmuHawk\DisplayManager\DisplayManager.cs". There are only two available surfaces: "emu" and "native". I've toyed with it only once. Let me try to explain... Suppose you emulating a GameBoy game. Since the 160x144 is very small, you configure the emulator to 3x zoom. Then, for all Lua gui functions, the coordinate system is the emulator one, which is just 160x144. However, if you call DrawNew("native"), all gui functions will now use the native coordinate system, which will be 480x432 (= 160x144 times 3). As I said, I only tried it once, discovered what happened, and never tried again. I don't even know what side-effects it has. I guess one small "issue" to be aware is that the "emu" surface always gets cleared and redrawn on each frame (by the emulation itself), while the "native" surface doesn't. Which means if you draw something on it once, it will stay there until it is overwritten. Again, I'm not 100% sure about it. And I'm not sure how it interacts with other built-in features (such as messages at the bottom, on-screen input indicators and frame counters).
Here's an example
Language: lua

function position(demoValue1,textX,textY) --gui.DrawNew("native") levelNumber = mainmemory.read_u8(demoValue1) + 1 gui.drawText(textX, textY,"Stage " .. levelNumber) end while true do position(0x0320,10,10) emu.frameadvance() end
With gui.DrawNew("native") commented out, we get this: This draws to the Emu surface, and is the default behavior. The net effect is that this is really good for drawing substitute HUDs, but is not so good for easily presenting the depth of information necessary in a TAS. For each frame that gui.DrawNew("native") is called, we would get the script drawn like this instead: This method draws to the BizHawk surface itself instead of on top of what the core is drawing. The net effect is that you can draw in the padding if you need to and have it. I haven't worked with the padding functions themselves as of yet.
Adventures in Lua When did I get a vest?
Pokota
He/Him
Joined: 2/5/2014
Posts: 779
This is still a thread, yo. Still working on updating the FF7 Crit Indicator script.
Language: lua

function generateCrit(luck, level, foelevel) sum = mainmemory.read_u8(luck) + mainmemory.read_u8(level) - mainmemory.read_u8(foelevel) div = math.floor(sum / 4) return div end function generateRNG(addr1, addr2, addr3) step1 = mainmemory.read_u8((addr2 + mainmemory.read_s32_le(addr3) + 1) % 8) step2 = mainmemory.read_u8(addr1 + step1) step3 = mainmemory.read_u8((addr2 + mainmemory.read_s32_le(addr3) + 2) % 8) step4 = mainmemory.read_u8(addr1 + step3) step5 = step4 * 256 step6 = step2 + step5 return math.floor((step6*99)/65535)+1 end while true do crit1 = generateCrit(0xf83f5, 0xf83e9, 0xf8589) crit2 = generateCrit(0xf845d, 0xf8451, 0xf8589) crit3 = generateCrit(0xf84c5, 0xf84b9, 0xf8589) crit_rng = generateRNG(0x83084, 0x62e10, 0x62e18) if crit1>=crit_rng then gui.text(0,50,"Critical Hit from Character 1 on Monster A!") else gui.text(0,50,"") end if crit2>=crit_rng then gui.text(0,60,"Critical Hit from Character 2!") else gui.text(0,60,"") end if crit3>=crit_rng then gui.text(0,70,"Critical Hit from Character 3!") else gui.text(0,70,"") end gui.text(0,30,"Enemy 1 crit% = " .. crit1 .. " " .. crit2 .. " " ..crit3) gui.text(0,40,"crit_rng = " .. crit_rng) emu.frameadvance() end
I've got some memory digging to do for the extensions I want to make (using character names instead of "Character 1," supporting multiple targets, ensuring that the addresses I do have are accurate...)
Adventures in Lua When did I get a vest?
Post subject: ZForms (proof of concept) - and my other lua scripts
CrazyTerabyte
He/Him
Joined: 5/7/2005
Posts: 74
Over time, I've written some Lua scripts and posted some of them here in the forums. Then, one day I decided to follow zeromus's suggestion and collected all my scripts in a repository: https://github.com/denilsonsa/bizhawk-lua-scripts In special, I want to share something I started working on, but stopped mid-way: ZForms. ZForms was my pet project that I wanted to fully implement before posting here. However, given that nowadays I'm not using a Windows machine anymore, and thus I haven't touched BizHawk in a while, I realized that it is unlikely I'll finish this project anytime soon. ZForms idea was to provide a simple (and almost declarative) API for building user interfaces. Have you ever used forms module to create a nice window for your script? When I did, it felt like it required too much manual work. It required positioning each widget, calculating new positions manually… It was cumbersome to use. ZForms was supposed to make building UIs fun again. It was supposed to simplify the creation of windows with several controls, automatically calculating the size and position of each widget. It could even automatically position the window itself. The current version (which is untouched since August 2015) has some features, but it is still incomplete and probably not ready for production. Consider it as a "tech demo", or as a "proof of concept". Feel free to get inspired by this project and build a better and more complete library than what I've written. I'd be very happy and glad to see a full library that was inspired by my project! :)
Skilled player (1743)
Joined: 9/17/2009
Posts: 4986
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
I'm not sure if it's answered before, but for these functions event.onmemoryexecute event.onmemoryread event.onmemorywrite How exactly do I know which one to use for an address?
AntyMew
It/Its
Encoder, Player (35)
Joined: 10/22/2014
Posts: 425
jlun2 wrote:
I'm not sure if it's answered before, but for these functions event.onmemoryexecute event.onmemoryread event.onmemorywrite How exactly do I know which one to use for an address?
Usually you shouldn't use any of them. These functions are for disassembly, and/or games you've already disassembled. Just reading the address every frame should be fine for most purposes.
Just a Mew! 〜 It/She ΘΔ 〜
1 2
6 7 8
13 14