From 495303a5202f37c3d4d0aa023ce68a3e50db437b Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 16 Jan 2017 11:36:30 +0100 Subject: [PATCH] Add playerplus variant (suffocation + cactus dmg) --- API.md | 7 ++ mods/playerplus/README.md | 28 +++++++ mods/playerplus/depends.txt | 2 + mods/playerplus/description.txt | 1 + mods/playerplus/init.lua | 134 ++++++++++++++++++++++++++++++++ mods/playerplus/license.txt | 21 +++++ 6 files changed, 193 insertions(+) create mode 100644 mods/playerplus/README.md create mode 100644 mods/playerplus/depends.txt create mode 100644 mods/playerplus/description.txt create mode 100644 mods/playerplus/init.lua create mode 100644 mods/playerplus/license.txt diff --git a/API.md b/API.md index 4335a1cacf..fadd8a045d 100644 --- a/API.md +++ b/API.md @@ -15,6 +15,13 @@ This section explains all the used groups in this subgame. * `soil_sapling=2`: Soil for saplings. Intended to be natural soil. All saplings will grow on this * `soil_sapling=1`: Artificial soil (such as farmland) for saplings. Some saplings will not grow on this * `soil_sugarcane=1`: Sugar canes will grow on this near water +* `disable_suffocation=1`: Disables suffocation for full solid cubes (1) + +### Footnotes + +1. Normally, all walkable blocks with the default 1×1×1 cube as a collision box (e.g. sand, + gravel, stone, but not fences) will damage the players while their head is inside. This + is called “suffocation”. Setting this group disables this behaviour ### Groups (mostly) used for crafting recipes diff --git a/mods/playerplus/README.md b/mods/playerplus/README.md new file mode 100644 index 0000000000..5a077fc79e --- /dev/null +++ b/mods/playerplus/README.md @@ -0,0 +1,28 @@ +# PlayerPlus mod for MineClone 2 + +## Features + +- Hurt players touching cacti (0.5 hearts / 0.5s) +- Suffocation: Hurt players who have their head inside a solid block (0.5 hearts / 0.5s) + +Suffocation *not* dealt to player with the `noclip` privilege. + +## Notes +This mod is based on PlayerPlus [`playerplus`] by TenPlus1. It behaves a bit +differently than the original, but the API is fully compatible. + +## API + +Every half second the mod checks which node the player is standing on, which +node is at foot and head level and stores inside a global table to be used by mods: + +- `playerplus[name].nod_stand` +- `playerplus[name].nod_foot` +- `playerplus[name].nod_head` + +Setting the group `disable_suffocation=1` disables suffocation for nodes which +would otherwise deal suffocation damage. + +## License +WTFPL. + diff --git a/mods/playerplus/depends.txt b/mods/playerplus/depends.txt new file mode 100644 index 0000000000..c12cc51ba8 --- /dev/null +++ b/mods/playerplus/depends.txt @@ -0,0 +1,2 @@ +default +3d_armor? diff --git a/mods/playerplus/description.txt b/mods/playerplus/description.txt new file mode 100644 index 0000000000..c1c9097f3f --- /dev/null +++ b/mods/playerplus/description.txt @@ -0,0 +1 @@ +Hurts players touching a cactus and when with the head inside solid blocks. diff --git a/mods/playerplus/init.lua b/mods/playerplus/init.lua new file mode 100644 index 0000000000..5683880916 --- /dev/null +++ b/mods/playerplus/init.lua @@ -0,0 +1,134 @@ +--[[ + PlayerPlus by TenPlus1 +]] + +playerplus = {} + +-- get node but use fallback for nil or unknown +local function node_ok(pos, fallback) + + fallback = fallback or "air" + + local node = minetest.get_node_or_nil(pos) + + if not node then + return fallback + end + + if minetest.registered_nodes[node.name] then + return node.name + end + + return fallback +end + +local armor_mod = minetest.get_modpath("3d_armor") +local def = {} +local time = 0 + +minetest.register_globalstep(function(dtime) + + time = time + dtime + + -- every 0.5 seconds + if time < 0.5 then + return + end + + -- reset time for next check + -- FIXME: Make sure a regular check interval applies + time = 0 + + -- check players + for _,player in pairs(minetest.get_connected_players()) do + + -- who am I? + local name = player:get_player_name() + + -- where am I? + local pos = player:getpos() + + -- what is around me? + pos.y = pos.y - 0.1 -- standing on + playerplus[name].nod_stand = node_ok(pos) + + pos.y = pos.y + 1.5 -- head level + playerplus[name].nod_head = node_ok(pos) + + pos.y = pos.y - 1.2 -- feet level + playerplus[name].nod_feet = node_ok(pos) + + pos.y = pos.y - 0.2 -- reset pos + + -- set defaults + def.speed = 1 + def.jump = 1 + def.gravity = 1 + + -- is 3d_armor mod active? if so make armor physics default + if armor_mod and armor and armor.def then + -- get player physics from armor + def.speed = armor.def[name].speed or 1 + def.jump = armor.def[name].jump or 1 + def.gravity = armor.def[name].gravity or 1 + end + + -- standing on soul sand? if so walk slower +-- if playerplus[name].nod_stand == "mcl_nether:soul_sand" then + -- TODO: Fix walk speed +-- def.speed = def.speed - 0.4 +-- end + + -- set player physics + -- TODO: Resolve conflict + player:set_physics_override(def.speed, def.jump, def.gravity) + + -- Is player suffocating inside node? (Only for solid full cube type nodes without damage + -- and without group disable_suffocation=1.) + local ndef = minetest.registered_nodes[playerplus[name].nod_head] + + if (ndef.walkable == nil or ndef.walkable == true) + and (ndef.drowning == nil or ndef.drowning == 0) + and (ndef.damage_per_second == nil or ndef.damage_per_second <= 0) + and (ndef.collision_box == nil or ndef.collision_box.type == "regular") + and (ndef.node_box == nil or ndef.node_box.type == "regular") + and (ndef.groups.disable_suffocation ~= 1) + -- Check privilege, too + and (not minetest.check_player_privs(name, {noclip = true})) then + if player:get_hp() > 0 then + player:set_hp(player:get_hp() - 1) + end + end + + -- am I near a cactus? + local near = minetest.find_node_near(pos, 1, "default:cactus") + + if near then + -- am I touching the cactus? if so it hurts + for _,object in pairs(minetest.get_objects_inside_radius(near, 1.1)) do + if object:get_hp() > 0 then + object:set_hp(object:get_hp() - 1) + end + end + + end + + end + +end) + +-- set to blank on join (for 3rd party mods) +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + + playerplus[name] = {} + playerplus[name].nod_head = "" + playerplus[name].nod_feet = "" + playerplus[name].nod_stand = "" +end) + +-- clear when player leaves +minetest.register_on_leaveplayer(function(player) + + playerplus[ player:get_player_name() ] = nil +end) diff --git a/mods/playerplus/license.txt b/mods/playerplus/license.txt new file mode 100644 index 0000000000..fec6f6aa51 --- /dev/null +++ b/mods/playerplus/license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 TenPlus1 + +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.