User File #44907750707175428

Upload All User Files

#44907750707175428 - R.C. Pro-Am - Nifty script

RCProAm_v2.lua
954 downloads
Uploaded 2/4/2018 9:58 AM by FatRatKnight (see all 245)
The script has a few features.
On the left, taking advantage of the 8 pixels of dead zone, I have a speed visual that basically deconstructs what effect your current velocity has. Colors are used to denote target speed, and the left vertical bar shows how much of an 8 MPH threshold is filled. Tick marks are used for 1 MPH increments, but meeting these tick marks have no impact on the player's position. Filling the rectangles do, representing these 8 MPH thresholds.
As well, the console output is also used to spit out frame counts automatically (using register exec functions) on how long it took to complete each race. There is a disabled feature in this script that would also use this output for checkpoints, letting the TASer know when the player has hit the next segment of the track. Uncomment a line with LogCheckpoints() (under function BasicHUD) in it to activate.
Finally, the numbers display. Shame my memory of the script is basically nil on the details here, but so it goes. I recommend experimenting a bit, and if that isn't helping, open the script and look for my comments in BasicHUD. I do have a habit of using hexadecimal if the numbers line up better that way.
--[[  Leeland Kirwan (FatRatKnight), 2014
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 btnstr= {A = "A", B   = "B", select= "S", start= "T",
               up= "U", down= "D", left  = "L", right= "R"}
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

    taseditor.clearinputchanges() -- Guessing something horrible w/o this.

    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
    local History= ""     -- Information for TASer in History list

    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])
                History= History .. pl .. btnstr[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(History) end
end
taseditor.registerauto(InputToggle)

--#############################################################################
--#############################################################################
--If you need some other code and other registers, I recommend them here.
--If you need the "while true do" loop, that's down below.

--*****************************************************************************
local Draw= {}
--*****************************************************************************
--Coordinates is the top-left pixel of the 3x5 digit.
--Used for drawing compact, colored numbers.

local Px,Li= gui.pixel, gui.line

Draw[0]= function(x,y,c) -- ###
    Li(x  ,y  ,x  ,y+4,c)-- # #
    Li(x+2,y  ,x+2,y+4,c)-- # #
    Px(x+1,y  ,c)        -- # #
    Px(x+1,y+4,c)        -- ###
end

Draw[1]= function(x,y,c) --  #
    Li(x  ,y+4,x+2,y+4,c)-- ##
    Li(x+1,y  ,x+1,y+3,c)--  #
    Px(x  ,y+1,c)        --  #
end                      -- ###

Draw[2]= function(x,y,c) -- ###
    Li(x  ,y  ,x+2,y  ,c)--   #
    Li(x  ,y+3,x+2,y+1,c)-- ###
    Li(x  ,y+4,x+2,y+4,c)-- #
    Px(x  ,y+2,c)        -- ###
    Px(x+2,y+2,c)
end

Draw[3]= function(x,y,c) -- ###
    Li(x  ,y  ,x+1,y  ,c)--   #
    Li(x  ,y+2,x+1,y+2,c)-- ###
    Li(x  ,y+4,x+1,y+4,c)--   #
    Li(x+2,y  ,x+2,y+4,c)-- ###
end

Draw[4]= function(x,y,c) -- # #
    Li(x  ,y  ,x  ,y+2,c)-- # #
    Li(x+2,y  ,x+2,y+4,c)-- ###
    Px(x+1,y+2,c)        --   #
end                      --   #

Draw[5]= function(x,y,c) -- ###
    Li(x  ,y  ,x+2,y  ,c)-- #
    Li(x  ,y+1,x+2,y+3,c)-- ###
    Li(x  ,y+4,x+2,y+4,c)--   #
    Px(x  ,y+2,c)        -- ###
    Px(x+2,y+2,c)
end

Draw[6]= function(x,y,c) -- ###
    Li(x  ,y  ,x+2,y  ,c)-- #
    Li(x  ,y+1,x  ,y+4,c)-- ###
    Li(x+2,y+2,x+2,y+4,c)-- # #
    Px(x+1,y+2,c)        -- ###
    Px(x+1,y+4,c)
end
                         -- ###
Draw[7]= function(x,y,c) --   #
    Li(x  ,y  ,x+1,y  ,c)--  ##
    Li(x+2,y  ,x+1,y+4,c)--  #
end                      --  #

Draw[8]= function(x,y,c) -- ###
    Li(x  ,y  ,x  ,y+4,c)-- # #
    Li(x+2,y  ,x+2,y+4,c)-- ###
    Px(x+1,y  ,c)        -- # #
    Px(x+1,y+2,c)        -- ###
    Px(x+1,y+4,c)
end

Draw[9]= function(x,y,c) -- ###
    Li(x  ,y  ,x  ,y+2,c)-- # #
    Li(x+2,y  ,x+2,y+3,c)-- ###
    Li(x  ,y+4,x+2,y+4,c)--   #
    Px(x+1,y  ,c)        -- ###
    Px(x+1,y+2,c)
end

Draw[10]=function(x,y,c) --  #
    Li(x  ,y+1,x  ,y+4,c)-- # #
    Li(x+2,y+1,x+2,y+4,c)-- # #
    Px(x+1,y  ,c)        -- ###
    Px(x+1,y+3,c)        -- # #
end

Draw[11]=function(x,y,c) -- ##
    Li(x  ,y  ,x  ,y+4,c)-- # #
    Li(x+1,y  ,x+2,y+1,c)-- ##
    Li(x+1,y+4,x+2,y+3,c)-- # #
    Px(x+1,y+2,c)        -- ##
end

Draw[12]=function(x,y,c) --  #
    Li(x  ,y+1,x  ,y+3,c)-- # #
    Li(x+1,y  ,x+2,y+1,c)-- #
    Li(x+1,y+4,x+2,y+3,c)-- # #
end                      --  #

Draw[13]=function(x,y,c) -- ##
    Li(x  ,y  ,x  ,y+4,c)-- # #
    Li(x+2,y+1,x+2,y+3,c)-- # #
    Px(x+1,y  ,c)        -- # #
    Px(x+1,y+4,c)        -- ##
end

Draw[14]=function(x,y,c) -- ###
    Li(x  ,y  ,x  ,y+4,c)-- #
    Li(x+1,y  ,x+2,y  ,c)-- ##
    Li(x+1,y+4,x+2,y+4,c)-- #
    Px(x+1,y+2,c)        -- ###
end

Draw[15]=function(x,y,c) -- ###
    Li(x  ,y  ,x  ,y+4,c)-- #
    Li(x+1,y  ,x+2,y  ,c)-- ##
    Px(x+1,y+2,c)        -- #
end                      -- #

--*****************************************************************************
local function __DN_AnyBase(right, y, Number, c, bkgnd, div)
--*****************************************************************************
-- Works with any base from 2 to 16. Paints the input number.
-- Returns the x position where it would paint another digit.
-- It only works with integers. Rounds fractions toward zero.

    if div < 2 then return end  -- Prevents the function from never returning.

    local Digit= {}
    local Negative= false
    if Number < 0 then
        Number= -Number
        Negative= true
    end

    Number= math.floor(Number)
    c= c or "white"
    bkgnd= bkgnd or "clear"

    local i= 0
    if Number < 1 then
        Digit[1]= 0
        i= 1
    end

    while (Number >= 1) do
        i= i+1
        Digit[i]= Number % div
        Number= math.floor(Number/div)
    end

    if Negative then  i= i+1  end
    local x= right - i*4
    gui.box(x+1, y-1, right+1, y+5,bkgnd,bkgnd)

    i= 1
    while Draw[Digit[i]] do
        Draw[Digit[i]](right-2,y,c)
        right= right-4
        i=i+1
    end

    if Negative then
        gui.line(right, y+2,right-2,y+2,c)
        right= right-4
    end
    return right
end
--*****************************************************************************
local function DrawNum(right, y, Number, c, bkgnd)
--*****************************************************************************
-- Paints the input number as right-aligned. Decimal version.
    return __DN_AnyBase(right, y, Number, c, bkgnd, 10)
end
--*****************************************************************************
local function DrawNumx(right, y, Number, c, bkgnd)
--*****************************************************************************
-- Paints the input number as right-aligned. Hexadecimal version.
    return __DN_AnyBase(right, y, Number, c, bkgnd, 16)
end

-------------------------------------------------------------------------------
local R1u= memory.readbyte
local R2u= memory.readword

local FA= false -- Flag. Behavior of emu.frameadvance not consistent enough.
local dX,dY= 0,0
--*****************************************************************************
local function d_pos()
--*****************************************************************************
--Bugged; I forget that gui.register is called repeatedly when paused.
--Meaning frame advance will always show 0, but playing shows other numbers.
    DrawNum( 60,180,dX,"orange","black")
    DrawNum( 60,186,dY,"orange","black")
end

local OldX,OldY= 0,0
--*****************************************************************************
local function Update_d_pos()
--*****************************************************************************
    local X= R2u(0x049C,0x04EC)*16 + R1u(0x05BC)/16
    local Y= R2u(0x04C4,0x0514)*16 + R1u(0x05C4)/16
    dX,dY= X-OldX,Y-OldY
    OldX,OldY=X,Y
end

local LastCheck= 0
--*****************************************************************************
local function LogCheckpoints()
--*****************************************************************************
    local Check= R1u(0x053C)
    if Check ~= LastCheck then
        LastCheck= Check
        print(string.format("c%2d f%6d x%5d y%5d s%3d.%2X",
           Check,
           emu.framecount(),
           R2u(0x049C,0x04EC)*16 + R1u(0x05BC)/16,
           R2u(0x04C4,0x0514)*16 + R1u(0x05C4)/16,
           R1u(0x05DC),R1u(0x05D8)
        ))
    end
end

--*****************************************************************************
local function VisualSpeed()
--*****************************************************************************
    local Spd,Sub,Max= R1u(0x05DC),R1u(0x05D8),R1u(0x0604)

    local Partial= math.floor(((Spd%8)*256+Sub)*225/2048)-1
    local Full= math.floor(Spd/8)

    local MaxPart= Max%8
    local MaxFull= math.floor(Max/8)

    for i= 1, 7 do
        local y= 231-math.floor(i*225/8)
        local clr= "orange"
        if i == MaxPart then clr= "white" end
        gui.line(0,y,4,y,clr)
    end

    if Partial >= 0 then
        gui.line(0,231,0,231-Partial,"white")
        gui.line(1,231,1,231-Partial,"white")
    end

    for i= 1, 15 do
        local y= 231-14*(i-1)
        local clr= "green"
        if i == MaxFull then clr="yellow" end
        if i >  MaxFull then clr="orange" end
        local fill= "black"
        if i <= Full then fill= clr end
        gui.box(3,y-12,7,y,fill,clr)
    end

--CPU cars
    local clr= {"green","orange","cyan"}
    for i= 1, 3 do
        local s= math.floor(R1u(0x05DC+i)/8)
        if s > 0 then
            local y= 234 - (s-1)*14 - i*4
            gui.line(2,y-2,2,y,clr[i])
        end
    end
end

--*****************************************************************************
local function BasicHUD()
--*****************************************************************************
    if FA then FA= false; Update_d_pos() end
    d_pos()
    VisualSpeed()
--    LogCheckpoints()

    DrawNum(  80,180,R2u(0x049C,0x04EC),"white" ,"black") -- X pos
    DrawNumx( 88,180,R1u(0x05BC)       ,"grey"  ,"black") -- X sub pos
    DrawNum(  80,186,R2u(0x04C4,0x0514),"white" ,"black") -- Y pos
    DrawNumx( 88,186,R1u(0x05C4)       ,"grey"  ,"black") -- Y sub pos
    DrawNum(  88,224,R1u(0x053C)       ,"green" ,"black") -- Checkpoint
    DrawNum( 184,180,R1u(0x05DC)       ,"green" ,"black") -- Speed
    DrawNumx(192,180,R1u(0x05D8)       ,"grey"  ,"black") -- Speed, sub
    DrawNumx(192,186,R1u(0x05DC)/8     ,"orange","black") -- Practical speed
    DrawNum( 184,186,R1u(0x0604)       ,"white" ,"black") -- Max speed

    local F,M= R1u(0x05CC),R1u(0x05E8)  --Facing & Momentum
    DrawNumx(110,180,(F-M)%256         ,"orange","black")
    DrawNumx(100,180,F                 ,"white" ,"black") -- Facing
    DrawNumx(120,180,M                 ,"green" ,"black") -- Momentum
    DrawNumx(128,180,R1u(0x05E4)       ,"grey"  ,"black") -- Momentum, sub
    DrawNum( 204,180,R1u(0x0459)       ,"orange","black") -- Ammo
    DrawNum( 160,180,R1u(0x05B8)       ,"white" ,"black") -- Invincibility

--Stuff about CPU cars. Just in case
    DrawNum(  22,  9,R1u(0x05DD)       ,"green" ,"black") -- Speed
    DrawNumx( 30,  9,R1u(0x05D9)       ,"grey"  ,"black") -- Speed, sub
    DrawNum(  22, 15,R1u(0x0605)       ,"green" ,"black") -- Max speed
    DrawNum(  22, 25,R1u(0x05DE)       ,"green" ,"black") -- Speed
    DrawNumx( 30, 25,R1u(0x05DA)       ,"grey"  ,"black") -- Speed, sub
    DrawNum(  22, 31,R1u(0x0606)       ,"orange","black") -- Max speed
    DrawNum(  22, 41,R1u(0x05DF)       ,"green" ,"black") -- Speed
    DrawNumx( 30, 41,R1u(0x05DB)       ,"grey"  ,"black") -- Speed, sub
    DrawNum(  22, 47,R1u(0x0607)       ,"cyan"  ,"black") -- Max speed

--[[  -- Just something to let me look at various addresses in a lua HUD.
    DrawNumx( 12,  8,R1u(0x002B),"green","black")
    DrawNumx( 12, 16,R1u(0x05B0),"green","black")
    DrawNumx( 12, 24,R1u(0x05B4),"green","black")
    DrawNumx( 12, 32,R1u(0x05B8),"green","black")
    DrawNumx( 12, 40,R1u(0x05BC),"green","black")
    DrawNumx( 12, 48,R1u(0x05C0),"green","black")
    DrawNumx( 12, 56,R1u(0x05C4),"green","black")
    DrawNumx( 12, 64,R1u(0x05C8),"green","black")
    DrawNumx( 12, 72,R1u(0x05CC),"green","black")
    DrawNumx( 12, 80,R1u(0x05D0),"green","black")
    DrawNumx( 12, 88,R1u(0x05D4),"green","black")
    DrawNumx( 12, 96,R1u(0x05D8),"green","black")
    DrawNumx( 12,104,R1u(0x05DC),"green","black")
]]--
end
gui.register(BasicHUD)

--#############################################################################
--#############################################################################
-- memory.registerexec time.

local FrameStart= 0
--*****************************************************************************
local function StartLine()
--*****************************************************************************
    FrameStart= emu.framecount()
    local Track= R1u(0x044B) + 1
    print(string.format("f%06d Track%02d begins",FrameStart,Track))
end
memory.registerexec(0xB52E,StartLine)

--*****************************************************************************
local function FinishLine()
--*****************************************************************************
    local FrameEnd= emu.framecount()
    local Track= R1u(0x044B) + 1
    print(string.format("f%06d Track%02d done. Length: %d",
        FrameEnd, Track, FrameEnd - FrameStart
    ))
end
memory.registerexec(0xAA46,FinishLine)

--#############################################################################
--#############################################################################
-- Ugh, need this loop on the very bottom...

--*****************************************************************************
while true do
--*****************************************************************************
-- Exists to detect frame advances, and thus clear the OldJoy array.
    for i= 1, 4 do OldJoy[i]= {} end -- Retrigger keys

-- Any code that needs this loop can go here.
    FA= true
    emu.frameadvance()
end
--f1592 - Finish first track

--f6357 - Me start track 4 (non-zero speed)
--f7696 - @1339 Me finish (pos doesn't update)

--f6573 - Adelikat start track 4
--f8364 - @1791 Yellow Car finishes track 4 (pos doesn't update)
--I suspect I can beat that just TAS driving. (Yep, I can. By seconds!)