fixed bugs, organized code, prevented other bugs

master
MisterE123 2021-02-01 13:16:19 -05:00
parent 3a0350daad
commit 5d8de72f52
20 changed files with 960 additions and 786 deletions

View File

@ -6,3 +6,60 @@ Eat colorpoints to grow, be the last and the longest! Beat the Highscore!
![](screenshot.png)
Contributors: MisterE
Wormball mod by MisterE for use with arena_lib (minigame_lib) You should be familiar with how to set up arena_lib arenas.
Code snippets from https://gitlab.com/zughy-friends-minetest/arena_lib/-/blob/master/DOCS.md and from Zughy's minigames
all assets cc0. Models by MisterE, textures by MisterE, and sounds CC0 from opengameart
to set up an arena, create a completely enclosed arena out of any nodes you wish except those provided by this mod.
You should place lights in the walls, or have glass to allow light in. In this version, you can have any shape arena you like.
You may decorate the walls how you wish. Keep in mind that very large arenas may cause server lag during loading, and they are in general not fun to play in anyways.
Make the arena,
THEN note 2 position that bound your arena.... The game will place powerups and erase game peices within these locations.
enter these locations in the editor settings (described below)
Basic setup:
1) type /wormball create <arena_name>
2) type /wormball edit <arena_name>
3) use the editor to place a minigame sign, assign it to your minigame.
4) while in the editor, move to where your arena will be.
5) Make your arena. It should be a completely enclosed area, but can be any shape.
6) using the editor tools, mark player spawner locations. Protect the arena.
7) note to locations of 2 positions that completely bound the arena. From the minigame editor, go to settings > arena_settings.
8) type in the locations of the 2 opposite corners. Click on area_to_clear_after_game_pos1 and enter the correct values. then do the same with pos2.
CAUTION: in the arena_settings, Y COMES FIRST! In the regular coordinate system, X COMES FIRST! Type the CORRECT values in... if you get it wrong, you may freeze your world and cause damage to it.
BE CAREFUL TO GET THE CORRECT VALUES!!!!! also, if you get them wrong, the game will not work... the game tries to clear that when it loads, if you get it wrong, then it will clear the wrong area.
If you wish, you may change the other settings (except high_scores)
the formula used to determine whether to start erasing powerup dots is:
if # dots in existence > min_food_factor * #players + min_food then
--have a 1/2 chance to erase a dot
end
9) exit the editor mode
10) type /minigamesettings wormball
11) change the hub spawnpoint to be next to the signs.
background music is available: it is in the sounds folder, and titled: wormball_bgm

View File

@ -42,6 +42,7 @@ end, {
- create <arena name> [min players] [max players]
- edit <arena name>
- enable <arena name>
- list -- show created arenas
Other commands:
- remove <arena name>

192
globals.lua Normal file
View File

@ -0,0 +1,192 @@
wormball.player_texture_save = {}
--lookup tables
--colors: a list of color codes, indexed by name
wormball.colors = {yellow = "fcba0388",
orangered = "fc280388",
darkred = "a1000088",
lightgreen = "80ff0088",
aqua = "00ff8488",
lightblue = "0084ff88",
darkblue = "0d00ff88",
purple = "8000ff88",
lightpurple = "ee00ff88",
pink = "ff006f88"}
--color_names: a list of color names, indexed by number
wormball.color_names = {}
local i=1
for color,code in pairs(wormball.colors) do
wormball.color_names[i] = color
i=i+1
end
--reference tables for placing node rotations properly
wormball.straight = {pxpx = 1,pzpz=0,pypy=4,
nxnx = 1,nznz=0,nyny=4,
nxpx = 1,nzpz=0,nypy=4,
pxnx = 1,pznz=0,pyny=4, } --format: axis
--format: sign,axis to sign,axis
wormball.corner = { --from, to
nynx=13,pynx=15,pznx=12,
nypz=10,pypz=2,pzpx=7,
nypx=21,pypx=17,nzpx=11,
nynz=20,pynz=0 ,nznx=9,
nxny=17,nxpy=19,nxpz=18,
pzny=0,pzpy=20,pxpz=9,
pxny=15,pxpy=13,pxnz=12,
nzny=2,nzpy=10 ,nxnz=7,
}
--format: dir pitch(h,u,d)for horiz, up or down ; dir facing
wormball.head = {
hpz=0,hpx=1,hnz=2,hnx=3,
dpz=4,dpx=13,dnz=10,dnx=19,
upz=8,upx=17,unz=6,unx=15,}
-- timer: a counter for keeping track of global step stuff
wormball.timer = 0
--place_node: a custom function for placing the head and second segment every movement. Uses rotation lookup tables above
--when I do a place_node, I place the head in the facing dir and the pitch, and I update where the head (last )
function wormball.place_node(nodes,dir,old_dir,look_dir,color) --dir should be:{x=1[-1],y=1[-1],z=1[-1]}
--lookdir should be: 'px','nx','pz',or 'nz'
if not look_dir then look_dir = 'py' end
local dircode =''
local old_dircode=''
local type = 'straight' --type will be: straight, corner
local axis = ''
local old_axis = ''
--dircode should ALWAYS be set, unless for some reason dir = {0,0,0}, which it shouldnt. Check this
if dir.x ~= 0 then
axis = 'x'
if dir.x > 0 then
dircode = 'px'
else
dircode = 'nx'
end
elseif dir.y ~= 0 then
axis = 'y'
if dir.y >0 then
dircode = 'py'
else
dircode = 'ny'
end
elseif dir.z ~= 0 then
axis = 'z'
if dir.z > 0 then
dircode = 'pz'
else
dircode = 'nz'
end
end
if old_dir then
if old_dir.x ~= 0 then
old_axis = 'x'
if old_dir.x > 0 then
old_dircode = 'px'
else
old_dircode = 'nx'
end
elseif old_dir.y ~= 0 then
old_axis = 'y'
if old_dir.y > 0 then
old_dircode = 'py'
else
old_dircode = 'ny'
end
elseif old_dir.z ~= 0 then
old_axis = 'z'
if old_dir.z > 0 then
old_dircode = 'pz'
else
old_dircode = 'nz'
end
end
if axis == old_axis then
type = 'straight'
else
type = 'corner'
end
local full_dircode = old_dircode..dircode --from dir..to dir
if type == 'straight' and #nodes > 1 then
minetest.set_node(nodes[2], {name="wormball:straight_"..color, param2 = wormball.straight[full_dircode]})
elseif type == 'corner' and #nodes > 1 then
minetest.set_node(nodes[2], {name="wormball:corner_"..color, param2 = wormball.corner[full_dircode]})
end
end
local p_dir = 'h' --p, for pitch
if dir.y == 1 then
p_dir = 'u'
elseif dir.y == -1 then
p_dir = 'd'
end
local head_dir = p_dir..look_dir
minetest.set_node(nodes[1], {name="wormball:head_"..color, param2 = wormball.head[head_dir]})
end
--get_look_dir: a custom function that returns a simplified player look direction in the form of a direction code, that place_node uses
function wormball.get_look_dir(arena,player)
local yaw = player:get_look_horizontal()
local look_dir
--get look_dir
if yaw < (3.14*.25) or yaw > (3.14 *(7/4)) then -- if we are looking in the +z direction,
look_dir = 'pz'
elseif yaw > (3.14*(1/4)) and yaw < (3.14 *(3/4)) then -- if we are looking in the -x direction
look_dir = 'nx'
elseif yaw > (3.14*(3/4)) and yaw < (3.14 *(5/4)) then -- if we are looking in the -z direction
look_dir = 'nz'
elseif yaw > (3.14*(5/4)) and yaw < (3.14 *(7/4)) then -- if we are looking in the +x direction
look_dir = 'px'
end
return look_dir
end
-- detaches player, resets texture
wormball.detach = function(p_name)
local player = minetest.get_player_by_name(p_name) or nil
--set texture back to normal... dont worry about disconnects... player_api handles setting textures on_join
if player and wormball.player_texture_save[p_name] ~= nil then --nil checks
player:set_properties({textures = wormball.player_texture_save[p_name]})
end
--detach and remove attachment entity, play losing sound
if player then
local att = player:get_attach()
player:set_detach()
if att then att:remove() end
end
end

View File

@ -1,18 +1,5 @@
wormball = {}
--lookup tables
wormball.colors = {yellow = "fcba0388",
orangered = "fc280388",
darkred = "a1000088",
lightgreen = "80ff0088",
aqua = "00ff8488",
lightblue = "0084ff88",
darkblue = "0d00ff88",
purple = "8000ff88",
lightpurple = "ee00ff88",
pink = "ff006f88"}
dofile(minetest.get_modpath("wormball") .. "/globals.lua")
arena_lib.register_minigame("wormball", {
prefix = "[Wormball] ",
@ -25,8 +12,8 @@ wormball.colors = {yellow = "fcba0388",
join_while_in_progress = false,
keep_inventory = false,
in_game_physics = {
speed = 2,
jump = 3,
speed = 0,
jump = 0,
sneak = false,
gravity = 1,
},
@ -73,6 +60,7 @@ wormball.colors = {yellow = "fcba0388",
apple = false,
--textures= {},
move = true,
attached = false,
},
})
@ -82,7 +70,9 @@ if not minetest.get_modpath("lib_chatcmdbuilder") then
end
dofile(minetest.get_modpath("wormball") .. "/commands.lua")
dofile(minetest.get_modpath("wormball") .. "/minigame_manager.lua")
dofile(minetest.get_modpath("wormball") .. "/nodes.lua")
dofile(minetest.get_modpath("wormball") .. "/privs.lua")
dofile(minetest.get_modpath("wormball") .. "/minigame_manager.lua")

View File

@ -1,762 +1,25 @@
--todo:
--make it only delete wormball nodes in clear area, so unusual shape arenas are possible. --done
--bgm --available (..wormball/sounds/wormball_bgm)
--colorize chat messages --kinda done
--timer hud --done
--highscores --kinda done, needs rework
wormball.player_texture_save = {}
--all files are in the minigame_manager folder
wormball.straight = {pxpx = 1,pzpz=0,pypy=4,
nxnx = 1,nznz=0,nyny=4,
nxpx = 1,nzpz=0,nypy=4,
pxnx = 1,pznz=0,pyny=4, } --format: axis
--format: sign,axis to sign,axis
wormball.corner = { --from, to
nynx=13,pynx=15,pznx=12,
nypz=10,pypz=2,pzpx=7,
nypx=21,pypx=17,nzpx=11,
nynz=20,pynz=0 ,nznx=9,
dofile(minetest.get_modpath("wormball") .. "/minigame_manager/on_load.lua")
nxny=17,nxpy=19,nxpz=18,
pzny=0,pzpy=20,pxpz=9,
pxny=15,pxpy=13,pxnz=12,
nzny=2,nzpy=10 ,nxnz=7,
}
--format: dir pitch(h,u,d)for horiz, up or down ; dir facing
wormball.head = {
hpz=0,hpx=1,hnz=2,hnx=3,
dpz=4,dpx=13,dnz=10,dnx=19,
upz=8,upx=17,unz=6,unx=15,}
dofile(minetest.get_modpath("wormball") .. "/minigame_manager/on_start.lua")
dofile(minetest.get_modpath("wormball") .. "/minigame_manager/on_time_tick.lua")
dofile(minetest.get_modpath("wormball") .. "/minigame_manager/globalstep.lua")
--when I do a place_node, I place the head in the facing dir and the pitch, and I update where the head (last )
function wormball.place_node(nodes,dir,old_dir,look_dir,color) --dir should be:{x=1[-1],y=1[-1],z=1[-1]}
--lookdir should be: 'px','nx','pz',or 'nz'
if not look_dir then look_dir = 'py' end
local dircode =''
local old_dircode=''
local type = 'straight' --type will be: straight, corner
dofile(minetest.get_modpath("wormball") .. "/minigame_manager/on_eliminate.lua")
local axis = ''
local old_axis = ''
dofile(minetest.get_modpath("wormball") .. "/minigame_manager/on_timeout.lua")
dofile(minetest.get_modpath("wormball") .. "/minigame_manager/on_disconnect.lua")
--dircode should ALWAYS be set, unless for some reason dir = {0,0,0}, which it shouldnt. Check this
if dir.x ~= 0 then
axis = 'x'
if dir.x > 0 then
dircode = 'px'
else
dircode = 'nx'
end
elseif dir.y ~= 0 then
axis = 'y'
if dir.y >0 then
dircode = 'py'
else
dircode = 'ny'
end
elseif dir.z ~= 0 then
axis = 'z'
if dir.z > 0 then
dircode = 'pz'
else
dircode = 'nz'
end
end
if old_dir then
if old_dir.x ~= 0 then
old_axis = 'x'
if old_dir.x > 0 then
old_dircode = 'px'
else
old_dircode = 'nx'
end
elseif old_dir.y ~= 0 then
old_axis = 'y'
if old_dir.y > 0 then
old_dircode = 'py'
else
old_dircode = 'ny'
end
elseif old_dir.z ~= 0 then
old_axis = 'z'
if old_dir.z > 0 then
old_dircode = 'pz'
else
old_dircode = 'nz'
end
end
dofile(minetest.get_modpath("wormball") .. "/minigame_manager/on_celebration.lua")
if axis == old_axis then
type = 'straight'
else
type = 'corner'
end
local full_dircode = old_dircode..dircode --from dir..to dir
if type == 'straight' and #nodes > 1 then
minetest.set_node(nodes[2], {name="wormball:straight_"..color, param2 = wormball.straight[full_dircode]})
elseif type == 'corner' and #nodes > 1 then
minetest.set_node(nodes[2], {name="wormball:corner_"..color, param2 = wormball.corner[full_dircode]})
end
end
local p_dir = 'h' --p, for pitch
if dir.y == 1 then
p_dir = 'u'
elseif dir.y == -1 then
p_dir = 'd'
end
local head_dir = p_dir..look_dir
minetest.set_node(nodes[1], {name="wormball:head_"..color, param2 = wormball.head[head_dir]})
end
function wormball.get_look_dir(arena,player)
local yaw = player:get_look_horizontal()
local look_dir
--get look_dir
if yaw < (3.14*.25) or yaw > (3.14 *(7/4)) then -- if we are looking in the +z direction,
look_dir = 'pz'
elseif yaw > (3.14*(1/4)) and yaw < (3.14 *(3/4)) then -- if we are looking in the -x direction
look_dir = 'nx'
elseif yaw > (3.14*(3/4)) and yaw < (3.14 *(5/4)) then -- if we are looking in the -z direction
look_dir = 'nz'
elseif yaw > (3.14*(5/4)) and yaw < (3.14 *(7/4)) then -- if we are looking in the +x direction
look_dir = 'px'
end
return look_dir
end
local function send_message(arena,num_str)
arena_lib.HUD_send_msg_all("title", arena, "Game Begins In "..num_str, 1,nil,0xFF0000)
--arena_lib.HUD_send_msg_all(HUD_type, arena, msg, <duration>, <sound>, <color>)
end
arena_lib.on_load("wormball", function(arena)
local c = 0
for pl_name, stats in pairs(arena.players) do
c =c +1
end
arena.num_players = c
send_message(arena,'5')
minetest.after(1, function(arena)
send_message(arena,'4')
minetest.after(1, function(arena)
send_message(arena,'3')
minetest.after(1, function(arena)
send_message(arena,'2')
minetest.after(1, function(arena)
send_message(arena,'1')
minetest.after(1, function(arena)
arena_lib.HUD_send_msg_all("title", arena, "GO!", 1,nil,0x00FF00)
minetest.after(1, function(arena)
arena_lib.HUD_send_msg_all("hotbar", arena, "Avoid Your Own Color, eat other dots!", 5,nil,0xFFAE00)
end, arena)
end, arena)
end, arena)
end, arena)
end, arena)
end, arena)
--clear the board of gamepieces
local pos1 = arena.area_to_clear_after_game_pos_1
local pos2 = arena.area_to_clear_after_game_pos_2
local x1 = pos1.x
local x2 = pos2.x
local y1 = pos1.y
local y2 = pos2.y
local z1 = pos1.z
local z2 = pos2.z
if x1 > x2 then
local temp = x2
x2 = x1
x1 = temp
end
if y1 > y2 then
local temp = y2
y2 = y1
y1 = temp
end
if z1 > z2 then
local temp = z2
z2 = z1
z1 = temp
end
for x = x1,x2 do
for y = y1,y2 do
for z = z1,z2 do
local nodename = minetest.get_node({x=x,y=y,z=z}).name
if string.find(nodename,'wormball') then
minetest.set_node({x=x,y=y,z=z}, {name="air"})
end
end
end
end
local color_assign = {} -- a table of color names idxed by number
local idx = 1
for name,color in pairs(wormball.colors) do
color_assign[idx] = name
idx = idx + 1
end
idx = 1
for pl_name, stats in pairs(arena.players) do
local message = 'Controls: Use look direction to steer, or press jump or sneak to move. Dont bump anything! Eat dots to grow and get points, but your own color will shrink you!'
minetest.chat_send_player(pl_name,message)
local player = minetest.get_player_by_name(pl_name)
player:set_velocity({x=0,y=0,z=0})
local pos = player:get_pos()
local color = color_assign[idx]
wormball.player_texture_save[pl_name] = player:get_properties().textures
arena.players[pl_name].color = color
player:set_properties({textures = {'wormball_alpha.png'}})
arena.players[pl_name].nodes = {pos}
local look_dir = wormball.get_look_dir(arena,player)
wormball.place_node(arena.players[pl_name].nodes ,{x=0,y=1,z=0},{x=0,y=1,z=0},look_dir,color)
local att = minetest.add_entity(pos, 'wormball:player_att')
-- if att then minetest.chat_send_all('ent spawned!')
-- else minetest.chat_send_all('ent not spawned!') end
player:set_attach(att, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
player_api.player_attached[pl_name] = true
--player:set_eye_offset(eye_offset, {x=0, y=0, z=0})
-- local att = minetest.add_entity(pos, 'wormball:player_att')
-- --player_api.player_attached[pl_name] = true
-- player:set_attach(att, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
if idx > 1 then
arena.mode = 'multiplayer'
end
idx = idx + 1
end
end)
arena_lib.on_time_tick('wormball', function(arena)
local c = 0x00FF00
if arena.current_time < 60 then
c = 0xFFFF00
end
if arena.current_time < 10 then
c = 0xFF0000
end
if arena.current_time < arena.initial_time - 5 then
arena_lib.HUD_send_msg_all('hotbar', arena, 'T - '..arena.current_time, 1,nil,c)
end
local p1 = arena.area_to_clear_after_game_pos_1
local p2 = arena.area_to_clear_after_game_pos_2
local x1 = p1.x
local x2 = p2.x
local y1 = p1.y
local y2 = p2.y
local z1 = p1.z
local z2 = p2.z
if x2 < x1 then
local temp = x2
x2 = x1
x1 = temp
end
if y2 < y1 then
local temp = y2
y2 = y1
y1 = temp
end
if z2 < z1 then
local temp = z2
z2 = z1
z1 = temp
end
local color_table = {}
local i=1
for color,code in pairs(wormball.colors) do
color_table[i] = color
i=i+1
end
local num_players = 0
for pl_name,stats in pairs(arena.players) do
num_players = num_players +1
end
local remove = false
if #arena.dots and #arena.dots> arena.min_food_factor * num_players + arena.min_food then
remove = true
end
for pl_name,stats in pairs(arena.players) do
local rand_pos = {x = math.random(x1,x2),y = math.random(y1,y2), z=math.random(z1,z2)}
local item = 'none'
if math.random(1,3)== 1 then
local color = color_table[math.random(1,#color_table)]
item = "wormball:power_"..color
end
--put other powerups here, with lower chances
if item ~= 'none' then
if minetest.get_node(rand_pos).name == 'air' then
minetest.set_node(rand_pos, {name=item})
table.insert(arena.dots,rand_pos)
end
end
if remove then
if math.random(1,2) == 1 then
rem_pos = table.remove(arena.dots,math.random(4,#arena.dots))
minetest.set_node(rem_pos, {name="air"})
end
end
end
return
end)
wormball.timer = 0
minetest.register_globalstep(function(dtime)
--if wormball.timer then wormball.timer = 0 end
for _,player in ipairs(minetest.get_connected_players()) do
local pl_name = player:get_player_name()
if arena_lib.is_player_in_arena(pl_name, "wormball") then
local arena = arena_lib.get_arena_by_player(pl_name)
if not(arena.in_queue == true) and not (arena.in_loading == true) and not(arena.in_celebration == true) and arena.enabled == true then
local stats = arena.players[pl_name]
if stats.alive == true then
if not player:get_attach() then
local pos_head = arena.players[pl_name].nodes[1]
local att = minetest.add_entity(pos_head, 'wormball:player_att')
player:set_attach(att, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
end
end
end
end
end
wormball.timer = wormball.timer+dtime
if wormball.timer < .4 then return
end
wormball.timer = 0
for _,player in ipairs(minetest.get_connected_players()) do
local pl_name = player:get_player_name()
if arena_lib.is_player_in_arena(pl_name, "wormball") then
local arena = arena_lib.get_arena_by_player(pl_name)
if not(arena.in_queue == true) and not (arena.in_loading == true) and not(arena.in_celebration == true) and arena.enabled == true then
local stats = arena.players[pl_name]
local remove_tail = true
local color = stats.color
if stats.alive == true then
-- if not player:get_attach() then
-- local pos_head = arena.players[pl_name].nodes[1]
-- local att = minetest.add_entity(pos_head, 'wormball:player_att')
-- player:set_attach(att, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
-- end
local old_dir = arena.players[pl_name].old_direction or {x=0,y=1,z=0} --grab the old_dir info before its updated
local player = minetest.get_player_by_name(pl_name)
-- local color = stats.color
local look_dir = ''
--+x is forward, +z is left
local control = player:get_player_control() --{jump=bool, right=bool, left=bool, LMB=bool, RMB=bool, sneak=bool, aux1=bool, down=bool, up=bool}
local yaw = player:get_look_horizontal()
local look_dir = wormball.get_look_dir(arena,player)
if control.jump == true then
arena.players[pl_name].direction = {x=0,y=1,z=0}
elseif control.sneak == true then
arena.players[pl_name].direction = {x=0,y=-1,z=0}
elseif look_dir == 'pz' then -- if we are looking in the +z direction,
arena.players[pl_name].direction = {x=0,y=0,z=1}
elseif look_dir == 'nx' then -- if we are looking in the -x direction
arena.players[pl_name].direction = {x=-1,y=0,z=0}
elseif look_dir == 'nz' then -- if we are looking in the -z direction
arena.players[pl_name].direction = {x=0,y=0,z=-1}
elseif look_dir == 'px' then -- if we are looking in the +x direction
arena.players[pl_name].direction = {x=1,y=0,z=0}
end
--save the direction info for next round
arena.players[pl_name].old_direction = arena.players[pl_name].direction
--get look_dir
local new_move = stats.direction
local head_pos = stats.nodes[1]
local new_pos = {x = head_pos.x + new_move.x, y = head_pos.y + new_move.y, z = head_pos.z + new_move.z}
local new_node = minetest.get_node(new_pos).name
if new_node == 'air' then
if arena.players[pl_name].move == true then
table.insert(arena.players[pl_name].nodes,1,new_pos)
--minetest.set_node(new_pos, {name="wormball:node_"..color})
wormball.place_node(arena.players[pl_name].nodes,arena.players[pl_name].direction,old_dir,look_dir,color)
--player:move_to(new_pos, true)
local att = player:get_attach()
if att then
att:move_to(new_pos, true)
else
--minetest.chat_send_all('not_attached!')
end
else
arena.players[pl_name].move = true
end
elseif new_node == "wormball:power_"..color then --oops, hit own color, remove 1 length
for _,dot in pairs(arena.dots) do
if dot == new_pos then
table.remove(arena.dots,_)
end
end
if arena.players[pl_name].move == true then
table.insert(arena.players[pl_name].nodes,1,new_pos)
--minetest.set_node(new_pos, {name="wormball:node_"..color})
wormball.place_node(arena.players[pl_name].nodes,arena.players[pl_name].direction,old_dir,look_dir,color)
arena.players[pl_name].score = arena.players[pl_name].score - 1
--minetest.chat_send_player(pl_name,'YUCK! You Lost a point.')
--minetest.chat_send_all('bad!')
arena_lib.HUD_send_msg('broadcast', pl_name, 'YUCK! You Lost a point.', 2, 'wormball_yuck',0xFF0000)
local att = player:get_attach()
if att then
att:move_to(new_pos, true)
else
--minetest.chat_send_all('not_attached!')
end
else
arena.players[pl_name].move = true
end
remove_tail = true
arena.players[pl_name].move = false
elseif string.find(new_node,'wormball:power_') then --we found a powerup!
for _,dot_pos in pairs(arena.dots) do
if dot_pos == new_pos then
table.remove(arena.dots,_)
end
end
if arena.players[pl_name].move == true then
remove_tail = false
table.insert(arena.players[pl_name].nodes,1,new_pos)
--minetest.set_node(new_pos, {name="wormball:node_"..color})
wormball.place_node(arena.players[pl_name].nodes,arena.players[pl_name].direction,old_dir,look_dir,color)
arena.players[pl_name].score = arena.players[pl_name].score + 1
--minetest.chat_send_player(pl_name,'You are now '..arena.players[pl_name].score..' long.')
arena_lib.HUD_send_msg('broadcast', pl_name, 'Yay! You are now '..arena.players[pl_name].score..' long.', 2, 'wormball_powerup',0x00FF11)
local att = player:get_attach()
if att then
att:move_to(new_pos, true)
else
--minetest.chat_send_all('not_attached!')
end
else
arena.players[pl_name].move = true
end
else --we have run into something
arena.players[pl_name].alive = false
minetest.sound_play('sumo_lose', {
to_player = pl_name,
gain = 2.0,
})
local n = 0
for name, stat in pairs(arena.players) do
n = n+1
end
if n == 1 then
minetest.chat_send_player(pl_name,'your score is '..arena.players[pl_name].score)
--disengage before removing player
if player then
player:set_properties({textures = wormball.player_texture_save[pl_name]})
local att = player:get_attach()
--minetest.chat_send_all('ln517')
player:set_detach()
player_api.player_attached[pl_name] = false
if att then att:remove() end
minetest.sound_play(sound, {
to_player = p_name,
gain = 2.0,
})
end
arena.players[pl_name].alive = false
minetest.after(1, function(pl_name)
arena_lib.remove_player_from_arena(pl_name, 1)
end,pl_name)
--return
end
end
--place an apple
end
if remove_tail == true then
local len = #arena.players[pl_name].nodes
local tail_pos = arena.players[pl_name].nodes[len]
if tail_pos then
if arena.players[pl_name].alive == false then
item = "wormball:power_"..color
minetest.set_node(tail_pos, {name=item})
else
minetest.set_node(tail_pos, {name="air"})
end
table.remove(arena.players[pl_name].nodes,len)
end
end
if #arena.players[pl_name].nodes == 0 then
minetest.chat_send_player(pl_name, 'Your score is '..arena.players[pl_name].score)
arena.players[pl_name].alive = false
local player = minetest.get_player_by_name(pl_name)
if player then
player:set_properties({textures = wormball.player_texture_save[pl_name]})
local att = player:get_attach()
--minetest.chat_send_all('ln566')
player:set_detach()
player_api.player_attached[pl_name] = false
if att then att:remove() end
minetest.sound_play(sound, {
to_player = p_name,
gain = 2.0,
})
end
arena.players[pl_name].alive = false
minetest.after(1, function(pl_name)
arena_lib.remove_player_from_arena(pl_name, 1)
end,pl_name)
end
end
end
end
end)
arena_lib.on_eliminate('wormball', function(arena, p_name)
--minetest.chat_send_all(dump(arena))
local count = 0
local sound = 'sumo_elim'
local win_player = nil
for p_name,data in pairs(arena.players) do
count = count + 1
win_player = p_name
end
if count == 1 then
sound = 'sumo_win'
end
if arena.mode == 'multiplayer' and count == 1 then
if win_player then
win_player_obj = minetest.get_player_by_name(win_player)
win_player_obj:set_properties({textures = wormball.player_texture_save[win_player]})
minetest.after(1,function(arena,win_player)
arena_lib.load_celebration('wormball', arena, win_player)
end,arena,win_player)
local att = win_player_obj:get_attach()
--minetest.chat_send_all('ln627')
win_player_obj:set_detach()
player_api.player_attached[win_player] = false
if att then att:remove() end
end
end
local player = minetest.get_player_by_name(p_name) or nil
-- if player then
-- --minetest.chat_send_all('player_textures is: '..dump(arena.players[p_name].textures))
-- player:set_properties({textures = wormball.player_texture_save[p_name]})
-- local att = player:get_attach()
-- player:set_detach()
-- if att then att:remove() end
-- end
for p_name, stats in pairs(arena.players) do
minetest.sound_play(sound, {
to_player = p_name,
gain = 2.0,
})
end
end)
arena_lib.on_disconnect('wormball', function(arena, p_name)
local player = minetest.get_player_by_name(p_name)
if player then
player:set_properties({textures = wormball.player_texture_save[p_name]})
local att = player:get_attach()
--player_api.player_attached[p_name] = false
--minetest.chat_send_all('ln664')
player:set_detach()
if att then att:remove() end
end
end)
arena_lib.on_timeout('wormball', function(arena)
local winner = {0,''}
for pl_name, stats in pairs(arena.players) do
if arena.players[pl_name].score > winner[1] then
winner[1] = arena.players[pl_name].score
winner[2] = pl_name
end
end
arena_lib.load_celebration('wormball', arena, winner[2])
end)
arena_lib.on_celebration('wormball', function(arena, winner_name)
for pl_name,stats in pairs(arena.players) do
local player = minetest.get_player_by_name(pl_name)
if player then
player:set_properties({textures = wormball.player_texture_save[pl_name]})
local att = player:get_attach()
--minetest.chat_send_all('ln693')
player:set_detach()
player_api.player_attached[pl_name] = false
if att then att:remove() end
end
end
if type(winner_name) == 'string' then
local highscore_tbl = {'highscore_1','highscore_2','highscore_3','highscore_4','highscore_5','highscore_6','highscore_7','highscore_8','highscore_9','highscore_10',}
local highscore = arena.highscores[arena.num_players]
local high_name = highscore[1] or ''
local high_num = highscore[2] or 0
local winner_pts = arena.players[winner_name].score
arena_lib.HUD_send_msg_all("title", arena, winner_name..' won with '..winner_pts.. ' pts!', 9,'sumo_win',0xAEAE00)
arena_lib.HUD_send_msg_all("hotbar", arena, 'Highscore: '..high_name.. ' '..high_num, 9,nil,0x0000FF)
if high_num < winner_pts then
arena.highscores[arena.num_players] = {winner_name,winner_pts}
minetest.after(2,function(arena,winner_name,winner_pts)
arena_lib.HUD_send_msg_all("title", arena, 'NEW HIGH SCORE '.. arena.num_players ..' PLAYER!', 7,'sumo_win',0xAEAE00)
arena_lib.HUD_send_msg_all("hotbar", arena, 'Highscore: '..winner_name.. ' '..winner_pts, 7,nil,0x0000FF)
end,arena,winner_name,winner_pts)
end
end
end)

View File

@ -0,0 +1,341 @@
--this minigame has a globalstep to update the board, because the arena_lib on_time_tick
--is too slow for the fast-paced nature of snake. However, lag has been tested to be low
--(please confirm as needed)
minetest.register_globalstep(function(dtime)
--every server_step, check if the players in-game are attached to their worm heads. Iff they are not, then spawn a new entity and attach them
--note, the entities have a 10 min timeout (wormball games last 5 min). A MT 5.3 engine bug can detach players unexpectedly, this is a workaround.
for _,player in ipairs(minetest.get_connected_players()) do
local pl_name = player:get_player_name()
if arena_lib.is_player_in_arena(pl_name, "wormball") then
local arena = arena_lib.get_arena_by_player(pl_name)
if not(arena.in_queue == true) and not (arena.in_loading == true) and not(arena.in_celebration == true) and arena.enabled == true then
local stats = arena.players[pl_name]
if stats.alive == true then
if not player:get_attach() then
local pos_head = arena.players[pl_name].nodes[1]
local att = minetest.add_entity(pos_head, 'wormball:player_att')
player:set_attach(att, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
end
end
end
end
end
--we will only run worm movement code about every 0.4 seconds, if not 0.4 seconds yet; return
wormball.timer = wormball.timer+dtime
if wormball.timer < .4 then return
end
--reset the timer
wormball.timer = 0
--because this is a global callback, I have to get the name from the player, and the arena from the name, and check that the
--arena is in-game before doing anything
--check all connected players
for _,player in ipairs(minetest.get_connected_players()) do
local pl_name = player:get_player_name()
--only mess with stuff if they are in the wormball minigame
if arena_lib.is_player_in_arena(pl_name, "wormball") then
local arena = arena_lib.get_arena_by_player(pl_name)
--only mess with stuff if the arena is in-game, add they are supposed to be attached
if not(arena.in_queue == true) and not (arena.in_loading == true) and not(arena.in_celebration == true) and arena.enabled == true and arena.players[pl_name].attached == true then
----------------------------------------------
---- mimic the normal for pl_name, stats ----
----------------------------------------------
local stats = arena.players[pl_name]
local color = stats.color
local remove_tail = true
-- if players are alive, move the worms (add to the length, subtract from the tail)
if stats.alive == true then
local old_dir = arena.players[pl_name].old_direction or {x=0,y=1,z=0} --grab the old_dir info before its updated
local player = minetest.get_player_by_name(pl_name)
local control = player:get_player_control() --ref: {jump=bool, right=bool, left=bool, LMB=bool, RMB=bool, sneak=bool, aux1=bool, down=bool, up=bool}
local look_dir = wormball.get_look_dir(arena,player) --in globals file; returns a string, one of: px, nx, pz, nz for the approximation of player look direction
--get player direction from current input, first check up or down, then look direction
if control.jump == true then --if we are going up
arena.players[pl_name].direction = {x=0,y=1,z=0}
elseif control.sneak == true then --if we are going down
arena.players[pl_name].direction = {x=0,y=-1,z=0}
elseif look_dir == 'pz' then -- if we are looking in the +z direction,
arena.players[pl_name].direction = {x=0,y=0,z=1}
elseif look_dir == 'nx' then -- if we are looking in the -x direction
arena.players[pl_name].direction = {x=-1,y=0,z=0}
elseif look_dir == 'nz' then -- if we are looking in the -z direction
arena.players[pl_name].direction = {x=0,y=0,z=-1}
elseif look_dir == 'px' then -- if we are looking in the +x direction
arena.players[pl_name].direction = {x=1,y=0,z=0}
end
--save the direction info for next round
arena.players[pl_name].old_direction = arena.players[pl_name].direction
-- localize the direction for easy reference
local new_move = stats.direction
--was:stats.direction
--stats.nodes is the positions of the worm body parts, idx 1 is the head
local head_pos = stats.nodes[1]
--get the new head pos, from the old pos and the new move pos
local new_pos = {x = head_pos.x + new_move.x, y = head_pos.y + new_move.y, z = head_pos.z + new_move.z}
--get the node at the tenative new head location.
local new_node = minetest.get_node(new_pos).name
----------------------------------------------
--- if the new node is air, move the head, delete the tail, length remains the same
--- if the new node is a powerup of a different color, move the head, but keep the tail, so the snake grows 1
--- if the new node is a powerup of the same color, set move to false, so the next round, the head will not be moved as the tail is deleted to shrink it
--- if the new node is none of the above, it is an obstacle, and the player loses
----------------------------------------------
--- note: if stats.move is set to false, then the next round, the head will not move, but move will be reset
--- note: if the local var remove_tail is true, then after checking the node, the tail is removed
-----------------
--- note: the function wormball.place_node is in the globals file, and performs the math to place the head and the
--- -- first body segment rotated according to the current and previous movement directions.
----------------------------------------------
--- note: we ALWAYS move forward, unless there is an arena obstacle. However, for the dots of the same color,
--- -- we do not move forward NEXT turn. This is so that dots are always *eaten*
----------------------------------------------
if new_node == 'air' then
if arena.players[pl_name].move == true then
-- place the head location into the player's body locations table
table.insert(arena.players[pl_name].nodes,1,new_pos)
--draw the head and the first body segment
wormball.place_node(arena.players[pl_name].nodes,arena.players[pl_name].direction,old_dir,look_dir,color)
--move the player's attached entity (use invisible entities so movements are smoother)
local att = player:get_attach()
--nil check
if att then
att:move_to(new_pos, true)
end
else
arena.players[pl_name].move = true
end
elseif new_node == "wormball:power_"..color then --oops, hit own color, remove 1 length
if arena.players[pl_name].move == true then
--delete the memory of the dot that was 'eaten'
for _,dot in pairs(arena.dots) do
if dot == new_pos then
table.remove(arena.dots,_)
end
end
-- place the head location into the player's body locations table
table.insert(arena.players[pl_name].nodes,1,new_pos)
--draw the head and the first body segment
wormball.place_node(arena.players[pl_name].nodes,arena.players[pl_name].direction,old_dir,look_dir,color)
--subtract 1 from the player's score
arena.players[pl_name].score = arena.players[pl_name].score - 1
--send an HUD message
arena_lib.HUD_send_msg('broadcast', pl_name, 'YUCK! You Lost a point.', 2, 'wormball_yuck',0xFF0000)
--move the player's attached entity
local att = player:get_attach()
if att then
att:move_to(new_pos, true)
end
--we will be removing the tail, to visually shorten the worm
remove_tail = true
--we will not be moving forward NEXT turn (after eating a same color dot)
arena.players[pl_name].move = false
else
arena.players[pl_name].move = true
end
elseif string.find(new_node,'wormball:power_') then --we found a powerup dot!
if arena.players[pl_name].move == true then
--delete the memory of the dot that was 'eaten'
for _,dot_pos in pairs(arena.dots) do
if dot_pos == new_pos then
table.remove(arena.dots,_)
end
end
-- place the head location into the player's body locations table
table.insert(arena.players[pl_name].nodes,1,new_pos)
--draw the head and the first body segment
wormball.place_node(arena.players[pl_name].nodes,arena.players[pl_name].direction,old_dir,look_dir,color)
-- add 1 to the player's score
arena.players[pl_name].score = arena.players[pl_name].score + 1
-- send HUD message
arena_lib.HUD_send_msg('broadcast', pl_name, 'Yay! You are now '..arena.players[pl_name].score..' long.', 2, 'wormball_powerup',0x00FF11)
--move the player's attached entity
local att = player:get_attach()
if att then
att:move_to(new_pos, true)
end
--we will be not removing the tail this round, we are growing
remove_tail = false
else
arena.players[pl_name].move = true
end
else --we have run into an arena obstacle, another snake, or ourselves
-- the player will no longer be alive. For the next few rounds, we may still be in-game,
-- as messages are displayed and our worm is converted back into food, but regular player
-- functions that rely on being alive will not run
arena.players[pl_name].alive = false --being dead, the player will lose a length every round until 0, and then they are eliminated. THey wont lose recorded pts tho
--play a losing sound
minetest.sound_play('sumo_lose', {
to_player = pl_name,
gain = 2.0,
})
--count how many players are left in the arena...
local n = 0
for name, stat in pairs(arena.players) do
n = n+1
end
-- if we are the only player in the arena, then load celebration... you lost, but you also won,
-- whether as a singleplayer of as a leader in multiplayer
-- although, really, this code will only ever run in singleplayer, since arena_lib automatically ends multiplayer arenas that have 1 player left
if n == 1 then
arena_lib.load_celebration('wormball', arena, pl_name)
return
end
end
end
----------------------------------------------------------------------------
--- the following code we run regardless of whether the player is alive or not
----------------------------------------------------------------------------
if remove_tail == true then --true by default, only false when having eaten a 'good' dot
local len = #arena.players[pl_name].nodes --worm length
local tail_pos = arena.players[pl_name].nodes[len] --position to change
if tail_pos then --nil check
-- if the player is dead, then we will slowly convert them into food (of their color)
-- if they are still alive, then we will place air there to delete the tail
if arena.players[pl_name].alive == false then
item = "wormball:power_"..color
minetest.set_node(tail_pos, {name=item})
else
minetest.set_node(tail_pos, {name="air"})
end
--forget the tail position in the player's body postions
table.remove(arena.players[pl_name].nodes,len)
end
end
-- if players have no nodes, eliminate them. (this can happen if they eat a 'bad' dot while only 1 long), and it always happens when
-- players crash, after all their nodes are converted into dots. This means that if 2 players crash soon between each other, but 1 has a
-- longer worm, that player will be eliminated after the player with the shorter worm.
if #arena.players[pl_name].nodes == 0 then
minetest.chat_send_player(pl_name, 'Your score is '..arena.players[pl_name].score)
arena.players[pl_name].alive = false --just to make sure
wormball.detach(pl_name)
arena_lib.remove_player_from_arena(pl_name, 1)
end
end
end
end
end)

View File

@ -0,0 +1,53 @@
arena_lib.on_celebration('wormball', function(arena, winner_name)
--reset player textures back to the texture they were... (wormball sets player textures to clear)
for pl_name,stats in pairs(arena.players) do
wormball.detach(pl_name)
end
--for now, arena_lib only supports single winners... change this when it supports multiple winners
if type(winner_name) == 'string' then
--Highscores are stored per number of players...
--in a crash report, highscore was nil... WHY!? #BUG
--crash (hopefully) prevented with nil check... place debug code here
--note: crash occured when arena edit mode was entered while arena had crashed due to another bug, and the arena was still active (in_celebration)
--note2: this will also prevent crashes due to arena editors messing with the highscores table.
local highscore = arena.highscores[arena.num_players]
if not highscore then --nil check
arena.highscores[arena.num_players] = {'pl_name_placeholder',0}
highscore = {'pl_name_placeholder',0}
end
--old highscore info if existing
local high_name = highscore[1] or ''
local high_num = highscore[2] or 0
--current winner pts
local winner_pts = arena.players[winner_name].score
--HUD info sent to players
arena_lib.HUD_send_msg_all("title", arena, winner_name..' won with '..winner_pts.. ' pts!', 9,'sumo_win',0xAEAE00)
arena_lib.HUD_send_msg_all("hotbar", arena, 'Highscore: '..high_name.. ' '..high_num, 9,nil,0x0000FF)
--if highscore was broken, 2 sec later, another HUD info abt that...
if high_num < winner_pts then
--set highscore info
arena.highscores[arena.num_players] = {winner_name,winner_pts} --could this have cause the bug?
minetest.after(2,function(arena,winner_name,winner_pts)
arena_lib.HUD_send_msg_all("title", arena, 'NEW HIGH SCORE '.. arena.num_players ..' PLAYER!', 7,'sumo_win',0xAEAE00)
arena_lib.HUD_send_msg_all("hotbar", arena, 'Highscore: '..winner_name.. ' '..winner_pts, 7,nil,0x0000FF)
end,arena,winner_name,winner_pts)
end
end
end)

View File

@ -0,0 +1,13 @@
--basic cleanup
arena_lib.on_disconnect('wormball', function(arena, p_name)
local player = minetest.get_player_by_name(p_name)
if player then
player:set_properties({textures = wormball.player_texture_save[p_name]})
local att = player:get_attach()
player:set_detach()
if att then att:remove() end
end
end)

View File

@ -0,0 +1,23 @@
arena_lib.on_eliminate('wormball', function(arena, p_name)
--play sound to remaining players
for pl_name, stats in pairs(arena.players) do
if pl_name ~= p_name then
minetest.sound_play('sumo_elim', {
to_player = pl_name,
gain = 2.0,
})
else
minetest.sound_play('sumo_lose', {
to_player = p_name,
gain = 2.0,
})
end
end
end)

View File

@ -0,0 +1,116 @@
local function send_message(arena,num_str)
arena_lib.HUD_send_msg_all("title", arena, "Game Begins In "..num_str, 1,nil,0xFF0000)
-- ref: arena_lib.HUD_send_msg_all(HUD_type, arena, msg, <duration>, <sound>, <color>)
end
arena_lib.on_load("wormball", function(arena)
--HUD countdown
send_message(arena,'5')
minetest.after(1, function(arena)
send_message(arena,'4')
minetest.after(1, function(arena)
send_message(arena,'3')
minetest.after(1, function(arena)
send_message(arena,'2')
minetest.after(1, function(arena)
send_message(arena,'1')
minetest.after(1, function(arena)
arena_lib.HUD_send_msg_all("title", arena, "GO!", 1,nil,0x00FF00)
minetest.after(1, function(arena)
arena_lib.HUD_send_msg_all("hotbar", arena, "Avoid Your Own Color, eat other dots!", 5,nil,0xFFAE00)
end, arena)
end, arena)
end, arena)
end, arena)
end, arena)
end, arena)
--clear the board of gamepieces
local pos1 = arena.area_to_clear_after_game_pos_1
local pos2 = arena.area_to_clear_after_game_pos_2
local x1 = pos1.x
local x2 = pos2.x
local y1 = pos1.y
local y2 = pos2.y
local z1 = pos1.z
local z2 = pos2.z
if x1 > x2 then
local temp = x2
x2 = x1
x1 = temp
end
if y1 > y2 then
local temp = y2
y2 = y1
y1 = temp
end
if z1 > z2 then
local temp = z2
z2 = z1
z1 = temp
end
for x = x1,x2 do
for y = y1,y2 do
for z = z1,z2 do
--only remove wormball-registered nodes
local nodename = minetest.get_node({x=x,y=y,z=z}).name
if string.find(nodename,'wormball') then
minetest.set_node({x=x,y=y,z=z}, {name="air"})
end
end
end
end
local idx = 1
for pl_name, stats in pairs(arena.players) do
--send control messages
local message = 'Controls: Use look direction to steer, or press jump or sneak to move. Dont bump anything!'
minetest.chat_send_player(pl_name,message)
local message = 'Eat dots to grow and get points, but your own color will shrink you!'
minetest.chat_send_player(pl_name,message)
local player = minetest.get_player_by_name(pl_name)
local pos = player:get_pos()
-- assign colors to players
arena.players[pl_name].color = wormball.color_names[idx]
--save players' textures so they can be made invisible
wormball.player_texture_save[pl_name] = player:get_properties().textures
--set their textures to invisible
player:set_properties({textures = {'wormball_alpha.png'}})
--set their first node (head) position
arena.players[pl_name].nodes = {pos}
local look_dir = wormball.get_look_dir(arena,player)
wormball.place_node( arena.players[pl_name].nodes , {x=0,y=1,z=0} , {x=0,y=1,z=0} , look_dir, arena.players[pl_name].color )
--determine whether it is singleplayer or multiplayer (singleplayer is set as default in arena temp props)
if idx > 1 then
arena.mode = 'multiplayer'
end
idx = idx + 1
end
end)

View File

@ -0,0 +1,22 @@
-- counting the initial number of players in the game has been moved to an on_start function because the highscore info
-- returned nil in a crash report. Perhaps not all players are accounted for in on_load. This ensures correct census info.
arena_lib.on_start('wormball', function(arena)
local c = 0
for pl_name, stats in pairs(arena.players) do
c =c +1
end
arena.num_players = c
-- set players' attachment entities
for pl_name, stats in pairs(arena.players) do
local player = minetest.get_player_by_name(pl_name)
local pos = player:get_pos()
local att = minetest.add_entity(pos, 'wormball:player_att')
player:set_attach(att, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
arena.players[pl_name].attached = true --indicates that the globalstep may take control; the player is supposed to be attached
end
end)

View File

@ -0,0 +1,112 @@
arena_lib.on_time_tick('wormball', function(arena)
----------------------------------------------
----------------------------------------------
-- send HUD with time, set color based on time left
----------------------------------------------
----------------------------------------------
local c = 0x00FF00
if arena.current_time < 60 then
c = 0xFFFF00
end
if arena.current_time < 10 then
c = 0xFF0000
end
if arena.current_time < arena.initial_time - 5 then
arena_lib.HUD_send_msg_all('hotbar', arena, 'TIME: '..arena.current_time, 1,nil,c)
end
----------------------------------------------
----------------------------------------------
-- set powerups within the arena ----------
----------------------------------------------
----------------------------------------------
-- get the arena area points from settings, order them
local p1 = arena.area_to_clear_after_game_pos_1
local p2 = arena.area_to_clear_after_game_pos_2
local x1 = p1.x
local x2 = p2.x
local y1 = p1.y
local y2 = p2.y
local z1 = p1.z
local z2 = p2.z
if x2 < x1 then
local temp = x2
x2 = x1
x1 = temp
end
if y2 < y1 then
local temp = y2
y2 = y1
y1 = temp
end
if z2 < z1 then
local temp = z2
z2 = z1
z1 = temp
end
--get a local table of color names
local color_table = wormball.color_names
--get current number of players
local num_players = 0
for pl_name,stats in pairs(arena.players) do
num_players = num_players +1
end
--decide whether to (have a chance of) removing dots
local remove = false
if #arena.dots and #arena.dots> arena.min_food_factor * num_players + arena.min_food then
remove = true
end
--add dots, with greater chance with more players
for pl_name,stats in pairs(arena.players) do
--random location within arena
local rand_pos = {x = math.random(x1,x2),y = math.random(y1,y2), z=math.random(z1,z2)}
local item = 'none'
--random chance to place random color
if math.random(1,3)== 1 then
local color = color_table[math.random(1,#color_table)]
item = "wormball:power_"..color
end
--if you want to place other nodes instead/also, set item here...
if item ~= 'none' then
if minetest.get_node(rand_pos).name == 'air' then --only place in air (not replace arena or worms or other powerups)
minetest.set_node(rand_pos, {name=item})
table.insert(arena.dots,rand_pos) --keep track of where powerups (dots) are
end
end
if remove then
--if there are enough powerups to remove some, have a 0.5 chance of removing them
if math.random(1,2) == 1 then
rem_pos = table.remove(arena.dots,math.random(4,#arena.dots)) --forget the pos of removed powerup
if not(string.find(minetest.get_node(rem_pos).name,"wormball:straight_"))
and not(string.find(minetest.get_node(rem_pos).name,"wormball:corner_"))
and not(string.find(minetest.get_node(rem_pos).name,"wormball:head_")) then
minetest.set_node(rem_pos, {name="air"})
end
end
end
end
end)

View File

@ -0,0 +1,14 @@
--as soon as arena_lib supports multiple winners, make this more fair.
arena_lib.on_timeout('wormball', function(arena)
local winner = {0,''}
for pl_name, stats in pairs(arena.players) do
if arena.players[pl_name].score > winner[1] then
winner[1] = arena.players[pl_name].score
winner[2] = pl_name
end
end
arena_lib.load_celebration('wormball', arena, winner[2])
end)

Binary file not shown.

Binary file not shown.

View File

@ -1,23 +0,0 @@
-- GENERATED CODE
-- Node Box Editor, version 0.9.0
-- Namespace: test
minetest.register_node("test:node_1", {
tiles = {
"wormball_straight.png",
"wormball_straight.png",
"wormball_end.png",
"wormball_end.png",
"wormball_straight.png",
"wormball_straight.png"
},
drawtype = "nodebox",
paramtype = "light",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.1875, -0.1875, 0.5, 0.1875, 0.1875}, -- NodeBox1
}
}
})

Binary file not shown.