Dateien nach "/" hochladen
This commit is contained in:
193
mecha_control_panel.lua
Normal file
193
mecha_control_panel.lua
Normal file
@@ -0,0 +1,193 @@
|
||||
-- assorted_mecha/mecha_control_panel.lua
|
||||
-- Per-mech configuration UI, opened via the remote control item
|
||||
-- State is stored directly in self_ent._ai_* fields (no persistent meta on entities)
|
||||
|
||||
local FORMNAME = "assorted_mecha:control_panel"
|
||||
|
||||
if not assorted_mecha_panel_refs then
|
||||
assorted_mecha_panel_refs = {}
|
||||
end
|
||||
|
||||
local function build_formspec(ent, clicker_name)
|
||||
local ai_on = ent._ai_enabled == true
|
||||
local atk_mob = ent._ai_attack_mobs ~= false
|
||||
local atk_ply = ent._ai_attack_players == true
|
||||
local prot = ent._ai_protect_owner ~= false
|
||||
local radius = tonumber(ent._ai_scan_radius) or 20
|
||||
local owner = ent._ai_owner or ""
|
||||
local mode = ent._ai_mode or "guard"
|
||||
local enemies = ent._ai_enemy_players or {}
|
||||
local enemy_set = {}
|
||||
for _, n in ipairs(enemies) do enemy_set[n] = true end
|
||||
|
||||
local player_list = {}
|
||||
for _, p in ipairs(minetest.get_connected_players()) do
|
||||
local pn = p:get_player_name()
|
||||
if pn ~= clicker_name then table.insert(player_list, pn) end
|
||||
end
|
||||
|
||||
local fs = "formspec_version[4]"
|
||||
.. "size[9,10.5]"
|
||||
.. "bgcolor[#1a1a2e;true]"
|
||||
.. "box[0,0;9,0.8;#0f3460]"
|
||||
.. "label[0.3,0.5;MECHA CONTROL PANEL]"
|
||||
|
||||
-- AI on/off status
|
||||
fs = fs .. "box[0.2,1.0;8.6,1.3;#16213e]"
|
||||
if ai_on then
|
||||
fs = fs
|
||||
.. "box[3.4,1.05;5.2,1.2;#0d4f1a]"
|
||||
.. "label[3.7,1.7;ACTIVE - boarding disabled]"
|
||||
.. "button[0.5,1.1;2.7,0.9;toggle_ai;Deactivate]"
|
||||
else
|
||||
fs = fs
|
||||
.. "box[3.4,1.05;5.2,1.2;#4f1a0d]"
|
||||
.. "label[3.7,1.7;MANUAL - mech is boardable]"
|
||||
.. "button[0.5,1.1;2.7,0.9;toggle_ai;Activate AI]"
|
||||
end
|
||||
|
||||
-- Owner
|
||||
fs = fs
|
||||
.. "box[0.2,2.45;8.6,0.7;#16213e]"
|
||||
.. "label[0.5,2.85;Owner: " .. (owner ~= "" and owner or "(none)") .. "]"
|
||||
.. "button[6.5,2.5;2.1,0.55;claim_owner;Claim]"
|
||||
|
||||
-- Owner protection
|
||||
fs = fs
|
||||
.. "box[0.2,3.3;8.6,0.7;#16213e]"
|
||||
.. "checkbox[0.5,3.7;cb_protect;Protect owner (no friendly fire);"
|
||||
.. (prot and "true" or "false") .. "]"
|
||||
|
||||
-- AI mode
|
||||
fs = fs
|
||||
.. "box[0.2,4.1;8.6,0.75;#16213e]"
|
||||
.. "label[0.5,4.4;AI Mode:]"
|
||||
.. "button[2.5,4.15;2.9,0.55;mode_guard;" .. (mode == "guard" and "[GUARD]" or "Guard") .. "]"
|
||||
.. "button[5.5,4.15;2.9,0.55;mode_freerun;" .. (mode == "freerun" and "[FREERUN]" or "Freerun") .. "]"
|
||||
|
||||
-- Attack targets
|
||||
fs = fs
|
||||
.. "box[0.2,5.0;8.6,1.65;#16213e]"
|
||||
.. "label[0.5,5.35;Attack targets:]"
|
||||
.. "checkbox[0.5,5.75;cb_mobs;Hostile mobs and entities;"
|
||||
.. (atk_mob and "true" or "false") .. "]"
|
||||
.. "checkbox[0.5,6.25;cb_players;Other players (PvP);"
|
||||
.. (atk_ply and "true" or "false") .. "]"
|
||||
|
||||
-- Scan radius
|
||||
local bar_val = math.floor((radius / 50) * 1000)
|
||||
fs = fs
|
||||
.. "box[0.2,6.85;8.6,1.05;#16213e]"
|
||||
.. "label[0.5,7.2;Scan radius: " .. radius .. " nodes]"
|
||||
.. "scrollbar[0.5,7.4;8.0,0.45;horizontal;radius_bar;" .. bar_val .. "]"
|
||||
|
||||
-- Enemy player list (only shown when PvP is enabled)
|
||||
if atk_ply then
|
||||
fs = fs .. "box[0.2,8.05;8.6,1.6;#16213e]"
|
||||
.. "label[0.5,8.4;Mark as enemy:]"
|
||||
if #player_list > 0 then
|
||||
local col, row = 0, 0
|
||||
for _, pname in ipairs(player_list) do
|
||||
local x = 0.5 + col * 4.3
|
||||
local y = 8.75 + row * 0.55
|
||||
fs = fs .. "checkbox[" .. x .. "," .. y .. ";enemy_" .. pname
|
||||
.. ";" .. pname .. ";" .. (enemy_set[pname] and "true" or "false") .. "]"
|
||||
col = col + 1
|
||||
if col >= 2 then col = 0; row = row + 1 end
|
||||
end
|
||||
else
|
||||
fs = fs .. "label[0.5,8.8;(No other players online)]"
|
||||
end
|
||||
end
|
||||
|
||||
-- Save / Cancel
|
||||
fs = fs
|
||||
.. "box[0,9.9;9,0.6;#0f3460]"
|
||||
.. "button_exit[0.5,9.95;3.5,0.85;save;Save]"
|
||||
.. "button_exit[5.0,9.95;3.5,0.85;cancel;Cancel]"
|
||||
|
||||
return fs
|
||||
end
|
||||
|
||||
function assorted_mecha_open_panel(ent, clicker)
|
||||
if not ent or not clicker then return end
|
||||
local cname = clicker:get_player_name()
|
||||
assorted_mecha_panel_refs[cname] = ent
|
||||
minetest.show_formspec(cname, FORMNAME, build_formspec(ent, cname))
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= FORMNAME then return false end
|
||||
local pname = player:get_player_name()
|
||||
local ent = assorted_mecha_panel_refs[pname]
|
||||
if not ent or not ent.object or not ent.object:get_pos() then
|
||||
assorted_mecha_panel_refs[pname] = nil
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.toggle_ai then
|
||||
ent._ai_enabled = not ent._ai_enabled
|
||||
if ent._ai_enabled then
|
||||
assorted_mecha_ai_start(ent)
|
||||
else
|
||||
ent._ai_running = false
|
||||
end
|
||||
minetest.show_formspec(pname, FORMNAME, build_formspec(ent, pname))
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.claim_owner then
|
||||
ent._ai_owner = pname
|
||||
minetest.show_formspec(pname, FORMNAME, build_formspec(ent, pname))
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.cancel then
|
||||
assorted_mecha_panel_refs[pname] = nil
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.mode_guard then
|
||||
ent._ai_mode = "guard"
|
||||
ent._ai_waypoint = nil
|
||||
minetest.show_formspec(pname, FORMNAME, build_formspec(ent, pname))
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.mode_freerun then
|
||||
ent._ai_mode = "freerun"
|
||||
minetest.show_formspec(pname, FORMNAME, build_formspec(ent, pname))
|
||||
return true
|
||||
end
|
||||
|
||||
if fields.save then
|
||||
if fields.cb_mobs ~= nil then ent._ai_attack_mobs = fields.cb_mobs == "true" end
|
||||
if fields.cb_players ~= nil then ent._ai_attack_players = fields.cb_players == "true" end
|
||||
if fields.cb_protect ~= nil then ent._ai_protect_owner = fields.cb_protect == "true" end
|
||||
|
||||
if fields.radius_bar then
|
||||
local bar_val = tonumber(string.match(fields.radius_bar, "CHG:(%d+)") or
|
||||
string.match(fields.radius_bar, "(%d+)") or "400")
|
||||
local r = math.max(5, math.min(50, math.floor((bar_val / 1000) * 50)))
|
||||
ent._ai_scan_radius = r
|
||||
end
|
||||
|
||||
local enemies = {}
|
||||
for k, v in pairs(fields) do
|
||||
if string.sub(k, 1, 6) == "enemy_" and v == "true" then
|
||||
table.insert(enemies, string.sub(k, 7))
|
||||
end
|
||||
end
|
||||
ent._ai_enemy_players = enemies
|
||||
|
||||
if ent._ai_enabled and not ent._ai_running then
|
||||
assorted_mecha_ai_start(ent)
|
||||
end
|
||||
|
||||
assorted_mecha_panel_refs[pname] = nil
|
||||
minetest.chat_send_player(pname, "[Mecha] Settings saved.")
|
||||
return true
|
||||
end
|
||||
|
||||
return true
|
||||
end)
|
||||
Reference in New Issue
Block a user