mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-08 00:39:30 +02:00
230 lines
9.1 KiB
Lua
230 lines
9.1 KiB
Lua
local event = require 'utils.event'
|
|
|
|
local function teleport_player(surface, source_player, position)
|
|
local materializing_characters = source_player.surface.find_entities_filtered({
|
|
name = "character",
|
|
area = {{position.x - 1, position.y - 1},{position.x + 1, position.y + 1}},
|
|
force = "neutral"
|
|
})
|
|
for _, e in pairs(materializing_characters) do
|
|
if e.valid then e.destroy() end
|
|
end
|
|
|
|
if not source_player.character then return end
|
|
surface.create_entity({name = "character-corpse", position = source_player.position, force = source_player.force.name})
|
|
source_player.teleport(position, surface)
|
|
if source_player.character.health < 25 then source_player.character.health = 250 end
|
|
global.team_teleport_delay[source_player.name] = game.tick + 18000
|
|
end
|
|
|
|
local function fix_player_position(source_player, original_position)
|
|
if not source_player.character then return end
|
|
if source_player.position.x == original_position.x and source_player.position.y == original_position.y then return end
|
|
source_player.teleport(original_position, source_player.surface)
|
|
end
|
|
|
|
local function teleport_effects(surface, position)
|
|
local x = position.x + (4 - (math.random(1,80) * 0.1))
|
|
surface.create_entity({
|
|
name = "railgun-beam",
|
|
position = {x = position.x, y = position.y},
|
|
target = {x = x, y = position.y - math.random(6,13)}
|
|
})
|
|
for y = 0, 1, 1 do
|
|
surface.create_entity({
|
|
name = "water-splash",
|
|
position = {x = position.x, y = position.y + y},
|
|
})
|
|
end
|
|
if math.random(1,40) == 1 then surface.create_entity({name = "explosion", position = {x = position.x + (3 - (math.random(1,60) * 0.1)), y = position.y + (3 - (math.random(1,60) * 0.1))}}) end
|
|
if math.random(1,32) == 1 then surface.create_entity({name = "blood-explosion-huge", position = position}) end
|
|
if math.random(1,16) == 1 then surface.create_entity({name = "blood-explosion-big", position = position}) end
|
|
if math.random(1,8) == 1 then surface.create_entity({name = "blood-explosion-small", position = position}) end
|
|
end
|
|
|
|
local function sync_health_and_direction(player, materializing_character)
|
|
if not player.character then return end
|
|
if not player.character.valid then return end
|
|
if not materializing_character then return end
|
|
if not materializing_character.valid then return end
|
|
materializing_character.health = materializing_character.health + 2
|
|
materializing_character.direction = player.character.direction
|
|
if player.character.health < 3 then player.character.health = 1 return end
|
|
if player.character.health == 250 then player.character.damage(2, "player") return end
|
|
if math.random(1,64) == 1 then player.character.damage(2, "player") return end
|
|
player.character.health = player.character.health - 2
|
|
end
|
|
|
|
local function teleport(source_player, target_player)
|
|
source_player.teleport({x = math.floor(source_player.position.x), y = math.floor(source_player.position.y)})
|
|
local target_position = target_player.surface.find_non_colliding_position("character", target_player.position, 128, 1)
|
|
if not target_position then target_position = {x = target_player.position.x, y = target_player.position.y} end
|
|
local materializing_character = target_player.surface.create_entity({name = "character", position = target_position, force = "neutral", direction = source_player.character.direction})
|
|
materializing_character.destructible = false
|
|
materializing_character.color = source_player.color
|
|
materializing_character.damage(1, "player")
|
|
materializing_character.health = 1
|
|
|
|
local a = 20
|
|
for t = 0, 780, 1 do
|
|
if not global.on_tick_schedule[game.tick + t] then global.on_tick_schedule[game.tick + t] = {} end
|
|
|
|
if t % a == 0 then
|
|
global.on_tick_schedule[game.tick + t][#global.on_tick_schedule[game.tick + t] + 1] = {
|
|
func = teleport_effects,
|
|
args = {source_player.surface, {x = source_player.position.x, y = source_player.position.y}}
|
|
}
|
|
global.on_tick_schedule[game.tick + t][#global.on_tick_schedule[game.tick + t] + 1] = {
|
|
func = teleport_effects,
|
|
args = {source_player.surface, target_position}
|
|
}
|
|
|
|
global.on_tick_schedule[game.tick + t][#global.on_tick_schedule[game.tick + t] + 1] = {
|
|
func = sync_health_and_direction,
|
|
args = {source_player, materializing_character}
|
|
}
|
|
|
|
a = a - 0.5
|
|
if a < 5 then a = 5 end
|
|
end
|
|
|
|
if t % 2 == 0 then
|
|
global.on_tick_schedule[game.tick + t][#global.on_tick_schedule[game.tick + t] + 1] = {
|
|
func = fix_player_position,
|
|
args = {source_player, {x = source_player.position.x, y = source_player.position.y}}
|
|
}
|
|
end
|
|
|
|
if t == 780 then
|
|
global.on_tick_schedule[game.tick + t][#global.on_tick_schedule[game.tick + t] + 1] = {
|
|
func = teleport_player,
|
|
args = {target_player.surface, source_player, target_position}
|
|
}
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
local function get_sorted_player_table(requesting_player)
|
|
local t = {}
|
|
for _, player in pairs(game.connected_players) do
|
|
if player.name ~= requesting_player.name and player.force == requesting_player.force then
|
|
local distance = math.ceil(math.sqrt((player.position.x - requesting_player.position.x)^2 + (player.position.y - requesting_player.position.y)^2) * 10) * 0.1
|
|
table.insert(t, {name = player.name, distance = distance})
|
|
end
|
|
end
|
|
for i = 1, #t, 1 do
|
|
for i2 = 1, #t, 1 do
|
|
if t[i].distance > t[i2].distance then
|
|
local k = t[i]
|
|
t[i] = t[i2]
|
|
t[i2] = k
|
|
end
|
|
end
|
|
end
|
|
return t
|
|
end
|
|
|
|
local function create_gui_toggle_button(player)
|
|
if player.gui.top["team_teleport_button"] then return end
|
|
local b = player.gui.top.add({type = "sprite-button", name = "team_teleport_button", caption = "TP", tooltip = "Teleport to a Team Member"})
|
|
b.style.font_color = {r = 0.55, g = 0.22, b = 0.77}
|
|
b.style.font = "heading-1"
|
|
b.style.minimal_height = 38
|
|
b.style.minimal_width = 38
|
|
b.style.top_padding = 2
|
|
b.style.left_padding = 4
|
|
b.style.right_padding = 4
|
|
b.style.bottom_padding = 2
|
|
end
|
|
|
|
local function create_teleport_gui(player)
|
|
if player.gui.center["team_teleport"] then player.gui.center["team_teleport"].destroy() end
|
|
local frame = player.gui.center.add({type = "frame", name = "team_teleport", caption = "<< Teleport to player >>"})
|
|
frame.style.font_color = {r = 0.55, g = 0.22, b = 0.77}
|
|
frame.style.font = "heading-1"
|
|
|
|
local scroll_pane = frame.add({ type = "scroll-pane", name = "scroll_pane", direction = "vertical", horizontal_scroll_policy = "never", vertical_scroll_policy = "auto"})
|
|
scroll_pane.style.maximal_height = 320
|
|
scroll_pane.style.minimal_height = 320
|
|
|
|
local t = scroll_pane.add({type = "table", column_count = 3, name = "team_teleport_table"})
|
|
local player_table = get_sorted_player_table(player)
|
|
|
|
for _, k in pairs(player_table) do
|
|
local l = t.add({type = "button", name = k.name, caption = k.name})
|
|
l.style.font_color = {r = game.players[k.name].color.r * 0.5, g = game.players[k.name].color.g * 0.5, b = game.players[k.name].color.b * 0.5}
|
|
l.style.font = "heading-2"
|
|
l.style.minimal_width = 120
|
|
|
|
local l = t.add({type = "label", caption = " Distance: "})
|
|
l.style.font = "heading-2"
|
|
|
|
local l = t.add({type = "label", caption = tostring(k.distance)})
|
|
l.style.font_color = {r = 0.66, g = 0.66, b = 0.99}
|
|
l.style.font = "heading-2"
|
|
l.style.minimal_width = 100
|
|
end
|
|
end
|
|
|
|
local function on_gui_click(event)
|
|
if not event then return end
|
|
if not event.element then return end
|
|
if not event.element.valid then return end
|
|
|
|
local player = game.players[event.player_index]
|
|
local name = event.element.name
|
|
if name == "team_teleport_button" then
|
|
if player.gui.center["team_teleport"] then
|
|
player.gui.center["team_teleport"].destroy()
|
|
return
|
|
else
|
|
create_teleport_gui(player)
|
|
return
|
|
end
|
|
end
|
|
|
|
if not game.players[name] then return end
|
|
if event.element.parent.name ~= "team_teleport_table" then return end
|
|
if not player.character then return end
|
|
if not game.players[name].character then return end
|
|
if player.character.driving then return end
|
|
if game.tick - global.team_teleport_delay[player.name] < 0 then
|
|
local recovery_time = math.ceil(math.abs(game.tick - global.team_teleport_delay[player.name]) / 3600)
|
|
if recovery_time == 1 then
|
|
player.print("You need one more minute to recover from the last teleport.")
|
|
else
|
|
player.print("You are not capable of handling another teleport yet, you need " .. tostring(recovery_time) .. " more minutes to recover.")
|
|
end
|
|
return
|
|
end
|
|
global.team_teleport_delay[player.name] = game.tick + 900
|
|
teleport(player, game.players[name])
|
|
player.gui.center["team_teleport"].destroy()
|
|
end
|
|
|
|
local function refresh_gui()
|
|
for _, p in pairs(game.connected_players) do
|
|
if p.gui.center["team_teleport"] then
|
|
p.gui.center["team_teleport"].destroy()
|
|
create_teleport_gui(p)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function on_player_joined_game(event)
|
|
local player = game.players[event.player_index]
|
|
if not global.team_teleport_delay then global.team_teleport_delay = {} end
|
|
if not global.team_teleport_delay[player.name] then global.team_teleport_delay[player.name] = 0 end
|
|
create_gui_toggle_button(player)
|
|
refresh_gui()
|
|
end
|
|
|
|
local function on_player_left_game(event)
|
|
refresh_gui()
|
|
end
|
|
|
|
event.add(defines.events.on_gui_click, on_gui_click)
|
|
event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
|
event.add(defines.events.on_player_left_game, on_player_left_game)
|