135 lines
5.3 KiB
Lua
135 lines
5.3 KiB
Lua
local player_system = {}
|
|
|
|
local function hide_dot(player)
|
|
if player and player.valid then player.show_on_map = false end
|
|
end
|
|
|
|
local function maintain_light(player)
|
|
if not (player and player.valid) then return end
|
|
storage.player_lights = storage.player_lights or {}
|
|
local light = storage.player_lights[player.index]
|
|
if not player.character or not player.character.valid then
|
|
if light and light.valid then light.destroy() end
|
|
storage.player_lights[player.index] = nil
|
|
return
|
|
end
|
|
if not light or not light.valid then
|
|
storage.player_lights[player.index] = rendering.draw_light{sprite = "utility/light_medium", target = player.character, surface = player.character.surface, players = {player}, scale = 1.2, intensity = .8, minimum_darkness = .2}
|
|
end
|
|
end
|
|
|
|
-- show_on_map is all-or-nothing, so allies are revealed with rendering objects
|
|
-- whose players list is restricted to the owner's force instead.
|
|
-- Name over the character in-world and on the map, plus a dot on the map.
|
|
-- Each is separate because render_mode is per-object.
|
|
local ALLY_MARKER_SPECS = {
|
|
{key = "name_game", mode = "game", text = true},
|
|
{key = "name_chart", mode = "chart", text = true},
|
|
{key = "dot_chart", mode = "chart", radius = 2},
|
|
}
|
|
|
|
local function is_team_force(force_name)
|
|
for _, name in pairs(storage.planet_teams or {}) do
|
|
if name == force_name then return true end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function maintain_marker(player)
|
|
if not (player and player.valid) then return end
|
|
storage.ally_markers = storage.ally_markers or {}
|
|
local markers = storage.ally_markers[player.index]
|
|
local viewers = {}
|
|
if player.character and player.character.valid and player.force and is_team_force(player.force.name) then
|
|
for _, ally in pairs(player.force.players) do
|
|
viewers[#viewers + 1] = ally.index
|
|
end
|
|
end
|
|
if #viewers == 0 then
|
|
if markers then for _, marker in pairs(markers) do if marker.valid then marker.destroy() end end end
|
|
storage.ally_markers[player.index] = nil
|
|
return
|
|
end
|
|
local color = (storage.force_colors and storage.force_colors[player.force.name]) or {r = 1, g = 1, b = 1, a = 1}
|
|
markers = markers or {}
|
|
for _, spec in pairs(ALLY_MARKER_SPECS) do
|
|
local marker = markers[spec.key]
|
|
if marker and marker.valid and marker.surface ~= player.character.surface then
|
|
marker.destroy()
|
|
marker = nil
|
|
markers[spec.key] = nil
|
|
end
|
|
if not (marker and marker.valid) then
|
|
if spec.text then
|
|
marker = rendering.draw_text{
|
|
text = player.name, surface = player.character.surface, target = player.character,
|
|
target_offset = {0, -2.5}, color = color, scale = 1.5, render_mode = spec.mode, players = viewers,
|
|
}
|
|
else
|
|
marker = rendering.draw_circle{
|
|
surface = player.character.surface, target = player.character, color = color,
|
|
radius = spec.radius, filled = true, render_mode = spec.mode, players = viewers,
|
|
}
|
|
end
|
|
markers[spec.key] = marker
|
|
else
|
|
marker.players = viewers
|
|
marker.target = player.character
|
|
marker.color = color
|
|
end
|
|
end
|
|
storage.ally_markers[player.index] = markers
|
|
end
|
|
|
|
-- Vanilla pins can bind to a player or their character, leaking a live
|
|
-- tracker arrow that defeats show_on_map = false. Drop any pin that targets
|
|
-- a player/character of another force.
|
|
local function clear_enemy_pins(player)
|
|
for _, pin in pairs(player.get_pins()) do
|
|
local pinned = pin.player
|
|
local leak = pinned and pinned.valid and pinned.force ~= player.force
|
|
if not leak then
|
|
for _, target in pairs(pin.targets or {}) do
|
|
if target.valid and target.type == "character" and target.force ~= player.force then
|
|
leak = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if leak and pin.valid then pin.destroy() end
|
|
end
|
|
end
|
|
|
|
function player_system.on_init()
|
|
storage.player_lights = storage.player_lights or {}
|
|
end
|
|
|
|
function player_system.on_player_created(event)
|
|
local player = game.get_player(event.player_index)
|
|
hide_dot(player); maintain_light(player)
|
|
end
|
|
|
|
function player_system.on_player_joined_game(event) hide_dot(game.get_player(event.player_index)) end
|
|
function player_system.on_player_respawned(event) hide_dot(game.get_player(event.player_index)); maintain_light(game.get_player(event.player_index)) end
|
|
|
|
function player_system.on_player_changed_surface(event)
|
|
local player = game.get_player(event.player_index)
|
|
if player and storage.player_lights[player.index] then
|
|
local light = storage.player_lights[player.index]
|
|
if light and light.valid then light.destroy() end
|
|
storage.player_lights[player.index] = nil
|
|
end
|
|
maintain_light(player)
|
|
end
|
|
|
|
function player_system.on_light_tick()
|
|
for _, player in pairs(game.connected_players) do
|
|
maintain_light(player)
|
|
maintain_marker(player)
|
|
clear_enemy_pins(player)
|
|
if player.character and player.character.valid then player.character.disable_flashlight() end
|
|
end
|
|
end
|
|
|
|
return player_system
|