aboutsummaryrefslogtreecommitdiff
path: root/builtin/game/knockback.lua
diff options
context:
space:
mode:
authorsfan5 <sfan5@live.de>2019-07-16 19:20:06 +0200
committersfan5 <sfan5@live.de>2019-08-10 19:44:27 +0200
commit291e7730cf24ba5081f10b5ddbf2494951333827 (patch)
treeba898a07025935ed768fe1d7daaf03db3f78d271 /builtin/game/knockback.lua
parentcf64054390970f3cf974afb2b174340a3e1da382 (diff)
downloadminetest-291e7730cf24ba5081f10b5ddbf2494951333827.tar.gz
minetest-291e7730cf24ba5081f10b5ddbf2494951333827.tar.bz2
minetest-291e7730cf24ba5081f10b5ddbf2494951333827.zip
Add player knockback on punch to builtin
Diffstat (limited to 'builtin/game/knockback.lua')
-rw-r--r--builtin/game/knockback.lua46
1 files changed, 46 insertions, 0 deletions
diff --git a/builtin/game/knockback.lua b/builtin/game/knockback.lua
new file mode 100644
index 000000000..b5c4cbc5a
--- /dev/null
+++ b/builtin/game/knockback.lua
@@ -0,0 +1,46 @@
+-- can be overriden by mods
+function core.calculate_knockback(player, hitter, time_from_last_punch, tool_capabilities, dir, distance, damage)
+ if damage == 0 or player:get_armor_groups().immortal then
+ return 0.0
+ end
+
+ local m = 8
+ -- solve m - m*e^(k*4) = 4 for k
+ local k = -0.17328
+ local res = m - m * math.exp(k * damage)
+
+ if distance < 2.0 then
+ res = res * 1.1 -- more knockback when closer
+ elseif distance > 4.0 then
+ res = res * 0.9 -- less when far away
+ end
+ return res
+end
+
+local function vector_absmax(v)
+ local max, abs = math.max, math.abs
+ return max(max(abs(v.x), abs(v.y)), abs(v.z))
+end
+
+core.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, unused_dir, damage)
+ if player:get_hp() == 0 then
+ return -- RIP
+ end
+
+ -- Server::handleCommand_Interact() adds eye offset to one but not the other
+ -- so the direction is slightly off, calculate it ourselves
+ local dir = vector.subtract(player:get_pos(), hitter:get_pos())
+ local d = vector.length(dir)
+ if d ~= 0.0 then
+ dir = vector.divide(dir, d)
+ end
+
+ local k = core.calculate_knockback(player, hitter, time_from_last_punch, tool_capabilities, dir, d, damage)
+
+ local kdir = vector.multiply(dir, k)
+ if vector_absmax(kdir) < 1.0 then
+ return -- barely noticeable, so don't even send
+ end
+
+ player:add_player_velocity(kdir)
+end)