163 lines
5.5 KiB
Lua
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
|