diff --git a/README.md b/README.md index 4d5374a..44da62f 100644 --- a/README.md +++ b/README.md @@ -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 +2) type /wormball edit +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 + + + + + + + + + + + + diff --git a/corner.blend b/blender_files/corner.blend similarity index 100% rename from corner.blend rename to blender_files/corner.blend diff --git a/head.blend b/blender_files/head.blend similarity index 100% rename from head.blend rename to blender_files/head.blend diff --git a/power.blend b/blender_files/power.blend similarity index 100% rename from power.blend rename to blender_files/power.blend diff --git a/commands.lua b/commands.lua index fd98f7c..e896c1a 100644 --- a/commands.lua +++ b/commands.lua @@ -42,6 +42,7 @@ end, { - create [min players] [max players] - edit - enable + - list -- show created arenas Other commands: - remove diff --git a/globals.lua b/globals.lua new file mode 100644 index 0000000..17c9837 --- /dev/null +++ b/globals.lua @@ -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 diff --git a/init.lua b/init.lua index 95b0f07..5c23a12 100644 --- a/init.lua +++ b/init.lua @@ -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") + + diff --git a/minigame_manager.lua b/minigame_manager.lua index f3b75e5..ac1dad8 100644 --- a/minigame_manager.lua +++ b/minigame_manager.lua @@ -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, , , ) -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) diff --git a/minigame_manager/globalstep.lua b/minigame_manager/globalstep.lua new file mode 100644 index 0000000..6356cb5 --- /dev/null +++ b/minigame_manager/globalstep.lua @@ -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) + + + + + + + + diff --git a/minigame_manager/on_celebration.lua b/minigame_manager/on_celebration.lua new file mode 100644 index 0000000..d349750 --- /dev/null +++ b/minigame_manager/on_celebration.lua @@ -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) + + diff --git a/minigame_manager/on_disconnect.lua b/minigame_manager/on_disconnect.lua new file mode 100644 index 0000000..55d927c --- /dev/null +++ b/minigame_manager/on_disconnect.lua @@ -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) \ No newline at end of file diff --git a/minigame_manager/on_eliminate.lua b/minigame_manager/on_eliminate.lua new file mode 100644 index 0000000..90c4ac3 --- /dev/null +++ b/minigame_manager/on_eliminate.lua @@ -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) diff --git a/minigame_manager/on_load.lua b/minigame_manager/on_load.lua new file mode 100644 index 0000000..542d91f --- /dev/null +++ b/minigame_manager/on_load.lua @@ -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, , , ) +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) + diff --git a/minigame_manager/on_start.lua b/minigame_manager/on_start.lua new file mode 100644 index 0000000..f2a935a --- /dev/null +++ b/minigame_manager/on_start.lua @@ -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) \ No newline at end of file diff --git a/minigame_manager/on_time_tick.lua b/minigame_manager/on_time_tick.lua new file mode 100644 index 0000000..e0f7fcf --- /dev/null +++ b/minigame_manager/on_time_tick.lua @@ -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) + + + diff --git a/minigame_manager/on_timeout.lua b/minigame_manager/on_timeout.lua new file mode 100644 index 0000000..abcd6ae --- /dev/null +++ b/minigame_manager/on_timeout.lua @@ -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) + diff --git a/nodesdump/corner.b3d b/nodesdump/corner.b3d deleted file mode 100644 index 5586ca1..0000000 Binary files a/nodesdump/corner.b3d and /dev/null differ diff --git a/nodesdump/head.b3d b/nodesdump/head.b3d deleted file mode 100644 index 41c7588..0000000 Binary files a/nodesdump/head.b3d and /dev/null differ diff --git a/nodesdump/straight b/nodesdump/straight deleted file mode 100644 index 108c49b..0000000 --- a/nodesdump/straight +++ /dev/null @@ -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 - } - } -}) - diff --git a/nodesdump/straight.b3d b/nodesdump/straight.b3d deleted file mode 100644 index 0ed2710..0000000 Binary files a/nodesdump/straight.b3d and /dev/null differ