add knockout
removed the knockout bat, at least for the time being
This commit is contained in:
parent
c42267755a
commit
4964c44ec3
21
mods/knockout/LICENSE
Normal file
21
mods/knockout/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 Billy S
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
7
mods/knockout/README.md
Normal file
7
mods/knockout/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# knockout
|
||||||
|
Adds a knockout system to minetest.
|
||||||
|
Once a player is knocked out, (s)he can be picked up by other players and moved around.
|
||||||
|
To pick up a player, right-click them once they are knocked out.
|
||||||
|
To drop a player, jump.
|
||||||
|
While a player is knocked out, they cannot move, talk, or run /killme.
|
||||||
|
They are also annoyed by a persistant formspec telling them how long they will be knocked out for.
|
12
mods/knockout/api.lua
Normal file
12
mods/knockout/api.lua
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
-- toolname is the name of the tool (ex "default:pick_wood")
|
||||||
|
-- chance is the chance that the target will be knocked out when hit with the tool
|
||||||
|
-- (A value betwen 1 and 0; 1 = will happen every time; 0 = will never happed. Note that a chance of 1 may fail to knock players out if the tool is not used wiht a full punch)
|
||||||
|
-- max_health is the maximum health the player will have to be knocked out with the tool
|
||||||
|
-- (If the player's health is greater then max_health, they won't be knocked out, regardless of chance)
|
||||||
|
-- max_time is the maximum time (in seconds) that the player will be knocked out for (note that this would happen if the player was hit when they had 0 hp, aka never)
|
||||||
|
-- the minimum time the player will be knocked out for is half of max_time
|
||||||
|
-- The actual time the player is knocked out for is calculated by the following equation:
|
||||||
|
-- time knocked out = max_time * (1 - current hp / (max_health * 2))
|
||||||
|
knockout.register_tool = function(toolname, chance, max_health, max_time)
|
||||||
|
knockout.tools[toolname] = {chance = chance, max_health = max_health, max_time = max_time}
|
||||||
|
end
|
2
mods/knockout/depends.txt
Normal file
2
mods/knockout/depends.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
default
|
||||||
|
lottweapons?
|
87
mods/knockout/handlers.lua
Normal file
87
mods/knockout/handlers.lua
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
-- Create formspec structure
|
||||||
|
local function getFs(name)
|
||||||
|
return "size[5,3]label[1.4,1;You are unconscious!]label[0.8,2;Time remaining: " .. tostring(knockout.knocked_out[name]) .. " seconds]"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Globalstep to revive players
|
||||||
|
local gs_time = 0
|
||||||
|
minetest.register_globalstep(function(dtime)
|
||||||
|
-- Decrease knockout time
|
||||||
|
gs_time = gs_time + dtime
|
||||||
|
if gs_time >= 1 then
|
||||||
|
gs_time = 0
|
||||||
|
for name, _ in pairs(knockout.knocked_out) do
|
||||||
|
local p = minetest.get_player_by_name(name)
|
||||||
|
if p ~= nil then
|
||||||
|
if p:get_hp() > 0 then
|
||||||
|
knockout.decrease_knockout_time(name, 1)
|
||||||
|
minetest.show_formspec(name, "knockout:fs", getFs(name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
knockout.save()
|
||||||
|
end
|
||||||
|
for name, carried in pairs(knockout.carrying) do
|
||||||
|
-- Check for player drop
|
||||||
|
local p = minetest.get_player_by_name(name)
|
||||||
|
if p:get_player_control().jump then
|
||||||
|
knockout.carrier_drop(name)
|
||||||
|
end
|
||||||
|
-- Set the look direction to make it more realistic
|
||||||
|
local c = minetest.get_player_by_name(carried)
|
||||||
|
c:set_look_horizontal(p:get_look_horizontal())
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Oh no you don't. I like that formspec open
|
||||||
|
minetest.register_on_player_receive_fields(function(player, fName, _)
|
||||||
|
if player:get_hp() <= 0 then return false end
|
||||||
|
if fName == "knockout:fs" then
|
||||||
|
local name = player:get_player_name()
|
||||||
|
minetest.show_formspec(name, fName, getFs(name))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- If the player is killed, they "wake up"
|
||||||
|
minetest.register_on_dieplayer(function(p)
|
||||||
|
local pName = p:get_player_name()
|
||||||
|
knockout.wake_up(pName)
|
||||||
|
-- If the player is carrying another player, drop them
|
||||||
|
knockout.carrier_drop(pName)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- If the player was carrying another player, drop them
|
||||||
|
minetest.register_on_leaveplayer(function(p, _)
|
||||||
|
knockout.carrier_drop(p:get_player_name())
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Catch those pesky players that try to leave/join to get un-knocked out
|
||||||
|
minetest.register_on_joinplayer(function(p)
|
||||||
|
local koed = false
|
||||||
|
local name = p:get_player_name()
|
||||||
|
if knockout.knocked_out[name] ~= nil then
|
||||||
|
minetest.after(1, knockout.knockout, name)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Catch whacks with various tools and calculate if the victim should be knocked out
|
||||||
|
minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
|
||||||
|
local victim = player:get_player_name()
|
||||||
|
local currHp = player:get_hp()
|
||||||
|
if knockout.knocked_out[victim] ~= nil then return end
|
||||||
|
if currHp <= 0 then return end
|
||||||
|
local tool = hitter:get_wielded_item():get_name() -- Get tool used
|
||||||
|
local def = knockout.tools[tool]
|
||||||
|
if def == nil then return end
|
||||||
|
-- Calculate
|
||||||
|
if currHp <= def.max_health then
|
||||||
|
local chanceMult = time_from_last_punch / tool_capabilities.full_punch_interval -- You can't knock people out with lots of love taps
|
||||||
|
if chanceMult > 1 then chanceMult = 1 end
|
||||||
|
if math.random() < def.chance * chanceMult then
|
||||||
|
-- Knocked out
|
||||||
|
local koTime = math.floor(def.max_time * (1 - currHp / (def.max_health * 2)))
|
||||||
|
knockout.knockout(victim, koTime)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
195
mods/knockout/init.lua
Normal file
195
mods/knockout/init.lua
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
local path = minetest.get_modpath(minetest.get_current_modname())
|
||||||
|
dofile(path .. "/overrides.lua")
|
||||||
|
|
||||||
|
-- Create globals
|
||||||
|
knockout = {}
|
||||||
|
knockout.knocked_out = {}
|
||||||
|
knockout.carrying = {}
|
||||||
|
knockout.tools = {}
|
||||||
|
|
||||||
|
-- Create mod storage
|
||||||
|
knockout.storage = minetest.get_mod_storage()
|
||||||
|
|
||||||
|
-- Created locals
|
||||||
|
local knockout_huds = {}
|
||||||
|
|
||||||
|
-- Register entity
|
||||||
|
|
||||||
|
minetest.register_entity("knockout:entity", {
|
||||||
|
hp_max = 1000,
|
||||||
|
physical = true,
|
||||||
|
weight = 5,
|
||||||
|
collisionbox = {-0.35, 0, -0.35, 0.35, 1.8, 0.35},
|
||||||
|
visual = "cube",
|
||||||
|
textures = {"invisible.png", "invisible.png", "invisible.png", "invisible.png", "invisible.png", "invisible.png"},
|
||||||
|
is_visible = true,
|
||||||
|
makes_footstep_sound = false,
|
||||||
|
automatic_rotate = false,
|
||||||
|
on_activate = function(e, sdata, dtime)
|
||||||
|
e.grabbed_name = sdata
|
||||||
|
e.object:set_armor_groups({immortal = 1})
|
||||||
|
local p = minetest.get_player_by_name(e.grabbed_name)
|
||||||
|
if p ~= nil then
|
||||||
|
e.object:set_yaw(p:get_look_horizontal())
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_punch = function(e, puncher, time_from_last_punch, tool_capabilities, dir)
|
||||||
|
-- The player can't punch themselves
|
||||||
|
if puncher:get_player_name() == e.grabbed_name then return end
|
||||||
|
-- If punched with a water bucket revive
|
||||||
|
local tool = puncher:get_wielded_item():get_name()
|
||||||
|
if tool == "bucket:bucket_water" then
|
||||||
|
knockout.wake_up(e.grabbed_name)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- Otherwise hurt the player
|
||||||
|
local p = minetest.get_player_by_name(e.grabbed_name)
|
||||||
|
if p == nil then
|
||||||
|
e.object:remove()
|
||||||
|
else
|
||||||
|
p:set_detach()
|
||||||
|
p:punch(puncher, time_from_last_punch, tool_capabilities, dir)
|
||||||
|
p:set_attach(e.object, "", {x = 0, y = 10, z = 0}, {x = 0, y = 0, z = 0})
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_rightclick = function(e, clicker)
|
||||||
|
local cName = clicker:get_player_name()
|
||||||
|
if cName == e.grabbed_name then return end
|
||||||
|
for carryer, carried in pairs(knockout.carrying) do
|
||||||
|
if carryer == cName or carried == e.grabbed_name then return end
|
||||||
|
end
|
||||||
|
victim = minetest.get_player_by_name(e.grabbed_name)
|
||||||
|
if victim then
|
||||||
|
victim:set_attach(clicker, "", {x = 0, y = 0, z = -15}, {x = 0, y = 0, z = 0})
|
||||||
|
knockout.carrying[cName] = e.grabbed_name
|
||||||
|
e.object:remove()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_step = function(e, dtime)
|
||||||
|
if knockout.knocked_out[e.grabbed_name] == nil or minetest.get_player_by_name(e.grabbed_name) == nil then
|
||||||
|
e.object:remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Load knocked out players
|
||||||
|
knockout.load = function()
|
||||||
|
local ko = knockout.storage:get_string("knocked_out")
|
||||||
|
if ko ~= "" then
|
||||||
|
knockout.knocked_out = minetest.deserialize(ko)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Save knocked out players
|
||||||
|
knockout.save = function()
|
||||||
|
knockout.storage:set_string("knocked_out", minetest.serialize(knockout.knocked_out))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Drop a player
|
||||||
|
knockout.carrier_drop = function(pName) -- pname = name of carrier
|
||||||
|
if knockout.carrying[pName] then
|
||||||
|
local cName = knockout.carrying[pName]
|
||||||
|
local carried = minetest.get_player_by_name(cName)
|
||||||
|
if carried then
|
||||||
|
carried:set_detach()
|
||||||
|
knockout.knockout(cName)
|
||||||
|
end
|
||||||
|
knockout.carrying[pName] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Knock out player
|
||||||
|
knockout.knockout = function(pName, duration)
|
||||||
|
local p = minetest.get_player_by_name(pName)
|
||||||
|
if not p then return end
|
||||||
|
if duration == nil then
|
||||||
|
if knockout.knocked_out[pName] == nil then return end
|
||||||
|
else
|
||||||
|
knockout.knocked_out[pName] = duration
|
||||||
|
end
|
||||||
|
-- Incase player is riding a horse or something
|
||||||
|
p:set_detach()
|
||||||
|
-- If the player is carrying another player, fix that
|
||||||
|
knockout.carrier_drop(pName)
|
||||||
|
-- Freeze player using entites
|
||||||
|
local pos = p:get_pos()
|
||||||
|
local e = minetest.add_entity(pos, "knockout:entity", pName)
|
||||||
|
p:set_attach(e, "", {x = 0, y = 10, z = 0}, {x = 0, y = 0, z = 0})
|
||||||
|
-- Make player lay down
|
||||||
|
default.player_attached[pName] = true
|
||||||
|
default.player_set_animation(p, "lay")
|
||||||
|
-- Black screen
|
||||||
|
if knockout_huds[pName] == nil then
|
||||||
|
knockout_huds[pName] = p:hud_add({
|
||||||
|
hud_elem_type = "image",
|
||||||
|
text = "knockout_black.png",
|
||||||
|
name = "knockedout",
|
||||||
|
position = {x = 0.5, y = 0.5},
|
||||||
|
scale = {x= -110, y= -110},
|
||||||
|
alignment = {x = 0, y = 0},
|
||||||
|
|
||||||
|
})
|
||||||
|
end
|
||||||
|
-- No interacting for you, player
|
||||||
|
local privs = minetest.get_player_privs(pName)
|
||||||
|
privs.shout = nil
|
||||||
|
privs.interact = nil
|
||||||
|
minetest.set_player_privs(pName, privs)
|
||||||
|
-- Save
|
||||||
|
knockout.save()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Wake up player
|
||||||
|
knockout.wake_up = function(pName)
|
||||||
|
local p = minetest.get_player_by_name(pName)
|
||||||
|
knockout.knocked_out[pName] = nil
|
||||||
|
-- Un-freeze player
|
||||||
|
local e = p:get_attach()
|
||||||
|
if e ~= nil then
|
||||||
|
local pos = e:get_pos()
|
||||||
|
e:remove()
|
||||||
|
p:set_detach()
|
||||||
|
p:set_pos(pos)
|
||||||
|
end
|
||||||
|
-- Make player stand back up
|
||||||
|
default.player_attached[pName] = false
|
||||||
|
default.player_set_animation(p, "stand")
|
||||||
|
p:set_eye_offset({x=0, y=0, z=0}, {x=0, y=0, z=0})
|
||||||
|
-- If the player was being carried, remove that
|
||||||
|
for name, carried in pairs(knockout.carrying) do
|
||||||
|
if carried == pName then
|
||||||
|
knockout.carrying[name] = nil
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Give the whiny player their privs back already
|
||||||
|
local privs = minetest.get_player_privs(pName)
|
||||||
|
privs.shout = true
|
||||||
|
privs.interact = true
|
||||||
|
minetest.set_player_privs(pName, privs)
|
||||||
|
-- Hide formspec
|
||||||
|
if p:get_hp() > 0 then
|
||||||
|
minetest.close_formspec(pName, "knockout:fs")
|
||||||
|
end
|
||||||
|
-- Un-black screen
|
||||||
|
if knockout_huds[pName] ~= nil then
|
||||||
|
p:hud_remove(knockout_huds[pName])
|
||||||
|
knockout_huds[pName] = nil
|
||||||
|
end
|
||||||
|
-- Save
|
||||||
|
knockout.save()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Decrease knockout time
|
||||||
|
knockout.decrease_knockout_time = function(pName, by)
|
||||||
|
knockout.knocked_out[pName] = knockout.knocked_out[pName] - by
|
||||||
|
if knockout.knocked_out[pName] <= 0 then
|
||||||
|
knockout.wake_up(pName)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Init
|
||||||
|
knockout.load()
|
||||||
|
dofile(path .. "/api.lua")
|
||||||
|
dofile(path .. "/handlers.lua")
|
||||||
|
dofile(path .. "/tools.lua")
|
11
mods/knockout/overrides.lua
Normal file
11
mods/knockout/overrides.lua
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-- No, you don't get to kill yourself
|
||||||
|
local oldKill = minetest.registered_chatcommands["killme"].func
|
||||||
|
minetest.override_chatcommand("killme", {
|
||||||
|
func = function(name, param)
|
||||||
|
if knockout.knocked_out[name] == nil then
|
||||||
|
return oldKill(name, param)
|
||||||
|
else
|
||||||
|
return false, "You can't kill yourself!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
BIN
mods/knockout/textures/invisible.png
Normal file
BIN
mods/knockout/textures/invisible.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 B |
BIN
mods/knockout/textures/knockout_bat.png
Normal file
BIN
mods/knockout/textures/knockout_bat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 411 B |
BIN
mods/knockout/textures/knockout_black.png
Normal file
BIN
mods/knockout/textures/knockout_black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
72
mods/knockout/tools.lua
Normal file
72
mods/knockout/tools.lua
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
---------------
|
||||||
|
--DEFINITIONS--
|
||||||
|
---------------
|
||||||
|
--[[
|
||||||
|
minetest.register_tool("knockout:bat", {
|
||||||
|
description = "Knockout Bat | Knocks out players with less then 4 hearts",
|
||||||
|
inventory_image = "knockout_bat.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "knockout:bat",
|
||||||
|
recipe = {
|
||||||
|
{"", "group:wood", "group:wood"},
|
||||||
|
{"", "default:steel_ingot", "group:wood"},
|
||||||
|
{"group:wood", "", ""},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
--]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--------------
|
||||||
|
--KNOCK OUT---
|
||||||
|
--------------
|
||||||
|
--knockout.register_tool("knockout:bat", 0.8, 8, 120)
|
||||||
|
|
||||||
|
-----------
|
||||||
|
--DEFAULT--
|
||||||
|
-----------
|
||||||
|
|
||||||
|
-- Fist
|
||||||
|
knockout.register_tool("", 0.6, 6, 80)
|
||||||
|
|
||||||
|
-- picks have no knockout chance
|
||||||
|
-- shovels have slight knockout chance with low knockout time
|
||||||
|
knockout.register_tool("default:shovel_wood", 0.1, 10, 20)
|
||||||
|
knockout.register_tool("default:shovel_stone", 0.05, 10, 20)
|
||||||
|
knockout.register_tool("default:shovel_steel", 0.07, 10, 20)
|
||||||
|
knockout.register_tool("default:shovel_bronze", 0.07, 10, 20)
|
||||||
|
knockout.register_tool("default:shovel_mese", 0.1, 10, 20)
|
||||||
|
knockout.register_tool("default:shovel_diamond", 0.1, 10, 20)
|
||||||
|
-- Low-level axes have a slight knockout chance with medium knockout time
|
||||||
|
knockout.register_tool("default:axe_wood", 0.3, 3, 100)
|
||||||
|
knockout.register_tool("default:axe_stone", 0.1, 4, 110)
|
||||||
|
-- Swords have a slight knockout chance with high knockout time, except for wooden sword = club
|
||||||
|
knockout.register_tool("default:sword_wood", 0.7, 6, 140)
|
||||||
|
knockout.register_tool("default:sword_stone", 0.3, 6, 150)
|
||||||
|
knockout.register_tool("default:sword_steel", 0.1, 7, 150)
|
||||||
|
knockout.register_tool("default:sword_bronze", 0.1, 7, 150)
|
||||||
|
knockout.register_tool("default:sword_mese", 0.05, 8, 160)
|
||||||
|
knockout.register_tool("default:sword_diamond", 0.05, 9, 160)
|
||||||
|
-- Hoes have no knockout chance
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
--LOTT WEAPONS--
|
||||||
|
-----------------
|
||||||
|
if minetest.get_modpath("lottweapons") ~= nil then
|
||||||
|
-- Battleaxes (Low knockout chance, high knockout time.)
|
||||||
|
knockout.register_tool("lottweapons:wood_battleaxe", 0.2, 4, 140)
|
||||||
|
knockout.register_tool("lottweapons:stone_battleaxe", 0.1, 6, 150)
|
||||||
|
knockout.register_tool("lottweapons:copper_battleaxe", 0.05, 7, 150)
|
||||||
|
knockout.register_tool("lottweapons:steel_battleaxe", 0.05, 7, 150)
|
||||||
|
-- Warhammers (high knockout chance, medium knockout time for lower levels.)
|
||||||
|
knockout.register_tool("lottweapons:wood_warhammer", 0.7, 7, 80)
|
||||||
|
knockout.register_tool("lottweapons:stone_warhammer", 0.3, 4, 100)
|
||||||
|
knockout.register_tool("lottweapons:copper_warhammer", 0.1, 4, 120)
|
||||||
|
knockout.register_tool("lottweapons:steel_warhammer", 0.1, 5, 120)
|
||||||
|
-- Spears have no knockout chance
|
||||||
|
-- Daggers have no knockout chance
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user