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

168 lines
4.3 KiB
Lua

local ns = firefly
local Beacon = include "beacons.lua"
local BattleMode = {
name = "battle"
}
BattleMode.__index = BattleMode
function BattleMode.init(map, players)
local e = {
map = map,
players = {},
beacons = {},
teams = {},
victory_conditions = {
max_score = 100,
}
}
setmetatable(e, BattleMode)
local teams_list = {}
for name, def in pairs(e.map.teams) do
e.teams[name] = {
color = def.color,
label = def.label,
score = 0,
players = {},
}
table.insert(teams_list, name)
end
for i = 1, #players do
local m = ns.players[players[i]]
local team = teams_list[math.random(1, #teams_list)]
e:add_player(team, m)
e.players[m.name] = m
end
for _, x in ipairs(map.beacons) do
table.insert(e.beacons, Beacon.init(e, x.pos or x, x.team))
end
return e
end
function BattleMode.deinit(e)
for i = 1, #e.beacons do
e.beacons[i]:deinit()
end
for name, m in pairs(e.players) do
for name, def in pairs(e.map.teams) do
ns.remove_hud_bar(m, name.."_team_score")
end
ns.remove_hud_bar(m, "beacon_status")
m.player:set_pos(vector.new(0, 12, 0))
end
end
function BattleMode.add_player(e, team, m)
m.game = e
m.player:set_pos(vector.new(math.random(e.map.pos.x, e.map.pos.x +e.map.size.x), e.map.pos.y +2, math.random(e.map.pos.z, e.map.pos.z +e.map.size.z)))
local players_in_team = #e.teams[team].players
for name, def in pairs(e.map.teams) do
ns.add_hud_bar(m, name.."_team_score", {
max = e.victory_conditions.max_score,
value = 0,
title = def.label or string.upper(string.sub(name, 1, 1))..string.sub(name, 2).." Team",
color = def.color
})
-- If the random choice would result in another team having two fewer players than this one, the player should be added to the underdog team instead.
if #e.teams[name].players < players_in_team then
team = name
end
end
m.team = team
table.insert(e.teams[team].players, m)
end
function BattleMode.remove_player(e, m)
end
function BattleMode.add_score(e, team, amount)
if e.game_over then return end
e.teams[team].score = e.teams[team].score +amount
-- Reflect the new score on players' HUD.
for name, m in pairs(e.players) do
ns.change_hud_bar(m, team.."_team_score", {
value = e.teams[team].score
})
end
if e.victory_conditions.max_score and e.teams[team].score >= e.victory_conditions.max_score then
e:declare_victory(team)
end
end
function BattleMode.declare_victory(e, team)
e.game_over = true
say("The "..team.." team has won the match!")
minetest.after(10, function()
e:deinit()
end)
end
function BattleMode.tick(e)
end
ns.register_mode(BattleMode)
local c_dirt_grass = minetest.get_content_id("dirt_grass")
local c_grass = minetest.get_content_id("grass")
ns.register_map {
name = "battle_test",
mode = "battle",
preview = "firefly_map_preview_battle_test.gltf",
preview_image = "firefly_battle_map_test.png",
size = vector.new(50, 50, 50),
beacons = {
vector.new(5, 1, 5),
vector.new(45, 1, 45),
{pos = vector.new(25, 2, 25), team = "red"}
},
teams = {
red = {
color = "#9b3c3c",
spawnpoint = vector.new(5, 2, 45)
},
blue = {
spawnpoint = vector.new(45, 2, 5)
}
},
generate = function(minp, maxp)
local vm = minetest.get_voxel_manip(minp, maxp)
local va = VoxelArea(vm:get_emerged_area())
local data = vm:get_data()
for x = minp.x, maxp.x do
for z = minp.z, maxp.z do
data[va:index(x, minp.y, z)] = c_dirt_grass
if math.random() < 0.4 then
data[va:index(x, minp.y +1, z)] = c_grass
end
end
end
vm:set_data(data)
vm:write_to_map()
end
}
ns.register_game_maker("battle", {
texture = "firefly_sand.png",
mode = "battle"
})