BallisticCalc = require("BallisticCalc")
Basalt = require("basalt")
CoordTransformer = require("CoordTransformer")
Quaternion = require("Quaternion")
Track = require("Track")
Util = require("Util")
Vector3d = require("Vector3d")
-- 系统初始化 --
local targetpos = { x = 0, y = 0, z = 0 }
local Cannon_Config = { Charge = 6, length = 18, G = -0.05, Drag = 0.01, Dep = -5, Ele = 90, Tol = 0.01, Mode = 3 }
local selfpos = coord.getCoord()
local q = peripheral.wrap("front").getRotation()
local vel = ship.getgetVelocity()
local i = 1
local rotation_matrix = {
x = Vector3d:new(1, 0, 0),
y = Vector3d:new(0, 1, 0),
z = Vector3d:new(0, 0, 1)
}
local cannon = peripheral.wrap("back")
local getPlayers = coord.getPlayersAll(50)
local players = {}
cannon.assemble()
local hasTargrt = false
local current_position = Vector3d:new( -1 , 0 , 0 )
local err_yaw, err_pitch
local yaw_control = peripheral.wrap("Create_RotationSpeedController_0")
local pitch_control = peripheral.wrap("Create_RotationSpeedController_1")
local yaw_speed, pitch_speed = 0, 0
local mode = 1
local controller = "AkashiSCO"
-- GUI初始化函数 --
local function createGUI()
local MainFrame = Basalt.getMainFrame()
-- 目标坐标显示组件
local targetXGui = MainFrame:addTextBox({ editable = false , background = colors.white , foreground = colors.red}):setPosition(4, 1):setSize(13, 1):setText(" TargetX");
local targetYGui = MainFrame:addTextBox({ editable = false , background = colors.white , foreground = colors.green}):setPosition(20, 1):setSize(13, 1):setText(" TargetY");
local targetZGui = MainFrame:addTextBox({ editable = false , background = colors.white , foreground = colors.blue}):setPosition(36, 1):setSize(13, 1):setText(" TargetZ");
-- 玩家选择控制组件
local TargetController = MainFrame:addTextBox({ editable = false , background = colors.white , foreground = colors.black}):setPosition(16, 2):setSize(20, 1):setText(
" control_player");
local buttomleft = MainFrame:addButton({ text = "<<--" , background = colors.white , foreground = colors.black }):setPosition(11, 2):setSize(4, 1)
local buttomright = MainFrame:addButton({ text = "-->>" , background = colors.white , foreground = colors.black }):setPosition(36, 2):setSize(4, 1)
-- 火炮配置组件
local Charge_text = MainFrame:addTextBox():setPosition(2, 4):setSize(10, 1):setText("Charge:" .. Cannon_Config.Charge)
local length_text = MainFrame:addTextBox():setPosition(15, 4):setSize(10, 1):setText("length:" ..Cannon_Config.length)
local Dep_text = MainFrame:addTextBox():setPosition(27, 4):setSize(10, 1):setText("Dep:" .. Cannon_Config.Dep)
local Ele_text = MainFrame:addTextBox():setPosition(40, 4):setSize(10, 1):setText("Ele:" .. Cannon_Config.Ele)
local G_text = MainFrame:addTextBox():setPosition(27, 5):setSize(10, 1):setText("G:" .. Cannon_Config.G)
local Drag_text = MainFrame:addTextBox():setPosition(15, 5):setSize(10, 1):setText("Drag:" .. Cannon_Config.Drag)
local reload_buttom = MainFrame:addButton({ text = "Apply Setting" }):setPosition(18, 6):setSize(13, 1)
return {
targetXGui = targetXGui,
targetYGui = targetYGui,
targetZGui = targetZGui,
TargetController = TargetController,
buttomleft = buttomleft,
buttomright = buttomright,
reload_buttom = reload_buttom,
Charge_text = Charge_text,
length_text = length_text,
Dep_text = Dep_text,
Ele_text = Ele_text,
G_text = G_text,
Drag_text = Drag_text
}
end
-- 初始化GUI并获取组件引用 --
local guiElements = createGUI()
-- 玩家列表处理 --
local function getPlayerslist()
i = 1
for _, v1 in pairs(getPlayers) do
for k, v2 in pairs(v1) do
if k == "name" then
players[i] = v2
i = i + 1
end
end
end
i = 1
end
getPlayerslist()
-- 工具函数 --
local function calcuspaces(max_length, text)
local text_length = string.len(text)
if text_length >= max_length then return "" end
local total_spaces = max_length - text_length
local left_spaces = math.floor(total_spaces / 2)
return string.rep(" ", left_spaces) .. text
end
local function getChatBoxContent(chatMessage)
if string.find(chatMessage, "xaero%-waypoint") then
local chatLocation = {}
for word in string.gmatch(chatMessage, "[%~%-%d]+") do
table.insert(chatLocation, word)
end
if chatLocation[3] == nil then chatLocation[3] = 69 end
if #chatLocation >= 4 then
return {
x = tonumber(chatLocation[2]),
y = tonumber(chatLocation[3]),
z = tonumber(chatLocation[4])
}
end
end
return nil
end
local function normalize_angle_diff(angle)
local normalized = angle % 360
if normalized > 180 then
normalized = normalized - 360
elseif normalized < -180 then
normalized = normalized + 360
end
return normalized
end
local function extract_number(input_str)
-- 匹配字符串中任意位置的第一个连续数字
local number_str = input_str:match("[-+]?%d*%.?%d+")
-- 加强类型转换校验
return tonumber(number_str) or 0
end
--计算目标相对于自身的速度
local function calculate_relative_velocity(
self_world_velocity, -- 自身世界速度 (Vector3d)
self_quaternion, -- 自身四元数 (Quaternion)
target_world_velocity -- 目标世界速度 (Vector3d)
)
-- 步骤1:计算相对世界速度
local relative_world_vel = target_world_velocity - self_world_velocity
-- 步骤2:应用四元数旋转
local rotated_velocity = self_quaternion:conj():rotate(relative_world_vel)
return rotated_velocity
end
-- 按钮事件处理 --
guiElements.buttomleft:onClick(function()
i = i - 1
if i < 1 then
i = #players
end
local len = #players[i]
local SpaceRep = string.rep(" ", math.floor((19 - len) / 2))
guiElements.TargetController:setText(SpaceRep .. players[i])
controller = players[i]
end)
guiElements.buttomright:onClick(function()
i = i + 1
if i > #players then
i = 1
end
local len = #players[i]
local SpaceRep = string.rep(" ", math.floor((19 - len) / 2))
guiElements.TargetController:setText(SpaceRep .. players[i])
controller = players[i]
end)
guiElements.reload_buttom:onClick(function()
Cannon_Config.Charge = extract_number(guiElements.Charge_text:getText())
Cannon_Config.length = extract_number(guiElements.length_text:getText())
Cannon_Config.Drag = extract_number(guiElements.Drag_text:getText())
Cannon_Config.Dep = extract_number(guiElements.Dep_text:getText())
Cannon_Config.Ele = extract_number(guiElements.Ele_text:getText())
Cannon_Config.G = extract_number(guiElements.G_text:getText())
end)
-- 目标获取函数 --
local function getTarget()
while true do
local _, user, msg = os.pullEvent("chat")
local target = getChatBoxContent(msg)
if target ~= nil and user == controller then
targetpos = Vector3d:new( target.x , target.y or 69 , target.z)
hasTargrt = true
local x_text = calcuspaces(13, "X=" .. targetpos.x)
local y_text = calcuspaces(13, "Y=" .. targetpos.y)
local z_text = calcuspaces(13, "Z=" .. targetpos.z)
guiElements.targetXGui:setText(x_text)
guiElements.targetYGui:setText(y_text)
guiElements.targetZGui:setText(z_text)
end
end
end
-- 控制逻辑函数 --
local function calc_speed_t(target)
local speed = target / 0.32222222222222222
return math.min(math.max(speed, -48), 48)
end
local function isdisassemble()
while true do
os.pullEvent("redstone")
if redstone.getInput("top") then
cannon.disassemble()
else
cannon.assemble()
end
end
end
-- 主控制逻辑 --
local function Main()
repeat os.sleep(0.5) until hasTargrt == true
while true do
selfpos = coord.getCoord()
q = peripheral.wrap("front").getRotation()
vel = ship.getgetVelocity()
local speed = Vector3d:new( vel.x , vel.y , vel.z )
local targetspeed = Vector3d:new( 0 , 0 , 0 )
local target_relative = CoordTransformer.InverseCoord(selfpos, targetpos, q)
local relative_Targrtspeed = calculate_relative_velocity( speed , q , targetspeed)
local relative_targetpos = {
x = target_relative.x - current_position.x,
y = target_relative.y - current_position.y,
z = target_relative.z - current_position.z
}
local Yaw, Dist_xz = BallisticCalc.calc_Yaw_and_Dist_xz(relative_targetpos, rotation_matrix, 90)
Yaw = Util:setInScope(Yaw)
local t_y = targetpos.y - selfpos.y - 1
local Pitch , time = BallisticCalc.customcalc(Dist_xz, t_y, Cannon_Config.Charge, Cannon_Config.length, Cannon_Config.G,Cannon_Config.Drag, Cannon_Config.Dep, Cannon_Config.Ele, Cannon_Config.Tol, mode)
if mode == 3 then
Pitch = Pitch.high or Pitch.low or 0
else
Pitch = Pitch or 0
end
local now_yaw = cannon.getYaw()
local now_pitch = cannon.getPitch()
err_yaw = normalize_angle_diff(Yaw - now_yaw)
err_pitch = normalize_angle_diff(Pitch - (now_pitch or 0))
yaw_speed = calc_speed_t(err_yaw)
pitch_speed = -calc_speed_t(err_pitch)
os.sleep(0.05)
end
end
-- 执行函数 --
local function setYawspeed()
repeat os.sleep(0.5) until hasTargrt == true
while true do
os.sleep(0.05)
if math.abs(yaw_speed) > 1 or math.abs(err_yaw) > 1 then
yaw_control.setTargetSpeed(yaw_speed)
else
yaw_control.setTargetSpeed(0)
if Yaw then
cannon.setYaw(Yaw)
end
end
end
end
local function setpitchspeed()
repeat os.sleep(0.5) until hasTargrt == true
while true do
os.sleep(0.05)
if math.abs(pitch_speed) > 1 or math.abs(err_pitch) > 1 then
pitch_control.setTargetSpeed(pitch_speed)
else
pitch_control.setTargetSpeed(0)
if Pitch then
cannon.setPitch(Pitch)
end
end
end
end
-- 启动所有并行任务 --
parallel.waitForAll(
Main,
setYawspeed,
setpitchspeed,
getTarget,
isdisassemble,
Basalt.run
)
这是我的代码,我希望把他的俯仰角和偏航角计算换成使用calc_leading_shot