1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-04 00:15:45 +02:00
ComfyFactorio/modules/team_teleport.lua
Gerkiz e91b6a352f 2.0 changes
Change global -> storage
Rework how rendering works
Game prototypes are now stored inside 'prototypes.#'
Renamed entity names
2024-10-22 21:47:11 +02:00

364 lines
12 KiB
Lua

-- by mewmew
-- modified by Gerkiz
local Event = require 'utils.event'
local Global = require 'utils.global'
local traps = {}
Global.register(
traps,
function (t)
traps = t
end
)
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
storage.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 traps[game.tick + t] then
traps[game.tick + t] = {}
end
if t % a == 0 then
traps[game.tick + t][#traps[game.tick + t] + 1] = {
callback = 'teleport_effects',
params = { source_player.surface, { x = source_player.position.x, y = source_player.position.y } }
}
traps[game.tick + t][#traps[game.tick + t] + 1] = {
callback = 'teleport_effects',
params = { source_player.surface, target_position }
}
traps[game.tick + t][#traps[game.tick + t] + 1] = {
callback = 'sync_health_and_direction',
params = { source_player, materializing_character }
}
a = a - 0.5
if a < 5 then
a = 5
end
end
if t % 2 == 0 then
traps[game.tick + t][#traps[game.tick + t] + 1] = {
callback = 'fix_player_position',
params = { source_player, { x = source_player.position.x, y = source_player.position.y } }
}
end
if t == 780 then
traps[game.tick + t][#traps[game.tick + t] + 1] = {
callback = 'teleport_player',
params = { 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
l = t.add({ type = 'label', caption = ' Distance: ' })
l.style.font = 'heading-2'
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 - storage.team_teleport_delay[player.name] < 0 then
local recovery_time = math.ceil(math.abs(game.tick - storage.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
storage.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 storage.team_teleport_delay then
storage.team_teleport_delay = {}
end
if not storage.team_teleport_delay[player.name] then
storage.team_teleport_delay[player.name] = 0
end
create_gui_toggle_button(player)
refresh_gui()
end
local function on_player_left_game()
refresh_gui()
end
local function on_tick()
if not traps[game.tick] then
return
end
for _, token in pairs(traps[game.tick]) do
local callback = token.callback
local params = token.params
if callback == 'teleport_effects' then
teleport_effects(params[1], params[2])
elseif callback == 'sync_health_and_direction' then
sync_health_and_direction(params[1], params[2])
elseif callback == 'fix_player_position' then
fix_player_position(params[1], params[2])
elseif callback == 'teleport_player' then
teleport_player(params[1], params[2], params[3])
end
end
traps[game.tick] = nil
end
Event.add(defines.events.on_tick, on_tick)
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)