201 lines
5.4 KiB
Lua
201 lines
5.4 KiB
Lua
local S = minetest.get_translator("tntrun")
|
|
|
|
-- Clear all TNT within the arena region.
|
|
-- No-op if arena region is not set.
|
|
function tntrun.clear_tnt(arena)
|
|
local positions = {}
|
|
local pos1 = arena.pos1
|
|
local pos2 = arena.pos2
|
|
if not pos1 or not pos2 then
|
|
return false
|
|
end
|
|
pos1, pos2 = tntrun.sort_positions(pos1, pos2)
|
|
minetest.load_area(pos1, pos2)
|
|
|
|
for x = pos1.x, pos2.x do
|
|
for y = pos1.y, pos2.y do
|
|
for z = pos1.z, pos2.z do
|
|
local pos = {x=x,y=y,z=z}
|
|
local node = minetest.get_node(pos)
|
|
if node.name == "tntrun:tnt" then
|
|
table.insert(positions, pos)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
minetest.bulk_set_node(positions, {name="air"})
|
|
minetest.fix_light(arena.pos1, arena.pos2)
|
|
return true
|
|
end
|
|
|
|
-- Place the TNT layers
|
|
function tntrun.place_tnt(arena)
|
|
local positions = {}
|
|
for k = 1, #arena.tnt_area_pos_1 do
|
|
local pos1 = arena.tnt_area_pos_1[k]
|
|
local pos2 = arena.tnt_area_pos_2[k]
|
|
minetest.load_area(pos1, pos2)
|
|
pos1, pos2 = tntrun.sort_positions(pos1, pos2)
|
|
|
|
for x = pos1.x, pos2.x do
|
|
for y = pos1.y, pos2.y do
|
|
for z = pos1.z, pos2.z do
|
|
local pos = {x=x,y=y,z=z}
|
|
local node = minetest.get_node(pos)
|
|
-- Only air is replaced to allow to more control
|
|
-- of the map designer
|
|
if node.name == "air" then
|
|
table.insert(positions, pos)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
minetest.bulk_set_node(positions, {name="tntrun:tnt"})
|
|
end
|
|
|
|
-- Remove all falling TNT entities in the arena.
|
|
-- The arena region must be set for this to work.
|
|
local function remove_falling_tnt_entities(arena)
|
|
if not arena.pos1 or not arena.pos2 then
|
|
return
|
|
end
|
|
local pos1, pos2 = tntrun.sort_positions(arena.pos1, arena.pos2)
|
|
local objs = minetest.get_objects_in_area(pos1, pos2)
|
|
for o=1, #objs do
|
|
local obj = objs[o]
|
|
local ent = obj:get_luaentity()
|
|
if ent and ent .name == "tntrun:tnt_falling" then
|
|
obj:remove()
|
|
end
|
|
end
|
|
end
|
|
|
|
arena_lib.on_load("tntrun", function(arena)
|
|
remove_falling_tnt_entities(arena)
|
|
tntrun.place_tnt(arena)
|
|
for pl_name, _ in pairs(arena.players) do
|
|
local message = S('How it works:')
|
|
minetest.chat_send_player(pl_name,message)
|
|
message = minetest.colorize('#f47e1b', S('Punch TNTs to make them fall down'))
|
|
minetest.chat_send_player(pl_name,message)
|
|
message = minetest.colorize('#e6482e', S('But beware: TNTs will also fall down when you walk onto it. Keep moving!'))
|
|
minetest.chat_send_player(pl_name,message)
|
|
arena.players[pl_name].lives = arena.lives
|
|
|
|
end
|
|
|
|
local countdown
|
|
countdown = function(seconds_left)
|
|
if seconds_left <= 0 then
|
|
arena_lib.HUD_send_msg_all("title", arena, S("Run!"), 1, {name="tntrun_round_start", gain=0.4}, 0x00FF00)
|
|
local item = ItemStack("tntrun:torch")
|
|
for pl_name, _ in pairs(arena.players) do
|
|
local player = minetest.get_player_by_name(pl_name)
|
|
player:get_inventory():set_stack("main", 1, item)
|
|
end
|
|
else
|
|
arena_lib.HUD_send_msg_all("title", arena, tostring(seconds_left), 1, {name="tntrun_countdown", gain=1.0}, 0xFFFF00)
|
|
minetest.after(1, countdown, seconds_left - 1)
|
|
end
|
|
end
|
|
|
|
countdown(3)
|
|
end)
|
|
|
|
arena_lib.on_end("tntrun", function(arena)
|
|
remove_falling_tnt_entities(arena)
|
|
tntrun.place_tnt(arena)
|
|
end)
|
|
|
|
arena_lib.on_time_tick("tntrun", function(arena)
|
|
-- Kill players who have fallen below the elimination height
|
|
|
|
-- Get players at the critical height
|
|
local to_eliminate = {}
|
|
for p_name in pairs(arena.players) do
|
|
local player = minetest.get_player_by_name(p_name)
|
|
local y = player:get_pos().y
|
|
if y <= arena.eliminate_height then
|
|
table.insert(to_eliminate, {player_name = p_name , y = y})
|
|
end
|
|
end
|
|
|
|
-- Sort players by height (lowest player first)
|
|
table.sort(to_eliminate, function(e1, e2)
|
|
return e1.y < e2.y
|
|
end)
|
|
|
|
-- Eliminate players, starting with the lowest player first,
|
|
-- as a tiebreaker in case multiple players
|
|
-- get eliminated in the same tick.
|
|
for e=1, #to_eliminate do
|
|
local elim = to_eliminate[e]
|
|
arena_lib.remove_player_from_arena(elim.player_name, 1)
|
|
end
|
|
end)
|
|
|
|
arena_lib.on_death('tntrun', function(arena, p_name, reason)
|
|
arena_lib.remove_player_from_arena(p_name, 1)
|
|
end)
|
|
|
|
arena_lib.on_eliminate('tntrun', function(arena, p_name)
|
|
-- Play elimination sound when player eliminated
|
|
-- and lose sound to the player who got
|
|
-- eliminated
|
|
minetest.sound_play('tntrun_lose', {
|
|
to_player = p_name,
|
|
gain = 2.0,
|
|
}, true)
|
|
|
|
local count = 0
|
|
local sound = 'tntrun_elim'
|
|
for p_name,data in pairs(arena.players) do
|
|
count = count + 1
|
|
end
|
|
if count == 1 then
|
|
-- No elimination sound for the last
|
|
-- player; they'll get the win sound
|
|
-- in celebration
|
|
return
|
|
end
|
|
|
|
local player = minetest.get_player_by_name(p_name)
|
|
|
|
for p_name, _ in pairs(arena.players) do
|
|
minetest.sound_play(sound, {
|
|
to_player = p_name,
|
|
gain = 2.0,
|
|
}, true)
|
|
end
|
|
end)
|
|
|
|
-- Play win sound to winners
|
|
arena_lib.on_celebration('tntrun', function(arena, winners)
|
|
local winners_list = {}
|
|
if type(winners) == "string" then
|
|
winners_list = {winners}
|
|
elseif type(winners) == "table" then
|
|
winners_list = winners
|
|
elseif winners == nil then
|
|
return
|
|
else
|
|
minetest.log("error", "[tntrun] winners in on_celebration is neither a string, table or nil")
|
|
return winners
|
|
end
|
|
for w=1, #winners_list do
|
|
local p_name = winners_list[w]
|
|
minetest.sound_play('tntrun_win', {
|
|
to_player = p_name,
|
|
gain = 1.0,
|
|
}, true)
|
|
end
|
|
return winners
|
|
end)
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
local inv = player:get_inventory()
|
|
local stack = ItemStack("tntrun:torch")
|
|
local taken = inv:remove_item("main", stack)
|
|
end)
|