Merge pull request 'Finish PVP Combat Parity with the rest + PVP Tweaks' (#4078) from Eliy21/MineClone2:combat_fixes into master

Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/4078
Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
This commit is contained in:
the-real-herowl 2023-12-30 04:21:18 +00:00
commit d11526f8e8
6 changed files with 107 additions and 20 deletions

View file

@ -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?

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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()