2022-10-03 18:51:13 +02:00
|
|
|
local function random_2dvectors() end
|
|
|
|
local last_pls_y_velocity = {} -- pl_name = y_velocity
|
|
|
|
local get_node = minetest.get_node
|
|
|
|
local get_pl_by_name = minetest.get_player_by_name
|
2022-10-20 21:30:09 +02:00
|
|
|
local T = fbrawl.T
|
2022-10-03 18:51:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fbrawl.replace_slot_item(player, slot, item)
|
|
|
|
local inv = player:get_inventory()
|
|
|
|
local list = inv:get_list("main")
|
|
|
|
list[slot] = ItemStack(item)
|
|
|
|
|
|
|
|
inv:set_list("main", list)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fbrawl.hit_player(puncher, player, damage)
|
|
|
|
player:set_hp(player:get_hp() - damage, {
|
|
|
|
type = "punch",
|
|
|
|
object = puncher,
|
|
|
|
from = "mod"
|
|
|
|
})
|
2022-10-13 23:46:04 +02:00
|
|
|
|
|
|
|
player:punch(puncher, 2, {damage_groups = {fleshy = damage}})
|
2022-10-03 18:51:13 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fbrawl.is_on_the_ground(player)
|
|
|
|
local pl_name = player:get_player_name()
|
|
|
|
local under_pl_feet = player:get_pos()
|
|
|
|
local pl_velocity = player:get_velocity()
|
|
|
|
local last_y_velocity = last_pls_y_velocity[pl_name] or pl_velocity.y
|
|
|
|
|
|
|
|
under_pl_feet.y = under_pl_feet.y - 0.4
|
|
|
|
|
|
|
|
local is_on_the_ground =
|
|
|
|
not (get_node(under_pl_feet).name == "air")
|
|
|
|
or (pl_velocity.y == 0 and last_y_velocity < 0)
|
|
|
|
|
|
|
|
last_pls_y_velocity[pl_name] = pl_velocity.y
|
|
|
|
|
|
|
|
return is_on_the_ground
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-10-08 17:09:54 +02:00
|
|
|
function fbrawl.area_raycast_up(center, radius, ray_length, objects, liquids)
|
2022-10-03 18:51:13 +02:00
|
|
|
local ray_distance = 0.5
|
2022-10-08 17:09:54 +02:00
|
|
|
local radius_x, radius_z
|
|
|
|
|
2022-10-03 18:51:13 +02:00
|
|
|
if type(radius) == "number" then
|
|
|
|
radius_x = radius
|
|
|
|
radius_z = radius
|
|
|
|
else
|
|
|
|
radius_x = radius.x
|
|
|
|
radius_z = radius.z
|
|
|
|
end
|
|
|
|
|
|
|
|
local start_pos = {x = center.x - radius_x, y = center.y + 0.5, z = center.z - radius_z}
|
|
|
|
local final_pos = {x = center.x + radius_x, y = center.y + 0.5, z = center.z + radius_z}
|
|
|
|
|
|
|
|
for x = start_pos.x, final_pos.x, ray_distance do
|
|
|
|
for z = start_pos.z, final_pos.z, ray_distance do
|
|
|
|
local pos1 = {x = x, y = start_pos.y, z = z}
|
2022-10-08 17:09:54 +02:00
|
|
|
local pos2 = vector.add(pos1, {x = 0, y = ray_length, z = 0})
|
2022-10-03 18:51:13 +02:00
|
|
|
local result = minetest.raycast(pos1, pos2, objects, liquids):next()
|
|
|
|
|
|
|
|
if result then
|
|
|
|
return result
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- TODO: improve
|
|
|
|
function fbrawl.camera_shake(pl_name, duration, strength, offsets, next_offset, eye_offset, last)
|
|
|
|
local player = get_pl_by_name(pl_name)
|
|
|
|
local speed = 0.4
|
|
|
|
local last = last or false
|
|
|
|
offsets = offsets or random_2dvectors(duration, strength)
|
|
|
|
next_offset = next_offset or 1
|
|
|
|
|
|
|
|
if not player then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- When offsets finish go back to zero
|
|
|
|
if next_offset > #offsets then
|
|
|
|
offsets[next_offset] = {x = 0, y = 0}
|
|
|
|
last = true
|
|
|
|
end
|
|
|
|
|
|
|
|
eye_offset = eye_offset or player:get_eye_offset()
|
|
|
|
local target_offset = offsets[next_offset]
|
|
|
|
local new_offset = {
|
|
|
|
x = fbrawl.interpolate(eye_offset.x, target_offset.x, speed),
|
|
|
|
y = fbrawl.interpolate(eye_offset.y, target_offset.y, speed),
|
|
|
|
z = 0
|
|
|
|
}
|
|
|
|
eye_offset = new_offset
|
|
|
|
|
|
|
|
-- If new_offset and eye_offset are equal go to the next offset or return if it was
|
|
|
|
-- the last offset
|
|
|
|
if target_offset.x == eye_offset.x and target_offset.y == eye_offset.y then
|
|
|
|
if last then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
next_offset = next_offset + 1
|
|
|
|
else
|
|
|
|
player:set_eye_offset(new_offset, new_offset)
|
|
|
|
end
|
|
|
|
|
|
|
|
minetest.after(0, function()
|
2022-10-30 01:25:19 +02:00
|
|
|
--fbrawl.camera_shake(pl_name, duration, strength, offsets, next_offset, eye_offset, last)
|
2022-10-03 18:51:13 +02:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fbrawl.reset_velocity(player)
|
|
|
|
player:add_velocity(vector.multiply(player:get_velocity(), -1))
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fbrawl.interpolate(a, b, factor)
|
|
|
|
local distance = math.abs(a-b)
|
|
|
|
local min_step = 0.1
|
|
|
|
local step = distance * factor
|
|
|
|
if step < min_step then step = min_step end
|
|
|
|
|
|
|
|
if a > b then
|
|
|
|
a = a - step
|
|
|
|
if a <= b then
|
|
|
|
a = b
|
|
|
|
end
|
|
|
|
else
|
|
|
|
a = a + step
|
|
|
|
if a >= b then
|
|
|
|
a = b
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return a
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-10-30 00:29:42 +02:00
|
|
|
function fbrawl.vec_interpolate(a, b, factor)
|
|
|
|
local i = fbrawl.interpolate
|
|
|
|
local f = factor
|
|
|
|
local interpolated_vec = {x=i(a.x, b.x, f), y=i(a.y, b.y, f), z=i(a.z, b.z, f)}
|
|
|
|
|
|
|
|
return interpolated_vec
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-10-29 17:36:41 +02:00
|
|
|
function fbrawl.damage_players_near(puncher, pos, range, damage, knockback, callback)
|
2022-10-04 12:29:09 +02:00
|
|
|
-- todo: iterare giocatori in arena
|
|
|
|
for _, hit_pl in pairs(minetest.get_connected_players()) do
|
|
|
|
local hit_pl_pos = vector.add({x=0, y=1, z=0}, hit_pl:get_pos())
|
|
|
|
|
|
|
|
local distance = vector.distance(pos, hit_pl_pos)
|
|
|
|
|
|
|
|
if hit_pl == puncher then distance = 9999 end
|
|
|
|
|
|
|
|
if distance <= range then
|
2022-10-13 23:46:04 +02:00
|
|
|
fbrawl.hit_player(puncher, hit_pl, damage)
|
|
|
|
|
|
|
|
if knockback then
|
|
|
|
hit_pl:add_velocity(knockback)
|
|
|
|
end
|
2022-10-29 02:22:18 +02:00
|
|
|
|
2022-10-29 17:36:41 +02:00
|
|
|
if callback then
|
|
|
|
callback(hit_pl:get_player_name())
|
2022-10-29 02:22:18 +02:00
|
|
|
end
|
2022-10-04 12:29:09 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-10-03 18:51:13 +02:00
|
|
|
function random_2dvectors(amount, strength)
|
|
|
|
local rnd = PcgRandom(os.time())
|
|
|
|
local vectors = {}
|
|
|
|
|
|
|
|
for i = 1, amount, 1 do
|
|
|
|
local rnd_vector = {
|
|
|
|
x = rnd:next(-1, 1) * strength,
|
|
|
|
y = rnd:next(-1, 1) * strength,
|
|
|
|
}
|
|
|
|
|
|
|
|
table.insert(vectors, rnd_vector)
|
|
|
|
end
|
|
|
|
|
|
|
|
return vectors
|
|
|
|
end
|
2022-10-08 17:09:54 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fbrawl.pl_look_at(player, target)
|
|
|
|
local pos = player:get_pos()
|
|
|
|
local delta = vector.subtract(target, pos)
|
|
|
|
player:set_look_horizontal(math.atan2(delta.z, delta.x) - math.pi / 2)
|
2022-10-20 21:30:09 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fbrawl.define_winner(arena)
|
2022-10-26 01:46:18 +02:00
|
|
|
if arena.in_celebration then return end
|
|
|
|
|
|
|
|
local best_pl = T("Nobody")
|
2022-10-20 21:30:09 +02:00
|
|
|
local best_kills = 0
|
|
|
|
|
|
|
|
for pl_name, props in pairs(arena.players) do
|
|
|
|
if props.kills > best_kills then
|
|
|
|
best_pl = pl_name
|
|
|
|
best_kills = props.kills
|
|
|
|
end
|
|
|
|
end
|
2022-10-26 01:46:18 +02:00
|
|
|
|
2022-10-20 21:30:09 +02:00
|
|
|
arena_lib.load_celebration("fbrawl", arena, best_pl)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fbrawl.can_cast_ultimate(pl_name)
|
|
|
|
local arena = arena_lib.get_arena_by_player(pl_name)
|
|
|
|
return arena.players[pl_name].ultimate_recharge >= fbrawl.min_kills_to_use_ultimate
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fbrawl.cast_ultimate(pl_name, skill_name, args)
|
|
|
|
local skill = pl_name:get_skill(skill_name)
|
|
|
|
if not skill then return false end
|
|
|
|
|
|
|
|
local arena = arena_lib.get_arena_by_player(pl_name)
|
|
|
|
local props = arena.players[pl_name]
|
|
|
|
|
|
|
|
if not fbrawl.can_cast_ultimate(pl_name) then
|
|
|
|
local pls_to_kill = fbrawl.min_kills_to_use_ultimate - props.ultimate_recharge
|
|
|
|
skillz.error(pl_name, T("You have to kill other @1 people!", pls_to_kill))
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
props.ultimate_recharge = 0
|
|
|
|
|
|
|
|
if skill.loop_params then
|
|
|
|
pl_name:start_skill(skill_name, args)
|
|
|
|
else
|
|
|
|
pl_name:cast_skill(skill_name, args)
|
|
|
|
end
|
2022-10-26 01:46:18 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fbrawl.are_there_nodes_in_area(pos, range)
|
|
|
|
range = range - 0.5
|
|
|
|
local get_node = minetest.get_node
|
|
|
|
local min_edge = vector.subtract(pos, range)
|
|
|
|
local max_edge = vector.add(pos, range)
|
|
|
|
local area = VoxelArea:new({MinEdge = min_edge, MaxEdge = max_edge})
|
|
|
|
|
|
|
|
for i in area:iterp(min_edge, max_edge) do
|
|
|
|
local pos = area:position(i)
|
|
|
|
local node_name = get_node(pos).name
|
|
|
|
|
|
|
|
if node_name ~= "ignore" and node_name ~= "air" then return true end
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|