BBLiT.lua v2
--local module definitions first
local bblitGUI = {}
do
local areaX, areaY
function bblitGUI.SetArea(x, y)
areaX = x
areaY = y
end
function bblitGUI.DrawValue(token, value)
gui.text(areaX, areaY, string.format("%s: %d", token, value))
areaY = areaY + 20
end
function bblitGUI.DrawVector3(token, value1, value2, value3)
gui.text(areaX,areaY, string.format("%s: (%6d,%6d,%6d)", token, value1, value2, value3))
areaY = areaY + 20
end
end
local bblitAngle = {}
do
-- Conversion as per: http://electronicstechnician.tpub.com/14091/css/14091_316.htm
function bblitAngle.DegreesToBAMS(degrees)
-- no conversion necessary
if degrees == 360 or deg == 0 then
return 0
end
-- need to convert
local returnValue = 0
local BAMSbits = 0x800
local angularDegrees = 180
while BAMSbits > 0 do
if degrees >= angularDegrees then
returnValue = returnValue + BAMSbits
degrees = degrees - angularDegrees
end
BAMSbits = math.floor(BAMSbits / 2)
angularDegrees = angularDegrees / 2
end
return returnValue
end
--TODO!
function bblitAngle.BAMStoDegrees(bams)
console.log("Function not implemented! bblitAngle.BAMStoDegrees")
end
function bblitAngle.ClampBAMS(bams)
if bams < 0 then
bams = bams + 4096
end
if bams == 4096 then
bams = 0
end
return bams
end
function bblitAngle.Vector2ToDegrees(x, y)
local angle = math.atan2(x, y)
if angle < 0 then
angle = angle + (math.pi * 2)
end
angle = math.deg(angle)
return angle
end
end
local bblitKeyboard = {}
do
local keysToCheck = {"J", "K", "L"}
local keys = {}
local keysPrev = {}
local keysDown = {}
function bblitKeyboard.GetInput()
keys = input.get()
for i, v in ipairs(keysToCheck) do
if keys[v] == true and keysPrev[v] ~= true then
keysDown[v] = true
else
keysDown[v] = false
end
end
keysPrev = keys
end
function bblitKeyboard.GetKey(token)
return keys[token] == true
end
function bblitKeyboard.GetKeyDown(token)
return keysDown[token] == true
end
end
local bblitJoypad = {}
do
function bblitJoypad.SetAnalog(x, y)
local analogInput = {}
analogInput["LStick X"] = x
analogInput["LStick Y"] = y
joypad.setanalog(analogInput, 1)
end
end
local gui = bblitGUI
local angle = bblitAngle
local keyboard = bblitKeyboard
local joypad = bblitJoypad
-----------------------
-----------------------
------modules end------
-----------------------
-----------------------
local function CheckModule(name,mod)
if mod ~= nil and mod ~= true then
console.log("Module " .. name .. " successfully loaded.")
else
console.log("Module " .. name .. " failed to load! (value = " .. mod .. ")")
end
end
do
--Due to that the game internally runs at 30 fps despite rendering at 60 fps
--the speed values cannot be updated each frame.
--Apply some simpler logic to only update this once per 2 frames by using an
--address that increments at 30 fps.
--The updated flag solves an issue caused by using emu.yield()
local Counter30FPS = 0
local Counter30FPSOld = 0
function CheckDoUpdate()
Counter30FPS = memory.read_u32_le(0x00076010)
if Counter30FPS == Counter30FPSOld then
return false
end
Counter30FPSOld = Counter30FPS
return true
end
end
local Xpos, Ypos, Zpos = 0, 0, 0
local XposOld, YposOld, ZposOld = 0, 0, 0
local Xspeed, Yspeed, Zspeed = 0, 0, 0
local XZspeed, XYZspeed = 0, 0
local Xwaypoint, Ywaypoint, Zwaypoint = 0, 0, 0
local waypointActive,autowalkActive = false, false
local camAngle, bugsAngle, waypointAngle = 0, 0, 0
local diffAngle = 0
local inputX, inputY = 0, 0
local function SetWaypoint()
--disable waypoints by 'double tapping' on the same spot
if waypointActive == true and Xwaypoint == Xpos and Ywaypoint == Ypos and Zwaypoint == Zpos then
waypointActive = false
else
waypointActive = true
Xwaypoint = Xpos
Ywaypoint = Ypos
Zwaypoint = Zpos
end
end
local function SetAutowalk()
autowalkActive = not autowalkActive
if not autowalkActive then
inputX = 128
inputY = 128
joypad.SetAnalog(inputX, inputY)
console.log("Autowalk disabled.")
else
console.log("Autowalk enabled.")
end
end
local function CalculateAutowalk()
local Xdistance = Xpos - Xwaypoint
local Zdistance = Zpos - Zwaypoint
if diffAngle <= 0 and diffAngle > -256 then
local d = -diffAngle / 1.25
--if d < 64 then d = d * 2 end
inputX = 128 + d
inputY = 0
end
if diffAngle >= 0 and diffAngle < 256 then
local d = diffAngle / 1.25
--if d < 64 then d = d * 2 end
inputX = 128 - d
inputY = 0
end
if diffAngle <= -256 and diffAngle > -512 then
local d = -diffAngle / 4
--if d < 64 then d = d * 2 end
inputX = 128 + d
inputY = 0
end
if diffAngle >= 256 and diffAngle < 512 then
local d = diffAngle / 4
--if d < 64 then d = d * 2 end
inputX = 128 - d
inputY = 0
end
if diffAngle <= -512 and diffAngle > -1024 then
local d = -(diffAngle + 512) / 4
inputX = 255
inputY = 128 + d
end
if diffAngle >= 512 and diffAngle < 1024 then
local d = (diffAngle - 512) / 4
inputX = 0
inputY = 128 + d
end
if diffAngle <= -1024 and diffAngle > -1536 then
local d = -(diffAngle + 1024) / 4
inputX = 255
inputY = 128 + d
end
if diffAngle >= 1024 and diffAngle < 1536 then
local d = (diffAngle - 1024) / 4
inputX = 0
inputY = 128 + d
end
if diffAngle <= -1536 and diffAngle > -2048 then
local d = -(diffAngle + 1536) / 4
inputX = 128 + d
inputY = 255
end
if diffAngle >= 1536 and diffAngle < 2048 then
local d = (diffAngle - 1536) / 4
inputX = 128 + d
inputY = 255
end
if math.sqrt(Xdistance*Xdistance + Zdistance*Zdistance) < 150 then
inputX = 128
inputY = 128
end
if inputX < 0 then inputX = 0 end
if inputX > 255 then inputX = 255 end
if inputY < 0 then inputY = 0 end
if inputY > 255 then inputY = 255 end
inputX = math.floor(inputX)
inputY = math.floor(inputY)
end
local function Update()
if not CheckDoUpdate() then return end
--Actual speed vector addresses:
--addr 00069D30 X Speed [signed dword]
--addr 00069D34 Y Speed(?) [signed dword]
--addr 00069D38 Z Speed [signed dword]
--This is not reliable as it shows the speed Bugs want to travel at,
--not the actual speed that he moves at.
--Use position as a source for speed instead
Xpos = memory.read_s32_le(0x00069DC0)
Ypos = memory.read_s32_le(0x00069DC4)
Zpos = memory.read_s32_le(0x00069DC8)
Xspeed = Xpos - XposOld
Yspeed = Ypos - YposOld
Zspeed = Zpos - ZposOld
XZspeed = math.sqrt(Xspeed*Xspeed + Zspeed*Zspeed)
XYZspeed = math.sqrt(Xspeed*Xspeed + Yspeed*Yspeed + Zspeed*Zspeed)
camAngle = angle.ClampBAMS(-2048 + memory.read_s16_le(0x00069402))
if XZspeed > 10 then
bugsAngle = angle.DegreesToBAMS(angle.Vector2ToDegrees(Xspeed, Zspeed))
end
--bugsAngle = angle.ClampBAMS(memory.read_s16_le(0x000B8AAA))
if waypointActive then
local Xdistance = Xpos - Xwaypoint
local Zdistance = Zpos - Zwaypoint
waypointAngle = angle.ClampBAMS(-2048 + angle.DegreesToBAMS(angle.Vector2ToDegrees(Xdistance, Zdistance)))
diffAngle = camAngle - waypointAngle
if diffAngle < -2048 then diffAngle = diffAngle + 4096 end
if autowalkActive == true then
CalculateAutowalk()
--console.log("Attempting to set input " .. inputX .. " " .. inputY)
joypad.SetAnalog(inputX, inputY)
end
end
XposOld = Xpos
YposOld = Ypos
ZposOld = Zpos
end
local function main()
CheckModule("GUI", gui)
CheckModule("Angle", angle)
CheckModule("Keyboard", keyboard)
joypad.SetAnalog(128, 128)
while true do
keyboard.GetInput()
Update()
if keyboard.GetKeyDown("J") == true then
SetWaypoint()
end
if keyboard.GetKeyDown("K") == true then
SetAutowalk()
end
gui.SetArea(20, 56)
gui.DrawVector3("Position ", Xpos, Ypos, Zpos)
gui.DrawVector3("Speed ", Xspeed, Yspeed, Zspeed)
gui.DrawValue( "XZ Speed ", XZspeed)
gui.DrawValue( "XYZ Speed", XYZspeed)
gui.DrawValue( "Camera BAM Angle", camAngle)
gui.DrawValue( "Bugs BAM Angle ", bugsAngle)
if waypointActive then
gui.DrawVector3("Waypoint ", Xwaypoint, Ywaypoint, Zwaypoint)
gui.DrawValue( "Waypoint BAM angle", waypointAngle)
gui.DrawValue( "Diff BAM angle", diffAngle)
end
if autowalkActive then
local Xdistance = Xpos - Xwaypoint
local Zdistance = Zpos - Zwaypoint
gui.DrawValue( "Autowalk X", inputX)
gui.DrawValue( "Autowalk Y", inputY)
gui.DrawValue( "Autowalk distance", math.sqrt(Xdistance*Xdistance + Zdistance*Zdistance))
end
emu.frameadvance()
end
end
main()