User File #637788982150691225

Upload All User Files

#637788982150691225 - BBLIT Script (Autowalker, XY/XYZ Speed, Global Requirements Check) - Nymashock Support

BBLIT_TASING_nyma.lua
108 downloads
Uploaded 1/27/2022 4:36 PM by AleMastroianni (see all 3)
Keybinds: - J: Set waypoint destination - K: Remove waypoint destination - L: Activate/Deactivate Autowalk
Works both with octoshock and nymashock UI Fixes Added xyz pointers
Originally and mostly made by Noxxa and Warepire, Korky Fixed some UI things, AleMastroianni put global check requirements and pointers. Noxxa thankfully fixed it for Nyma diverse analog range and scheme. He did most of the job, im just uploading this in case i lose it locally.
local isNyma = false
local isNymaCheck = joypad.get()
if isNymaCheck["P1 Left Stick Left / Right"] ~= nil then
	isNyma = true
	console.log("Nyma core detected")
end

-- 6AAD3 control variable for in-stage state


-- local module definitions first
local bblitGUI = {}
do
	local areaX, areaY
	
	function bblitGUI.SetArea(x, y)
		areaX = x
		areaY = y
	end

	function bblitGUI.DrawBool(token, value)
		gui.text(areaX, areaY, string.format("%s: %s", token, tostring(value)))
		areaY = areaY + 20
	end		

	function bblitGUI.DrawValue(token, value)
		gui.text(areaX, areaY, string.format("%s: %d", token, value))
		areaY = areaY + 20
	end
	
	function bblitGUI.DrawVector2(token, value1, value2)
		gui.text(areaX, areaY, string.format("%s: (%3d,%3d)", token, value1, value2))
		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

	function bblitGUI.DrawLStick(x, y)
		local drawXScale = 1
		local drawYScale = 1
		if isNyma then
			drawXScale = 0.75
			drawYScale = 0.50
		end
	
		gui.drawEllipse(areaX * drawXScale, areaY * drawYScale, 256 * drawXScale, 256 * drawYScale, "white")
		gui.drawLine((areaX + 128) * drawXScale, (areaY + 128) * drawYScale, (areaX + x) * drawXScale, (areaY + y) * drawYScale, "red")
		gui.drawEllipse((areaX + x - 2) * drawXScale, (areaY + y - 2) * drawYScale, 4 * drawXScale, 4 * drawYScale, "red", "red")
		areaY = areaY + 260
	end
end

local bblitAngle = {}
do
	-- Conversions as per: http://electronicstechnician.tpub.com/14091/css/14091_316.htm

	function bblitAngle.DegreesToBAMS(degrees)
		-- no conversion necessary
		if degrees == 360 or degrees == 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


	function bblitAngle.BAMStoDegrees(bams)
		if bams == 4096 or bams == 0 then
			return 0
		end

		local returnValue = 0

		local BAMSbits = 0x800
		local angularDegrees = 180

		while bams > 0 do
			if bams >= BAMSbits then
				returnValue = returnValue + angularDegrees
				bams = bams - BAMSbits
			end

			BAMSbits = math.floor(BAMSbits / 2)
			angularDegrees = angularDegrees / 2

		end

		return returnValue
	end
	
	function bblitAngle.ClampBAMS(bams)
		if bams < 0 then
			bams = bams + 4096
		end
		if bams >= 4096 then
			bams = bams - 4096
		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 = {}
		if isNyma then
			analogInput["Left Stick Left / Right"] = x * 256
			analogInput["Left Stick Up / Down"] = y * 256
		else
			analogInput["LStick X"] = x
			analogInput["LStick Y"] = y
		end
		joypad.setanalog(analogInput, 1)
	end
end

local bblitAutowalk = {}
do
	local active = false
	local waypoints = {}
	local waypointAngle, diffAngle = 0, 0
	local input = { X = 128, Y = 128 }
	local gui
	local angle
	local joypad
	local Xdistance
    local Zdistance
	
	function bblitAutowalk.CopyWaypoint(wp)
		copy = {}
		for key, value in pairs(wp) do
			copy[key] = value
		end
		return copy
	end

	function bblitAutowalk.CountWaypoints()
		return table.getn(waypoints)
	end
	
	function bblitAutowalk.GetFirstWaypoint()
		return waypoints[1]
	end
	
	function bblitAutowalk.GetDifferenceAngle()
		return diffAngle
	end
	
	function bblitAutowalk.GetWaypointAngle()
		return waypointAngle
	end

	function bblitAutowalk.Init(modGui, modAngle, modJoypad)
		gui = modGui
		angle = modAngle
		joypad = modJoypad
	end

	function bblitAutowalk.Enable(yes)
		if yes and bblitAutowalk.CountWaypoints() == 0 then
			return
		end
		active = yes
		if active == false then
			input.X = 128
			input.Y = 128
			joypad.SetAnalog(input.X, input.Y)
		end
	end

	function bblitAutowalk.Enabled()
		return active
	end

	function bblitAutowalk.PushWaypoint(wp)
		table.insert(waypoints, bblitAutowalk.CopyWaypoint(wp))
	end

	function bblitAutowalk.PopWaypoint()
		if bblitAutowalk.CountWaypoints() > 0 then
			table.remove(waypoints)
		end
	end

	function bblitAutowalk.Autowalk(pos, camAngle)
		if not active or bblitAutowalk.CountWaypoints() < 1 then
			return
		end

		Xdistance = pos.X - waypoints[1].X
		Zdistance = pos.Z - waypoints[1].Z

		waypointAngle = angle.ClampBAMS(angle.DegreesToBAMS(angle.Vector2ToDegrees(Xdistance, Zdistance)))
		diffAngle = angle.ClampBAMS(camAngle - waypointAngle)
		local diffAngleRadians = math.rad(angle.BAMStoDegrees(diffAngle))
		
		--dead zone
		if diffAngleRadians < 0.406 and diffAngleRadians > 0.1 then
			diffAngleRadians = 0.406
		elseif diffAngleRadians > 5.870 and diffAngleRadians < 6.18 then
			diffAngleRadians = 5.870
		elseif diffAngleRadians < 0.1 or diffAngleRadians > 6.18 then
			diffAngleRadians = 0
		end
		
		
		-- Add 0.5 to round the float correctly as we go to integers
		-- Interpolate the X/Y from the angle as per: http://mathforum.org/sarah/hamilton/ham.1side.1angle.html
		-- X/Y are inverted (X = Y and Y = X) compared to the angle, they're also inverted along their own axis (X 255 = X 0)
		input.Y = math.abs(math.max(0, math.min(math.floor(((math.cos(diffAngleRadians) * 128) + 128) + 0.5), 255)) - 255)
		input.X = math.abs(math.max(0, math.min(math.floor(((math.sin(diffAngleRadians) * 128) + 128) + 0.5), 255)) - 255)
	
		if math.sqrt(Xdistance*Xdistance + Zdistance*Zdistance) < 150 then
			if bblitAutowalk.CountWaypoints() > 0 then
				-- Special, remove from front!
				--table.remove(waypoints, 1)
			end
			if bblitAutowalk.CountWaypoints() == 0 then
				--bblitAutowalk.Enable(false)
				input.X = 128
				input.Y = 128
				return
			end
		end

		joypad.SetAnalog(input.X, input.Y)
		
		waypointAngle = (waypointAngle + 2048) % 4096
	end

	-- HACK: Should not need pos as a parameter?
	function bblitAutowalk.DrawHUD(pos)
		gui.SetArea(0, 200)
		gui.DrawLStick(input.X, input.Y)
		gui.DrawVector2("L Stick", input.X, input.Y)
		gui.DrawBool("Autowalk", bblitAutowalk.Enabled())
		if bblitAutowalk.CountWaypoints() > 0 then
			for i, wp in ipairs(waypoints) do
				gui.DrawVector3(string.format("Waypoint %d", i), wp.X, wp.Y, wp.Z)
			end
		end
	end
end

local gui = bblitGUI
local angle = bblitAngle
local keyboard = bblitKeyboard
local joypad = bblitJoypad
local autowalk = bblitAutowalk

-----------------------
-----------------------
------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.

	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 pos = { X = 0, Y = 0, Z = 0 }
local posOld = { X = 0, Y = 0, Z = 0 }
local speed = { X = 0, Y = 0, Z = 0, XZ = 0, XYZ = 0 }
local camAngle, bugsAngle = 0, 0

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



			NORMAL_CARROTS = memory.read_u8 (0x010043)
			CLOCKS = memory.read_u8 (0x010045)
			GC1 = memory.read_u8 (0x010047)
			GC2 = memory.read_u8 (0x01013C)
			GOLDEN_CARROTS = GC1 + GC2 *256
			HP = memory.read_u8 (0x010041)

	pos.X = memory.read_s32_le(0x00069DC0)
	pos.Y = memory.read_s32_le(0x00069DC4)
	pos.Z = memory.read_s32_le(0x00069DC8)
	
	speed.X = pos.X - posOld.X
	speed.Y = pos.Y - posOld.Y
	speed.Z = pos.Z - posOld.Z
	
	speed.XZ = math.sqrt(speed.X*speed.X + speed.Z*speed.Z)
	speed.XYZ = math.sqrt(speed.X*speed.X + speed.Y*speed.Y + speed.Z*speed.Z)
	
	camAngle = angle.ClampBAMS(memory.read_s16_le(0x00069402))
	--Seems to change every stage?
	--bugsAngle = angle.ClampBAMS(memory.read_s16_le(0x000B8AAA))
	--HACK:
	if speed.XZ > 10 then
		bugsAngle = angle.DegreesToBAMS(angle.Vector2ToDegrees(speed.X, speed.Z))
	end

	autowalk.Autowalk(pos, camAngle)

	posOld.X = pos.X
	posOld.Y = pos.Y
	posOld.Z = pos.Z

end

local function main()

	CheckModule("GUI", gui)
	CheckModule("Angle", angle)
	CheckModule("Keyboard", keyboard)
	CheckModule("Joypad", joypad)
	CheckModule("Autowalk", autowalk)
	
	autowalk.Init(gui, angle, joypad)

--	Kork: What is the purpose of this? leaving space for text in the right side?
--	client.SetGameExtraPadding(200, 0, 500, 0)

	joypad.SetAnalog(128, 128)

	while true do
		keyboard.GetInput()
		Update()
		
		if keyboard.GetKeyDown("J") == true then
			autowalk.PushWaypoint(pos)
		end
		if keyboard.GetKeyDown("K") == true then
			autowalk.PopWaypoint()
		end
		if keyboard.GetKeyDown("L") == true then
			if autowalk.Enabled() then
				autowalk.Enable(false)
			else
				autowalk.Enable(true)
			end
		end
	

		gui.SetArea(0, 150)
		gui.DrawVector3("Position ", pos.X, pos.Y, pos.Z)
		--gui.DrawVector3("Speed    ", speed.X, speed.Y, speed.Z)
		gui.DrawValue(  "XZ Speed ", speed.XZ)
		gui.DrawValue(  "XYZ Speed", speed.XYZ)
		gui.DrawValue(  "Camera BAM Angle", camAngle)
		gui.DrawValue(  "Bugs BAM Angle  ", bugsAngle)
		gui.DrawValue(	"HP: ", HP)
		gui.DrawValue(	"Carrots: ", NORMAL_CARROTS)
		gui.DrawValue(	"Golden Carrots: ", GOLDEN_CARROTS)
		gui.DrawValue(	"Clocks: ", CLOCKS)

		
		
		if autowalk.Enabled() then
			if autowalk.CountWaypoints() > 0 then
				gui.DrawValue(  "Waypoint BAM angle", autowalk.GetWaypointAngle())
				gui.DrawValue(  "Diff BAM angle", autowalk.GetDifferenceAngle())
		
				if autowalk.Enabled() then
					local Xdistance = pos.X - autowalk.GetFirstWaypoint().X
					local Zdistance = pos.Z - autowalk.GetFirstWaypoint().Z
					gui.DrawValue(  "Autowalk distance", math.sqrt(Xdistance*Xdistance + Zdistance*Zdistance))
				end
			end
		end

		autowalk.DrawHUD(pos)

		emu.frameadvance()
	end
end

main()