PlanetPvPGreen/player.lua
2026-10-16 20:27:02 -05:00

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