add knockout

removed the knockout bat, at least for the time being
This commit is contained in:
Elkien3 2018-07-27 10:04:21 -05:00
parent c42267755a
commit 4964c44ec3
11 changed files with 407 additions and 0 deletions

21
mods/knockout/LICENSE Normal file
View 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
View 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
View 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

View File

@ -0,0 +1,2 @@
default
lottweapons?

View 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
View 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")

View 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
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

72
mods/knockout/tools.lua Normal file
View 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