diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index c7f8d3e84..b701b48fe 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -522,7 +522,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir) if is_player then -- is mob out of reach? - if vector.distance(mob_pos, player_pos) > 3 then + if vector.distance(mob_pos, player_pos) > 3 then return end -- is mob protected? diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index 6b05b5434..37c38a085 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -57,7 +57,9 @@ function mcl_bows.shoot_arrow(arrow_item, pos, dir, yaw, shooter, power, damage, damage = damage + (enchantments.power + 1) / 4 end if enchantments.punch then - knockback = enchantments.punch * 21 + knockback = enchantments.punch * 24 + else + knockback = 4.875 end if enchantments.flame then mcl_burning.set_on_fire(obj, math.huge) diff --git a/mods/ITEMS/mcl_bows/crossbow.lua b/mods/ITEMS/mcl_bows/crossbow.lua index af356e399..b6a1a3ad6 100644 --- a/mods/ITEMS/mcl_bows/crossbow.lua +++ b/mods/ITEMS/mcl_bows/crossbow.lua @@ -48,7 +48,7 @@ function mcl_bows_s.shoot_arrow_crossbow(arrow_item, pos, dir, yaw, shooter, pow if damage == nil then damage = 3 end - local knockback + local knockback = 4.875 if crossbow_stack then local enchantments = mcl_enchanting.get_enchantments(crossbow_stack) if enchantments.piercing then diff --git a/mods/ITEMS/mcl_enchanting/enchantments.lua b/mods/ITEMS/mcl_enchanting/enchantments.lua index c6436339c..591dfb679 100644 --- a/mods/ITEMS/mcl_enchanting/enchantments.lua +++ b/mods/ITEMS/mcl_enchanting/enchantments.lua @@ -133,7 +133,11 @@ minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, if wielditem then local fire_aspect_level = mcl_enchanting.get_enchantment(wielditem, "fire_aspect") if fire_aspect_level > 0 then - mcl_burning.set_on_fire(player, fire_aspect_level * 4) + local player_pos = player:get_pos() + local hitter_pos = hitter:get_pos() + if vector.distance(hitter_pos, player_pos) <= 3 then + mcl_burning.set_on_fire(player, fire_aspect_level * 4) + end end end end @@ -276,15 +280,65 @@ function minetest.calculate_knockback(player, hitter, time_from_last_punch, tool if hitter then luaentity = hitter:get_luaentity() end - if hitter and hitter:is_player() then + if hitter and hitter:is_player() and distance <= 3 then local wielditem = hitter:get_wielded_item() - knockback = knockback + 5 * mcl_enchanting.get_enchantment(wielditem, "knockback") + --knockback = knockback + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") + local enchant = mcl_enchanting.get_enchantment(wielditem, "knockback") + knockback = knockback + 3.22 * enchant + -- add vertical lift to knockback + local v = player:get_velocity() + local added_v = 0 + local invul = player:get_meta():get_int("mcl_damage:invulnerable") + if v and v.y <= 0.01 and v.y >= -0.01 and invul == 0 then + local regular_v = 6.4 + local enchant_v = 7 + regular_v = regular_v * math.abs(dir.y - 1) + enchant_v = enchant_v * math.abs(dir.y - 1) + if enchant == 0 then + player:add_velocity({x = 0, y = regular_v, z = 0}) + added_v = regular_v + else + player:add_velocity({x = 0, y = enchant_v, z = 0}) + added_v = enchant_v + end + -- add minimum knockback + if knockback <= 1.5 then + knockback = knockback + 4.875 + elseif knockback <= 6.19 then + knockback = knockback + 0.609375 + end + end + -- counteract forward velocity when hit + local self_dir_dot = (v.x * dir.x) + (v.z * dir.z) + if self_dir_dot < 0 then + player:add_velocity({x = v.x * -1, y = 0, z = v.z * -1}) + end -- add player velocity to knockback + local h_name = hitter:get_player_name() local hv = hitter:get_velocity() local dir_dot = (hv.x * dir.x) + (hv.z * dir.z) - if dir_dot > 0 then - knockback = knockback + dir_dot * 2 + local hitter_mag = math.sqrt((hv.x * hv.x) + (hv.z * hv.z)) + if dir_dot > 0 and mcl_sprint.is_sprinting(h_name) then + knockback = knockback + hitter_mag * 0.6875 + elseif dir_dot > 0 then + knockback = knockback + hitter_mag * 0.515625 end + -- reduce floatiness + minetest.after(0.25, function() + player:add_velocity({x = 0, y = (v.y + added_v) * -0.375, z = 0}) + end) + -- reduce knockback when moving towards hitter while attacking + local self_dir_dot = (v.x * dir.x) + (v.z * dir.z) + local control = player:get_player_control() + if self_dir_dot < -4.3 and control.up and control.LMB then + knockback = knockback * 0.6 + end + -- remove knockback if invulnerable + if invul > 0 then + knockback = 0 + end + elseif hitter and hitter:is_player() and distance > 3 then + knockback = 0 elseif luaentity and luaentity._knockback then local kb = knockback + luaentity._knockback / 4 local punch_dir = dir diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index f3cc782d5..0e666aa5b 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -228,6 +228,11 @@ minetest.register_globalstep(function(dtime) -- Apply animations based on what the player is doing if player:get_hp() == 0 then player_set_animation(player, "die") + elseif player:get_meta():get_int("mcl_damage:damage_animation") > 0 then + player_set_animation(player, "walk", animation_speed_mod) + minetest.after(0.5, function() + player:get_meta():set_int("mcl_damage:damage_animation", 0) + end) elseif mcl_playerplus.elytra[player] and mcl_playerplus.elytra[player].active then player_set_animation(player, "stand") elseif walking and velocity.x > 0.35 diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 6cfb15bad..e3d323854 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -663,6 +663,8 @@ minetest.register_on_joinplayer(function(player) lastPos = nil, swimDistance = 0, jump_cooldown = -1, -- Cooldown timer for jumping, we need this to prevent the jump exhaustion to increase rapidly + last_damage = 0, + invul_timestamp = 0, } mcl_playerplus.elytra[player] = {active = false, rocketing = 0, speed = 0} @@ -727,19 +729,43 @@ mcl_damage.register_modifier(function(obj, damage, reason) end end, -200) --- damage invulnerability -mcl_damage.register_modifier(function(obj, damage, reason) - local invul = obj:get_meta():get_int("mcl_damage:invulnerable") - if invul > 0 then - return 0 - else - obj:get_meta():set_int("mcl_damage:invulnerable", 1) - minetest.after(0.5, function() - obj:get_meta():set_int("mcl_damage:invulnerable", 0) - end) - return damage +minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage) + -- attack reach limit + if hitter and hitter:is_player() then + local player_pos = player:get_pos() + local hitter_pos = hitter:get_pos() + if vector.distance(player_pos, hitter_pos) > 3 then + damage = 0 + return damage + end end -end, -1000) + -- damage invulnerability + if hitter then + local name = player:get_player_name() + local time_now = minetest.get_us_time() + local invul_timestamp = mcl_playerplus_internal[name].invul_timestamp + local time_diff = time_now - invul_timestamp + -- check for invulnerability time in microseconds (0.5 second) + if time_diff <= 500000 and time_diff >= 0 then + player:get_meta():set_int("mcl_damage:invulnerable", 1) + minetest.after(0.5, function() + player:get_meta():set_int("mcl_damage:invulnerable", 0) + end) + damage = damage - mcl_playerplus_internal[name].last_damage + if damage < 0 then + damage = 0 + end + return damage + else + mcl_playerplus_internal[name].last_damage = damage + mcl_playerplus_internal[name].invul_timestamp = time_now + player:get_meta():set_int("mcl_damage:damage_animation", 1) + minetest.after(0.5, function() + player:get_meta():set_int("mcl_damage:damage_animation", 0) + end) + end + end +end) minetest.register_on_respawnplayer(function(player) local pos = player:get_pos()