PlanetPvPGreen/base.lua
2026-09-30 21:13:44 -05:00

166 lines
7.6 KiB
Lua

local drop_zone = require("drop_zone")
local base = {}
local COLORS = {
{r = .90, g = .45, b = .10, a = 1}, {r = .95, g = .20, b = .20, a = 1},
{r = .70, g = .20, b = .90, a = 1}, {r = .20, g = .85, b = .20, a = 1},
{r = .20, g = .60, b = .95, a = 1},
}
local function notify(force_name, message)
local force = game.forces[force_name]
if force then for _, player in pairs(force.players) do if player.valid then player.print(message) end end end
end
local function count(force_name)
local total = 0
for _ in pairs(storage.force_bases[force_name] or {}) do total = total + 1 end
return total
end
local function color_for(force_name)
return storage.force_colors[force_name] or {r = 1, g = 1, b = 1, a = 1}
end
function base.assign_force_color(force_name)
if storage.force_colors[force_name] then return end
local used = 0
for _ in pairs(storage.force_colors) do used = used + 1 end
storage.force_colors[force_name] = COLORS[(used % #COLORS) + 1]
end
function base.register(entity)
if not (entity and entity.valid) then return end
local force_name = entity.force.name
storage.force_bases[force_name] = storage.force_bases[force_name] or {}
storage.force_bases[force_name][entity.unit_number] = true
local color = color_for(force_name)
entity.color = color
storage.base_label_ids[entity.unit_number] = rendering.draw_text{
text = force_name, surface = entity.surface, target = entity, target_offset = {0, -3.5},
color = color, scale = 2, font = "default-bold", alignment = "center", visible = true,
}
notify(force_name, "[color=green][BASE] A base has been established at (" .. math.floor(entity.position.x)
.. ", " .. math.floor(entity.position.y) .. ") on " .. entity.surface.name .. ".[/color]")
end
function base.spawn_initial(force_name, planet_name)
local planet = game.planets[planet_name]
if not planet then return end
local surface = planet.create_surface()
local position = surface.find_non_colliding_position("market", {8, 0}, 200, 1) or {x = 8, y = 0}
local entity = surface.create_entity{name = "pvp-base", position = position, force = game.forces[force_name], raise_built = true}
if entity and entity.valid then base.register(entity) end
end
local function destroyed(entity)
local force_name = entity.force.name
if storage.force_bases[force_name] then storage.force_bases[force_name][entity.unit_number] = nil end
local label = storage.base_label_ids[entity.unit_number]
if label and label.valid then label.destroy() end
storage.base_label_ids[entity.unit_number] = nil
local remaining = count(force_name)
if remaining > 0 then
notify(force_name, "[color=orange][BASE] A base was destroyed! You have " .. remaining .. " base(s) remaining. Respawn is still active.[/color]")
else
notify(force_name, "[color=red][BASE] ALL BASES DESTROYED! Any player who dies now is PERMANENTLY ELIMINATED. Rebuild a base core to restore respawning.[/color]")
end
end
local function spectator(player)
player.set_controller{type = defines.controllers.spectator}
player.print("[color=red]You have been permanently eliminated.[/color]")
end
function base.on_built_entity(event)
if event.entity and event.entity.valid and event.entity.name == "pvp-base" then base.register(event.entity) end
end
function base.on_entity_died(event)
if event.entity and event.entity.valid and event.entity.name == "pvp-base" then destroyed(event.entity) end
end
function base.on_player_died(event)
local player = game.players[event.player_index]
if not (player and player.valid) then return end
if not (storage.player_team_joined and storage.player_team_joined[player.index]) then return end
local force_name = player.force.name
if storage.permadead[force_name] and storage.permadead[force_name][player.index] then return end
if count(force_name) > 0 then
player.print("[color=yellow]You died. Respawning... (Base is alive)[/color]")
else
storage.permadead[force_name] = storage.permadead[force_name] or {}
storage.permadead[force_name][player.index] = true
storage.pending_spectator[player.index] = force_name
player.print("[color=red]You died while your team had no base. You are PERMANENTLY ELIMINATED.[/color]")
end
end
function base.on_player_respawned(event)
local player = game.players[event.player_index]
if not (player and player.valid) then return end
if not (storage.player_team_joined and storage.player_team_joined[player.index]) then return end
local force_name = player.force.name
if storage.permadead[force_name] and storage.permadead[force_name][player.index] then spectator(player); return end
if count(force_name) == 0 then
storage.permadead[force_name] = storage.permadead[force_name] or {}
storage.permadead[force_name][player.index] = true
spectator(player)
return
end
for planet_name, assigned_force in pairs(storage.planet_teams or {}) do
if assigned_force == force_name then
local planet = game.planets[planet_name]
if planet and planet.surface then drop_zone.teleport_to_planet(player, planet.surface) end
return
end
end
end
function base.on_pre_player_mined_item(event)
local entity, player = event.entity, game.players[event.player_index]
if entity and entity.valid and entity.name == "pvp-base" and player and player.valid then
player.mining_state = {mining = false}
player.print("[color=red]The base cannot be moved once placed. Destroy it to retrieve the core.[/color]")
end
end
function base.on_robot_pre_mined(event)
local entity = event.entity
if entity and entity.valid and entity.name == "pvp-base" then entity.cancel_deconstruction("all") end
end
function base.on_tick(event)
if not storage.crash_site_cleanup_done then
local nauvis = game.planets["nauvis"] and game.planets["nauvis"].surface
if nauvis then
local crash_names = {
"crash-site-spaceship", "crash-site-spaceship-wreck-big-1", "crash-site-spaceship-wreck-big-2",
"crash-site-spaceship-wreck-medium-1", "crash-site-spaceship-wreck-medium-2", "crash-site-spaceship-wreck-medium-3",
"crash-site-spaceship-wreck-small-1", "crash-site-spaceship-wreck-small-2", "crash-site-spaceship-wreck-small-3",
"crash-site-spaceship-wreck-small-4", "crash-site-spaceship-wreck-small-5", "crash-site-spaceship-wreck-small-6",
"crash-site-chest-1", "crash-site-chest-2",
}
for _, name in pairs(crash_names) do
for _, entity in pairs(nauvis.find_entities_filtered{name = name}) do if entity.valid then entity.destroy() end end
end
for _, type in pairs({"fire", "smoke", "explosion", "particle"}) do
for _, entity in pairs(nauvis.find_entities_filtered{type = type, area = {{-200, -200}, {200, 200}}}) do if entity.valid then entity.destroy() end end
end
if event.tick >= 300 then storage.crash_site_cleanup_done = true end
end
end
if event.tick % 10 ~= 0 or not next(storage.pending_spectator) then return end
for index in pairs(storage.pending_spectator) do
local player = game.players[index]
if player and player.valid and not player.character then spectator(player); storage.pending_spectator[index] = nil end
end
end
function base.status_command(event)
local player = game.players[event.player_index]
if player then for force_name in pairs(storage.force_bases) do player.print(force_name .. ": " .. count(force_name) .. " base(s)") end end
end
return base