Upload files to ''

master
MisterE123 2020-12-20 05:42:19 +00:00
parent ed97d01da8
commit b33b216fb6
10 changed files with 675 additions and 2 deletions

View File

@ -1,3 +1,17 @@
# sumo_with_spectate
# sumo
adds a spectate functionality, which is in beta phase. Needs testing. For now, you can only spectate 1 player until they die, then you switch. Also, you die when the player you are spectating dies.
Knock other players off the platform to win
![](screenshot.png)
Contributors: Zughy, MisterE
Schematics for arenas can be found here:
https://notabug.org/MisterE123/sumo_arenas
^
// \\
// ! \\ Caution: This mod gives players the interact priv when they join the server. This is because interact is temporarily revoked during spectation mode.
-------

306
chatcmdbuilder.lua Normal file
View File

@ -0,0 +1,306 @@
ChatCmdBuilder = {}
function ChatCmdBuilder.new(name, func, def)
def = def or {}
local cmd = ChatCmdBuilder.build(func)
cmd.def = def
def.func = cmd.run
minetest.register_chatcommand(name, def)
return cmd
end
local STATE_READY = 1
local STATE_PARAM = 2
local STATE_PARAM_TYPE = 3
local bad_chars = {}
bad_chars["("] = true
bad_chars[")"] = true
bad_chars["."] = true
bad_chars["%"] = true
bad_chars["+"] = true
bad_chars["-"] = true
bad_chars["*"] = true
bad_chars["?"] = true
bad_chars["["] = true
bad_chars["^"] = true
bad_chars["$"] = true
local function escape(char)
if bad_chars[char] then
return "%" .. char
else
return char
end
end
local dprint = function() end
ChatCmdBuilder.types = {
pos = "%(? *(%-?[%d.]+) *, *(%-?[%d.]+) *, *(%-?[%d.]+) *%)?",
text = "(.+)",
number = "(%-?[%d.]+)",
int = "(%-?[%d]+)",
word = "([^ ]+)",
alpha = "([A-Za-z]+)",
modname = "([a-z0-9_]+)",
alphascore = "([A-Za-z_]+)",
alphanumeric = "([A-Za-z0-9]+)",
username = "([A-Za-z0-9-_]+)",
}
function ChatCmdBuilder.build(func)
local cmd = {
_subs = {}
}
function cmd:sub(route, func, def)
dprint("Parsing " .. route)
def = def or {}
if string.trim then
route = string.trim(route)
end
local sub = {
pattern = "^",
params = {},
func = func
}
-- End of param reached: add it to the pattern
local param = ""
local param_type = ""
local should_be_eos = false
local function finishParam()
if param ~= "" and param_type ~= "" then
dprint(" - Found param " .. param .. " type " .. param_type)
local pattern = ChatCmdBuilder.types[param_type]
if not pattern then
error("Unrecognised param_type=" .. param_type)
end
sub.pattern = sub.pattern .. pattern
table.insert(sub.params, param_type)
param = ""
param_type = ""
end
end
-- Iterate through the route to find params
local state = STATE_READY
local catching_space = false
local match_space = " " -- change to "%s" to also catch tabs and newlines
local catch_space = match_space.."+"
for i = 1, #route do
local c = route:sub(i, i)
if should_be_eos then
error("Should be end of string. Nothing is allowed after a param of type text.")
end
if state == STATE_READY then
if c == ":" then
dprint(" - Found :, entering param")
state = STATE_PARAM
param_type = "word"
catching_space = false
elseif c:match(match_space) then
print(" - Found space")
if not catching_space then
catching_space = true
sub.pattern = sub.pattern .. catch_space
end
else
catching_space = false
sub.pattern = sub.pattern .. escape(c)
end
elseif state == STATE_PARAM then
if c == ":" then
dprint(" - Found :, entering param type")
state = STATE_PARAM_TYPE
param_type = ""
elseif c:match(match_space) then
print(" - Found whitespace, leaving param")
state = STATE_READY
finishParam()
catching_space = true
sub.pattern = sub.pattern .. catch_space
elseif c:match("%W") then
dprint(" - Found nonalphanum, leaving param")
state = STATE_READY
finishParam()
sub.pattern = sub.pattern .. escape(c)
else
param = param .. c
end
elseif state == STATE_PARAM_TYPE then
if c:match(match_space) then
print(" - Found space, leaving param type")
state = STATE_READY
finishParam()
catching_space = true
sub.pattern = sub.pattern .. catch_space
elseif c:match("%W") then
dprint(" - Found nonalphanum, leaving param type")
state = STATE_READY
finishParam()
sub.pattern = sub.pattern .. escape(c)
else
param_type = param_type .. c
end
end
end
dprint(" - End of route")
finishParam()
sub.pattern = sub.pattern .. "$"
dprint("Pattern: " .. sub.pattern)
table.insert(self._subs, sub)
end
if func then
func(cmd)
end
cmd.run = function(name, param)
for i = 1, #cmd._subs do
local sub = cmd._subs[i]
local res = { string.match(param, sub.pattern) }
if #res > 0 then
local pointer = 1
local params = { name }
for j = 1, #sub.params do
local param = sub.params[j]
if param == "pos" then
local pos = {
x = tonumber(res[pointer]),
y = tonumber(res[pointer + 1]),
z = tonumber(res[pointer + 2])
}
table.insert(params, pos)
pointer = pointer + 3
elseif param == "number" or param == "int" then
table.insert(params, tonumber(res[pointer]))
pointer = pointer + 1
else
table.insert(params, res[pointer])
pointer = pointer + 1
end
end
if table.unpack then
-- lua 5.2 or later
return sub.func(table.unpack(params))
else
-- lua 5.1 or earlier
return sub.func(unpack(params))
end
end
end
return false, "Invalid command"
end
return cmd
end
local function run_tests()
if not (ChatCmdBuilder.build(function(cmd)
cmd:sub("bar :one and :two:word", function(name, one, two)
if name == "singleplayer" and one == "abc" and two == "def" then
return true
end
end)
end)).run("singleplayer", "bar abc and def") then
error("Test 1 failed")
end
local move = ChatCmdBuilder.build(function(cmd)
cmd:sub("move :target to :pos:pos", function(name, target, pos)
if name == "singleplayer" and target == "player1" and
pos.x == 0 and pos.y == 1 and pos.z == 2 then
return true
end
end)
end).run
if not move("singleplayer", "move player1 to 0,1,2") then
error("Test 2 failed")
end
if not move("singleplayer", "move player1 to (0,1,2)") then
error("Test 3 failed")
end
if not move("singleplayer", "move player1 to 0, 1,2") then
error("Test 4 failed")
end
if not move("singleplayer", "move player1 to 0 ,1, 2") then
error("Test 5 failed")
end
if not move("singleplayer", "move player1 to 0, 1, 2") then
error("Test 6 failed")
end
if not move("singleplayer", "move player1 to 0 ,1 ,2") then
error("Test 7 failed")
end
if not move("singleplayer", "move player1 to ( 0 ,1 ,2)") then
error("Test 8 failed")
end
if move("singleplayer", "move player1 to abc,def,sdosd") then
error("Test 9 failed")
end
if move("singleplayer", "move player1 to abc def sdosd") then
error("Test 10 failed")
end
if not (ChatCmdBuilder.build(function(cmd)
cmd:sub("does :one:int plus :two:int equal :three:int", function(name, one, two, three)
if name == "singleplayer" and one + two == three then
return true
end
end)
end)).run("singleplayer", "does 1 plus 2 equal 3") then
error("Test 11 failed")
end
local checknegint = ChatCmdBuilder.build(function(cmd)
cmd:sub("checknegint :x:int", function(name, x)
return x
end)
end).run
if checknegint("checker","checknegint -2") ~= -2 then
error("Test 12 failed")
end
local checknegnumber = ChatCmdBuilder.build(function(cmd)
cmd:sub("checknegnumber :x:number", function(name, x)
return x
end)
end).run
if checknegnumber("checker","checknegnumber -3.3") ~= -3.3 then
error("Test 13 failed")
end
local checknegpos = ChatCmdBuilder.build(function(cmd)
cmd:sub("checknegpos :pos:pos", function(name, pos)
return pos
end)
end).run
local negpos = checknegpos("checker","checknegpos (-13.3,-4.6,-1234.5)")
if negpos.x ~= -13.3 or negpos.y ~= -4.6 or negpos.z ~= -1234.5 then
error("Test 14 failed")
end
local checktypes = ChatCmdBuilder.build(function(cmd)
cmd:sub("checktypes :int:int :number:number :pos:pos :word:word :text:text", function(name, int, number, pos, word, text)
return int, number, pos.x, pos.y, pos.z, word, text
end)
end).run
local int, number, posx, posy, posz, word, text
int, number, posx, posy, posz, word, text = checktypes("checker","checktypes -1 -2.4 (-3,-5.3,6.12) some text to finish off with")
--dprint(int, number, posx, posy, posz, word, text)
if int ~= -1 or number ~= -2.4 or posx ~= -3 or posy ~= -5.3 or posz ~= 6.12 or word ~= "some" or text ~= "text to finish off with" then
error("Test 15 failed")
end
dprint("All tests passed")
end
if not minetest then
run_tests()
end

51
commands.lua Normal file
View File

@ -0,0 +1,51 @@
ChatCmdBuilder.new("sumo", function(cmd)
-- create arena
cmd:sub("create :arena", function(name, arena_name)
arena_lib.create_arena(name, "sumo", arena_name)
end)
cmd:sub("create :arena :minplayers:int :maxplayers:int", function(name, arena_name, min_players, max_players)
arena_lib.create_arena(name, "sumo", arena_name, min_players, max_players)
end)
-- remove arena
cmd:sub("remove :arena", function(name, arena_name)
arena_lib.remove_arena(name, "sumo", arena_name)
end)
-- list of the arenas
cmd:sub("list", function(name)
arena_lib.print_arenas(name, "sumo")
end)
-- enter editor mode
cmd:sub("edit :arena", function(sender, arena)
arena_lib.enter_editor(sender, "sumo", arena)
end)
-- enable and disable arenas
cmd:sub("enable :arena", function(name, arena)
arena_lib.enable_arena(name, "sumo", arena)
end)
cmd:sub("disable :arena", function(name, arena)
arena_lib.disable_arena(name, "sumo", arena)
end)
end, {
description = [[
(/help sumo)
Use this to configure your arena:
- create <arena name> [min players] [max players]
- edit <arena name>
- enable <arena name>
Other commands:
- remove <arena name>
- disable <arena>
]],
privs = { sumo_admin = true }
})

1
description.txt Normal file
View File

@ -0,0 +1 @@
A minigame for arena_lib where you punch the other players with your stick to knock them off the platform or island. Some advanced uses of the stick include vaulting yourself and throwing otehr players over your shoulder.

49
init.lua Normal file
View File

@ -0,0 +1,49 @@
sumo = {}
-- local value settings
local player_speed = 2 -- when in the minigame
local player_jump = 1.3 -- when in the minigame
arena_lib.register_minigame("sumo", {
prefix = "[Sumo] ",
hub_spawn_point = { x = 0, y = 20, z = 0 },
show_minimap = false,
time_mode = 2,
load_time = 1,
celebration_time = 5,
join_while_in_progress = false,
keep_inventory = false,
in_game_physics = {
speed = player_speed,
jump = player_jump,
sneak = false,
},
hotbar = {
slots = 1,
background_image = "sumo_gui_hotbar.png"
},
disabled_damage_types = {"punch","fall"},
player_properties = {
textures = "",
watching = "",
playing = true,
collisionbox = {},
},
})
dofile(minetest.get_modpath("sumo") .. "/commands.lua")
dofile(minetest.get_modpath("sumo") .. "/items.lua")
dofile(minetest.get_modpath("sumo") .. "/minigame_manager.lua")
dofile(minetest.get_modpath("sumo") .. "/nodes.lua")
dofile(minetest.get_modpath("sumo") .. "/privs.lua")
if not minetest.get_modpath("lib_chatcmdbuilder") then
dofile(minetest.get_modpath("sumo") .. "/chatcmdbuilder.lua")
end

92
items.lua Normal file
View File

@ -0,0 +1,92 @@
local stick_knockback = 30 --multiplier for how hard the stick hits
local stick_vault_reach = 3 -- how close to the pointed node must the player be to vault
local stick_vault_timeout = 1 -- int timer for how long the vault cannot be used after it is used
local allow_swap_distance = 4 -- if an opponent is within this distance, then if the player uses the pushstick with the shift key pressed, the players switch positions.
minetest.register_craftitem("sumo:pushstick", {
description = "Push Stick",
inventory_image = "default_stick.png",
stack_max = 1,
wield_scale = {x = 2, y = 2, z = 2},
on_drop = function() end,
on_use = function(itemstack, user, pointed_thing)
local sound = 'swish'..math.random(1,4)
minetest.sound_play(sound, {
pos = user:get_pos(),
max_hear_distance = 5,
gain = 10.0,
})
if pointed_thing == nil then return end
if pointed_thing.type == 'object' then
if minetest.is_player(pointed_thing.ref) == true then
local dir = user:get_look_dir()
local keys = user:get_player_control()
local swap = false
local hitted_pos = pointed_thing.ref:get_pos()
local hitter_pos = user:get_pos()
if keys.sneak and vector.distance(hitted_pos,hitter_pos) < allow_swap_distance then
swap = true
user:move_to(hitted_pos, true)
pointed_thing.ref:move_to(hitter_pos, true)
pointed_thing.ref:add_player_velocity(vector.multiply({x = -dir.x, y = dir.y, z= -dir.z}, stick_knockback/2))
else
pointed_thing.ref:add_player_velocity(vector.multiply(dir, stick_knockback))
if not swap then
local sound = 'thwack'..math.random(1,3)
minetest.sound_play(sound, {
pos = user:get_pos(),
max_hear_distance = 10,
gain = 10.0,
})
local sound = 'hurt'..math.random(1,2)
minetest.sound_play(sound, {
to_player = pointed_thing.ref:get_player_name(),
pos = user:get_pos(),
gain = 10.0,
})
end
end
end
end
end,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing == nil then return end
if pointed_thing.type == 'node' then
if vector.distance(pointed_thing.under, placer:get_pos()) < stick_vault_reach then
local first_use = false
local imeta = itemstack:get_meta()
local old_time = imeta:get_int('old_time')
local current_time = minetest.get_gametime()
if old_time == 0 or old_time == nil then
first_use = true
end
if first_use or current_time > old_time + stick_vault_timeout then
local lookvect = placer:get_look_dir()
local pushvect = vector.normalize( {x=lookvect.x, z=lookvect.z, y= math.sqrt(1-(lookvect.y*lookvect.y))})
--gives a unit vector that is 90 deg offset in the vert direction
local force = 10 * vector.length(vector.normalize( {x=lookvect.x, z=lookvect.z, y= 0}))
placer:add_player_velocity(vector.multiply(pushvect, force))
--update the staff time for next check
local sound = 'jump'..math.random(1,2)
minetest.sound_play(sound, {
pos = placer:get_pos(),
max_hear_distance = 10,
gain = 10.0,
})
imeta:set_int('old_time', current_time)
return itemstack
end
end
end
end,
})

126
nodes.lua Normal file
View File

@ -0,0 +1,126 @@
minetest.register_node("sumo:player_killer_air", {
description = "Sumo Arena Player Killer Air",
drawtype = "airlike",
paramtype = "light",
sunlight_propagates = true,
walkable = false,
pointable = true,
diggable = true,
buildable_to = false,
drop = "",
damage_per_second = 40,
groups = {oddly_breakable_by_hand = 1},
})
minetest.register_node("sumo:fullclip", {
description = "Player Blocker (sumo)",
drawtype = "airlike",
paramtype = "light",
sunlight_propagates = true,
walkable = true,
pointable = true,
diggable = false,
buildable_to = false,
drop = "",
damage_per_second = 40,
groups = {},
})
minetest.register_node("sumo:player_killer_water_source", {
description = "Sumo Arena Player Killer Water Source",
drawtype = "liquid",
waving = 3,
tiles = {
{
name = "default_water_source_animated.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 2.0,
},
},
{
name = "default_water_source_animated.png",
backface_culling = true,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 2.0,
},
},
},
damage_per_second = 40,
alpha = 191,
paramtype = "light",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drop = "",
drowning = 1,
liquidtype = "source",
liquid_alternative_flowing = "sumo:player_killer_water_flowing",
liquid_alternative_source = "sumo:player_killer_water_source",
liquid_viscosity = 1,
post_effect_color = {a = 103, r = 30, g = 60, b = 90},
groups = {water = 3, liquid = 3, cools_lava = 1},
sounds = default.node_sound_water_defaults(),
})
minetest.register_node("sumo:player_killer_water_flowing", {
description = "Sumo Arena Player Killer Water Flowing",
drawtype = "flowingliquid",
waving = 3,
tiles = {"default_water.png"},
special_tiles = {
{
name = "default_water_flowing_animated.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 0.5,
},
},
{
name = "default_water_flowing_animated.png",
backface_culling = true,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 0.5,
},
},
},
damage_per_second = 200,
alpha = 191,
paramtype = "light",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drop = "",
drowning = 1,
liquidtype = "flowing",
liquid_alternative_flowing = "sumo:player_killer_water_flowing",
liquid_alternative_source = "sumo:player_killer_water_source",
liquid_viscosity = 1,
post_effect_color = {a = 103, r = 30, g = 60, b = 90},
groups = {water = 3, liquid = 3, not_in_creative_inventory = 1,
cools_lava = 1},
sounds = default.node_sound_water_defaults(),
})

3
privs.lua Normal file
View File

@ -0,0 +1,3 @@
minetest.register_privilege("sumo_admin", {
description = "With this you can use /sumo create, edit"
})

31
readme.txt Normal file
View File

@ -0,0 +1,31 @@
Sumo 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
to set up an arena, create a confined space that floats in the air, with lava or other damage blocks beneath. Set the spawners on the platform. You can use mesecons to make the board more interesting.
In this game, each player gets a tool that pushes other players... the goal is to knowck all other players off and be the last one standing. Each player gets 3 lives
Basic setup:
1) type /sumo create <arena_name>
2) type /sumo 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. There should be some type of platform, with a lava pool underneath to kill players that fall off.
6) using the editor tools, mark player spawner locations. Protect the arena.
7) exit the editor mode
8) type /minigamesettings sumo
9) change the hub spawnpoint to be next to the signs.

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB