firefly/mods/firefly_state/firefly_battle_mode/beacons.lua
2026-02-14 12:37:11 -05:00

163 lines
5.5 KiB
Lua

local ns = firefly
--minetest.register_entity(":firefly:beacon", {
-- initial_properties = {
-- visual = "sprite",
-- textures = {"blank.png"},
-- static_save = false,
-- },
-- time = 0,
-- on_step = function(e)
-- local time = minetest.get_us_time()
-- if time -e.time > 1000000 then
-- e.delegate:check_nearby()
-- e.time = time
-- end
-- end,
--})
local beacons = {}
local MAX_LOYALTY = 10
local Beacon
Beacon = {
init = function(game, pos, team)
local e = {
id = "beacon_"..minetest.get_us_time().."_"..math.random(1, 1000000),
game = game,
pos = game.map.pos +pos,
team = team or "__neutral",
loyalty = MAX_LOYALTY,
nearby = {},
}
setmetatable(e, Beacon)
beacons[e.id] = e
e:rebuild()
e._timer = function() e:check_nearby() end
ns.timer:listen("every_second", e._timer)
-- minetest.set_node(e.pos, {name = "beacon"})
-- minetest.get_meta(e.pos):set_string("beacon", e.id)
-- minetest.get_node_timer(e.pos):start(1)
return e
end,
deinit = function(e)
ns.timer:unlisten("every_second", e._timer)
beacons[e.id] = nil
end,
rebuild = function(e)
for x = e.pos.x -1, e.pos.x +1 do
for z = e.pos.z -1, e.pos.z +1 do
minetest.set_node(vector.new(x, e.pos.y -1, z), {name = "colored_glass", param2 = e.team == "__neutral" and 0 or e.team == "red" and 1 or 2})
end
end
end,
check_nearby = function(e)
local team = e.game.teams[e.team]
-- Give score to the controlling team, if there is one.
if team then
e.game:add_score(e.team, 1)
end
local not_nearby = table.copy(e.nearby)
local enemies_near = {}
local ally_near
for _, m in pairs(ns.players) do
if ns.manhattan_distance(m.pos, e.pos) < 3 then
if not e.nearby[m.name] then
ns.add_hud_bar(m, "beacon_status", {
max = MAX_LOYALTY,
min = 0,
title = "Beacon",
-- Charge-down if we are controlled by someone, but charge-up if contested.
value = e.team == "__neutral" and MAX_LOYALTY -e.loyalty or e.loyalty,
color = e.team == "__neutral" and "#fff" or e.game.teams[e.team].color,
})
end
e.nearby[m.name] = true
not_nearby[m.name] = nil
if m.team ~= e.team then
table.insert(enemies_near, m)
else
ally_near = true
end
end
end
for name in pairs(not_nearby) do
e.nearby[name] = nil
ns.remove_hud_bar(ns.players[name], "beacon_status")
end
-- If an enemy is near, weaken our team loyalty (but not if someone from out team is also near).
if #enemies_near > 0 and not ally_near then
-- Interference from competing enemy teams will also prevent us from losing loyalty, if we are contested.
local team
if e.team == "__neutral" then
for i = 1, #enemies_near do
local m = enemies_near[i]
if team and m.team ~= team then
team = nil
break
end
team = m.team
end
if team then
e:set_loyalty(e.loyalty -1)
end
-- Otherwise, we only care that at least one enemy is near.
else
e:set_loyalty(e.loyalty -1)
end
-- If this dropped our loyalty to zero, we must switch teams.
if e.loyalty <= 0 then
e:switch_team(team)
end
-- If no enemies are near, we can rebuild loyalty.
elseif e.loyalty < MAX_LOYALTY then
-- Loyalty is rebuilt faster if an ally is near.
e:set_loyalty(e.loyalty +(ally_near and 2 or 1))
end
end,
set_loyalty = function(e, value)
e.loyalty = value
-- Update the status bar seen by nearby players.
for name in pairs(e.nearby) do
ns.change_hud_bar(ns.players[name], "beacon_status",{
value = e.team == "__neutral" and MAX_LOYALTY -e.loyalty or e.loyalty,
})
end
end,
switch_team = function(e, team)
-- If we are switching from a non-contested state, we must enter a contested state before we can be assigned a new team.
if team and e.team ~= "__neutral" then
team = "__neutral"
end
-- If we didn't get a team, we weren't contested, but should be.
e.team = team or "__neutral"
-- Reset our loyalty.
e.loyalty = MAX_LOYALTY
-- We don't use set_loyalty to update the status bar because we also change the color.
for name in pairs(e.nearby) do
ns.change_hud_bar(ns.players[name], "beacon_status", {
value = e.team == "__neutral" and MAX_LOYALTY -e.loyalty or e.loyalty,
color = e.team == "__neutral" and "#fff" or e.game.teams[e.team].color or "#48d",
})
end
e:rebuild()
end,
}
Beacon.__index = Beacon
return Beacon