1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-10-08 22:42:06 +02:00
Files
ComfyFactorio/modules/melee_mode.lua
2025-09-07 19:59:54 +02:00

266 lines
8.2 KiB
Lua

local Event = require 'utils.event'
local Global = require 'utils.global'
local SpamProtection = require 'utils.spam_protection'
local BottomFrame = require 'utils.gui.bottom_frame'
local Gui = require 'utils.gui'
local Task = require 'utils.task_token'
local melee_mode_name = Gui.uid_name()
local state = {}
Global.register(state, function (s) state = s end)
local delay_add_inner_frame_token =
Task.register(
function (event)
local player_index = event.player_index
local player = game.get_player(player_index)
if not player or not player.valid then
return
end
local activate_custom_buttons = BottomFrame.get('activate_custom_buttons')
if activate_custom_buttons then
BottomFrame.add_inner_frame(
{
player = player,
element_name = melee_mode_name,
tooltip =
{
'modules_melee.tooltip'
},
sprite = 'item/pistol',
section_override = 1
}
)
end
end
)
local function create_gui_button(player)
if player.gui.top[melee_mode_name] then
return
end
local tooltip = { "modules_melee.tooltip" }
local b = player.gui.top.add(
{
type = 'sprite-button',
sprite = 'item/pistol',
name = melee_mode_name,
tooltip = tooltip
})
b.style.font_color = { r = 0.11, g = 0.8, b = 0.44 }
b.style.font = 'heading-1'
b.style.minimal_height = 40
b.style.maximal_width = 40
b.style.minimal_width = 38
b.style.maximal_height = 38
b.style.padding = 1
b.style.margin = 0
end
local function on_player_joined_game(event)
local activate_custom_buttons = BottomFrame.get('activate_custom_buttons')
local player = game.get_player(event.player_index)
if not activate_custom_buttons then
create_gui_button(player)
else
Task.set_timeout_in_ticks(5, delay_add_inner_frame_token, { player_index = event.player_index })
end
end
local function move_to_main(player, from, to)
local ret = {}
if from == nil or to == nil then
return {}
end
for i = 1, #from do
local c = from[i]
if c.valid_for_read then
if to.can_insert(c) then
local amt = to.insert(c)
ret[#ret + 1] = { name = c.name, count = amt, quality = c.quality }
c.count = c.count - amt
else
player.print('Unable to move ' .. c.name .. ' to main inventory')
end
end
end
return ret
end
local function change_to_melee(player)
local main_inv = player.get_main_inventory()
local gun_inv = player.get_inventory(defines.inventory.character_guns)
local ammo_inv = player.get_inventory(defines.inventory.character_ammo)
if main_inv == nil or gun_inv == nil or ammo_inv == nil then
return false
end
local gun_moved = move_to_main(player, gun_inv, main_inv)
local ammo_moved = move_to_main(player, ammo_inv, main_inv)
state[player.index] = { gun = gun_moved, ammo = ammo_moved }
return true
end
local function try_move_from_main(main, to, what)
if what == nil or main == nil or to == nil then
return
end
for i = 1, #what do
local amt_out = main.remove(what[i])
if amt_out > 0 then
local amt_in = to.insert({ name = what[i].name, count = amt_out, quality = what[i].quality })
if amt_in < amt_out then
main.insert({ name = what[i].name, count = amt_out - amt_in, quality = what[i].quality })
end
end
end
end
local function change_to_ranged(player)
local moved = state[player.index]
if moved == nil then
moved = {}
end
local main_inv = player.get_main_inventory()
local gun_inv = player.get_inventory(defines.inventory.character_guns)
local ammo_inv = player.get_inventory(defines.inventory.character_ammo)
if main_inv == nil or gun_inv == nil or ammo_inv == nil then
return false
end
try_move_from_main(main_inv, gun_inv, moved.gun)
try_move_from_main(main_inv, ammo_inv, moved.ammo)
state[player.index] = {}
return true
end
local function on_gui_click(event)
local activate_custom_buttons = BottomFrame.get('activate_custom_buttons')
if activate_custom_buttons then
return
end
if not event.element then
return
end
if not event.element.valid then
return
end
if event.element.name ~= melee_mode_name then
return
end
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
local mm = player.gui.top[melee_mode_name]
if mm and mm.valid and mm.sprite == 'item/pistol' then
if change_to_melee(player) then
player.print({ "modules_melee.change_to_melee" })
mm.sprite = 'technology/steel-axe'
else
player.print({ "modules_melee.change_to_melee_failed" })
end
else
if change_to_ranged(player) then
player.print({ "modules_melee.change_to_ranged" })
mm.sprite = 'item/pistol'
else
player.print({ "modules_melee.change_to_ranged_failed" })
end
end
end
local function moved_to_string(tbl)
local ret = ''
for i = 1, #tbl do
if ret ~= '' then
ret = ret .. ', '
end
ret = ret .. tbl[i].count .. ' ' .. tbl[i].name
end
return ret
end
local function player_inventory_changed(player_index, inv_id, name)
local player = game.get_player(player_index)
if not player or not player.valid then
return
end
local activate_custom_buttons = BottomFrame.get('activate_custom_buttons')
if activate_custom_buttons then
local old_frame = BottomFrame.get_frame_by_element_name(player, melee_mode_name)
if old_frame and old_frame.sprite == 'item/pistol' then
return
end
else
if player.gui.top[melee_mode_name] and player.gui.top[melee_mode_name].valid and player.gui.top[melee_mode_name].sprite == 'item/pistol' then
return
end
end
local inv = player.get_inventory(inv_id)
local moved = move_to_main(player, inv, player.get_main_inventory())
if #moved > 0 then
player.print({ "modules_melee.move_to_main_inventory", moved_to_string(moved) })
end
if not inv or not inv.is_empty() then
player.print({ "modules_melee.move_to_main_inventory_failed", name })
end
end
local function on_player_ammo_inventory_changed(event)
if event.tick < 200 then return end
player_inventory_changed(event.player_index, defines.inventory.character_ammo, 'ammo')
end
local function on_player_gun_inventory_changed(event)
if event.tick < 200 then return end
player_inventory_changed(event.player_index, defines.inventory.character_guns, 'guns')
end
Gui.on_click(
melee_mode_name,
function (event)
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Mtn v3 Spectate Ready Button')
if is_spamming then
return
end
local player = event.player
if not player or not player.valid or not player.connected then
return
end
local old_frame = BottomFrame.get_frame_by_element_name(player, melee_mode_name)
if old_frame and old_frame.sprite == 'item/pistol' then
if change_to_melee(player) then
player.print({ "modules_melee.change_to_melee" })
old_frame.sprite = 'technology/steel-axe'
BottomFrame.refresh_inner_frames(player)
else
player.print({ "modules_melee.change_to_melee_failed" })
end
else
if change_to_ranged(player) then
player.print({ "modules_melee.change_to_ranged" })
old_frame.sprite = 'item/pistol'
BottomFrame.refresh_inner_frames(player)
else
player.print({ "modules_melee.change_to_ranged_failed" })
end
end
on_gui_click(event)
end
)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_gui_click, on_gui_click)
Event.add(defines.events.on_player_ammo_inventory_changed, on_player_ammo_inventory_changed)
Event.add(defines.events.on_player_gun_inventory_changed, on_player_gun_inventory_changed)