yeah, so... I forgot I made this repo, anyway here's what we've got this far (very WIP)
21
SETTINGS.lua
Normal file
@ -0,0 +1,21 @@
|
||||
--[[
|
||||
! WARNING !
|
||||
Don't change the variables names if you don't know what you're doing!
|
||||
|
||||
(fbrawl_settings.variable_name = value)
|
||||
]]
|
||||
|
||||
|
||||
-- ARENA LIB'S SETTINGS --
|
||||
|
||||
-- The table that stores all the global variables, don't touch this.
|
||||
fbrawl_settings = {}
|
||||
|
||||
-- The maximum amount of time between the loading state and the start of the match.
|
||||
fbrawl_settings.max_loading_time = 10
|
||||
|
||||
-- The time between the end of the match and the respawn at the hub.
|
||||
fbrawl_settings.celebration_time = 5
|
||||
|
||||
-- What's going to appear in most of the lines printed by fantasy brawl.
|
||||
fbrawl_settings.prefix = "Fantasy Brawl > "
|
76
_arena_lib/arena_callbacks.lua
Normal file
@ -0,0 +1,76 @@
|
||||
local function on_load() end
|
||||
local T = fbrawl.T
|
||||
|
||||
|
||||
|
||||
arena_lib.on_enable("fbrawl", function(arena, pl_name)
|
||||
return true
|
||||
end)
|
||||
|
||||
|
||||
|
||||
arena_lib.on_start("fbrawl", function(arena)
|
||||
arena.match_id = math.random(1, 9999999999)
|
||||
|
||||
arena_lib.send_message_in_arena(
|
||||
arena,
|
||||
"players",
|
||||
minetest.colorize("#f9a31b",
|
||||
fbrawl_settings.prefix ..
|
||||
T(
|
||||
"You have @1 seconds to choose your class!",
|
||||
fbrawl_settings.max_loading_time
|
||||
)
|
||||
)
|
||||
)
|
||||
arena_lib.HUD_send_msg_all(
|
||||
"broadcast",
|
||||
arena,
|
||||
T("Read your items' description to learn their utility"),
|
||||
fbrawl_settings.max_loading_time
|
||||
)
|
||||
|
||||
minetest.after(fbrawl_settings.max_loading_time, function() on_load(arena) end)
|
||||
end)
|
||||
|
||||
|
||||
|
||||
arena_lib.on_celebration("fbrawl", function(arena, winner_name)
|
||||
for pl_name, _ in pairs(arena.players) do
|
||||
arena.classes[pl_name]:on_end(arena, pl_name)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
arena_lib.on_death("fbrawl", function(arena, pl_name, reason)
|
||||
arena.classes[pl_name]:on_death(arena, pl_name, reason)
|
||||
end)
|
||||
|
||||
|
||||
|
||||
arena_lib.on_timeout("fbrawl", function(arena)
|
||||
-- cose
|
||||
end)
|
||||
|
||||
|
||||
|
||||
arena_lib.on_quit("fbrawl", function(arena, pl_name, is_spectator)
|
||||
-- cose
|
||||
end)
|
||||
|
||||
|
||||
|
||||
arena_lib.on_time_tick("fbrawl", function(arena)
|
||||
for pl_name, _ in pairs(arena.players) do
|
||||
fbrawl.update_HUD(pl_name, "timer_ID", arena.current_time)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
arena_lib.on_load("fbrawl", function(arena)
|
||||
for pl_name in pairs(arena.players) do
|
||||
arena.classes[pl_name]:on_start(arena, pl_name)
|
||||
end
|
||||
end
|
15
_arena_lib/arena_utils.lua
Normal file
@ -0,0 +1,15 @@
|
||||
local function apply_class() end
|
||||
local T = fbrawl.T
|
||||
|
||||
|
||||
|
||||
function fbrawl.is_player_playing(pl_name)
|
||||
local arena = arena_lib.get_arena_by_player(pl_name)
|
||||
return arena and not arena.in_celebration and not arena.in_loading and not arena.in_queue
|
||||
end
|
||||
|
||||
|
||||
|
||||
function fbrawl.prekick_operations(pl_name)
|
||||
fbrawl.remove_HUD(pl_name)
|
||||
end
|
170
_classes/classes_system.lua
Normal file
@ -0,0 +1,170 @@
|
||||
--[[
|
||||
When the code refers to the player'S class it means the class table
|
||||
associated to him/her in the arena.classes[pl_name] property.
|
||||
|
||||
The definition table to put in register_class() is the following:
|
||||
{
|
||||
name : string =
|
||||
the class name, it is automatically translated in chat
|
||||
messages.
|
||||
|
||||
items : { "name" or {name : string}, ...} =
|
||||
the items that the player will receive when the match starts.
|
||||
|
||||
skills : {"skill1", ...} =
|
||||
the skills that the player will unlock.
|
||||
|
||||
physics_override : {...}
|
||||
|
||||
HUD_timer : string =
|
||||
a custom texture for the timer HUD.
|
||||
|
||||
sound : string =
|
||||
the sound that will be reproduced to the player when this class
|
||||
will be assigned to them.
|
||||
|
||||
on_start : function(self, arena, pl_name) =
|
||||
this gets called when this class gets assigned to pl_name. self
|
||||
is the class table assigned to the player while pl_name is his/her
|
||||
name.
|
||||
|
||||
on_end : function(self, arena, pl_name) =
|
||||
this gets called when the match finishes (on_celebration).
|
||||
|
||||
on_death : function(self, arena, pl_name, reason) =
|
||||
this gets called when the player dies.
|
||||
|
||||
on_kill : function(self, arena, pl_name, killed_pl_name) =
|
||||
this gets called when the player kills someone.
|
||||
|
||||
... other functions or custom properties, just make sure
|
||||
that their names don't conflict with the already existing
|
||||
ones.
|
||||
}
|
||||
]]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
local function get_valid_class() end
|
||||
local function set_callbacks() end
|
||||
local function set_physics() end
|
||||
fbrawl.classes = {} -- index : number = class : {}
|
||||
local T = fbrawl.T
|
||||
|
||||
|
||||
|
||||
function fbrawl.register_class(name, def)
|
||||
def = get_valid_class(name, def)
|
||||
fbrawl.classes[#fbrawl.classes+1] = def
|
||||
end
|
||||
|
||||
|
||||
|
||||
function fbrawl.apply_class(pl_name, class)
|
||||
local player = minetest.get_player_by_name(pl_name)
|
||||
local player_inv = player:get_inventory()
|
||||
local arena = arena_lib.get_arena_by_player(pl_name)
|
||||
|
||||
-- Adding the class' items to the player.
|
||||
for i, item in pairs(class.items) do
|
||||
local item_name = item.name or item
|
||||
|
||||
player_inv:add_item("main", ItemStack(item_name))
|
||||
end
|
||||
|
||||
-- Unlocking the player's skins.
|
||||
for i, skill_name in pairs(class.skills) do
|
||||
player_inv:unlock_skill(skill_name)
|
||||
end
|
||||
|
||||
player:set_physics_override(class.physics_override)
|
||||
|
||||
--minetest.sound_play(class.sound, {to_player = pl_name})
|
||||
end
|
||||
|
||||
|
||||
|
||||
function fbrawl.get_class_by_name(name)
|
||||
for i, class in pairs(fbrawl.classes) do
|
||||
if class.name:lower() == name:lower() then return class end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function get_valid_class(name, class)
|
||||
set_physics(class)
|
||||
set_callbacks(class)
|
||||
|
||||
assert(
|
||||
class.name or class.hotbar_description or class.items or class.skills
|
||||
"A class hasn't been configured correctly ("..name..")!"
|
||||
)
|
||||
assert(
|
||||
not fbrawl.get_class_by_name(class.name),
|
||||
"Two classes have the same name ("..name..")!"
|
||||
)
|
||||
|
||||
return class
|
||||
end
|
||||
|
||||
|
||||
|
||||
function set_callbacks(class)
|
||||
local empty_func = function() end
|
||||
local on_death = class.on_death or empty_func
|
||||
local on_end = class.on_end or empty_func
|
||||
local on_eliminated = class.on_eliminated or empty_func
|
||||
local on_start = class.on_start or empty_func
|
||||
local on_kill = class.on_kill or empty_func
|
||||
|
||||
class.on_start = function(self, arena, pl_name)
|
||||
local player = minetest.get_player_by_name(pl_name)
|
||||
self.in_game = true
|
||||
|
||||
fbrawl.generate_HUD(arena, pl_name)
|
||||
-- Hiding the wielded item if 3d_armor is installed.
|
||||
player:get_meta():set_int("show_wielded_item", 2)
|
||||
|
||||
on_start(self, arena, pl_name)
|
||||
end
|
||||
|
||||
class.on_kill = function(self, arena, pl_name, killed_pl_name)
|
||||
on_kill(self, arena, pl_name, killed_pl_name)
|
||||
end
|
||||
|
||||
class.on_death = function(self, arena, pl_name, reason)
|
||||
on_death(self, arena, pl_name, reason)
|
||||
|
||||
-- If the player was killed using fbrawl.kill_player().
|
||||
if reason and reason.type == "punch" then
|
||||
local killer_name = reason.object:get_player_name()
|
||||
local killer_class = arena.classes[killer_name]
|
||||
|
||||
fbrawl.print_msg(pl_name, T("@1 (@2) killed you!", killer_name, T(killer_class.name)))
|
||||
killer_class:on_kill(arena, killer_name, pl_name)
|
||||
end
|
||||
end
|
||||
|
||||
class.on_end = function(self, arena, pl_name)
|
||||
fbrawl.prekick_operations(pl_name)
|
||||
on_end(self, arena, pl_name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function set_physics(class)
|
||||
local phys = class.physics_override or {}
|
||||
phys.speed = phys.speed or 1.2
|
||||
phys.gravity = phys.gravity or 1
|
||||
phys.acceleration = phys.acceleration or 1
|
||||
phys.jump = phys.jump or 1
|
||||
phys.sneak = phys.sneak or true
|
||||
phys.sneak_glitch = phys.sneak_glitch or false
|
||||
phys.new_move = phys.new_move or true
|
||||
|
||||
class.physics_override = phys
|
||||
end
|
18
_classes/mage/items.lua
Normal file
@ -0,0 +1,18 @@
|
||||
local T = fbrawl.T
|
||||
|
||||
|
||||
|
||||
minetest.register_craftitem("fantasy_brawl:mage_staff", {
|
||||
description = T("Pew pew them with magical bullets!"),
|
||||
inventory_image = "fbrawl_mage_staff.png",
|
||||
stack_max = 1,
|
||||
on_drop = function() return end,
|
||||
on_use = function(itemstack, player)
|
||||
local pl_name = player:get_player_name()
|
||||
local sound = {name = "fbrawl_mage_staff", pos = player:get_pos(), max_hear_distance = 12}
|
||||
|
||||
if pl_name:cast_skill("fbrawl:magic_bullet") then
|
||||
minetest.sound_play(sound, sound, true)
|
||||
end
|
||||
end
|
||||
})
|
13
_classes/mage/mage.lua
Normal file
@ -0,0 +1,13 @@
|
||||
fbrawl.register_class("mage", {
|
||||
name = "Mage",
|
||||
physics_override = {
|
||||
speed = 1.5,
|
||||
gravity = 0.9
|
||||
},
|
||||
items = {"fbrawl:mage_staff", "fbrawl:"},
|
||||
skills = {"fbrawl:smash"},
|
||||
sound = "mage-class"
|
||||
})
|
||||
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/mage/skills/magic_bullet.lua")
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/mage/items.lua")
|
148
_classes/mage/skills/magic_bullet.lua
Normal file
@ -0,0 +1,148 @@
|
||||
local function look_raycast() end
|
||||
local T = fbrawl.T
|
||||
|
||||
|
||||
|
||||
skillz.register_skill("fbrawl:magic_bullet", {
|
||||
name = "Magic bullet",
|
||||
slot = 1,
|
||||
cooldown = 1.5,
|
||||
chat_warnings = {
|
||||
cooldown = false
|
||||
},
|
||||
--sounds = {
|
||||
-- cast = {name = ""}
|
||||
--},
|
||||
cast = function(self)
|
||||
local cast_starting_pos = vector.add({x=0, y=0.9, z=0}, self.player:get_pos())
|
||||
minetest.add_entity(cast_starting_pos, "fantasy_brawl:magic_bullet", self.pl_name)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
|
||||
-- The magic bullet entity declaration.
|
||||
local magic_bullet = {
|
||||
initial_properties = {
|
||||
hp_max = 999,
|
||||
physical = true,
|
||||
collide_with_objects = false,
|
||||
collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
|
||||
visual = "sprite",
|
||||
visual_size = {x = 1, y = 1},
|
||||
textures = {"fbrawl_mage_bullet_entity.png"},
|
||||
spritediv = {x = 1, y = 1},
|
||||
initial_sprite_basepos = {x = 0, y = 0},
|
||||
speed = 50,
|
||||
range = 1,
|
||||
damage = 4
|
||||
},
|
||||
pl_name = "",
|
||||
hit = false,
|
||||
time_passed = 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- staticdata = player's username.
|
||||
function magic_bullet:on_activate(staticdata, dtime_s)
|
||||
local obj = self.object
|
||||
|
||||
if staticdata then
|
||||
self.pl_name = staticdata
|
||||
local player = minetest.get_player_by_name(self.pl_name)
|
||||
|
||||
if not player then
|
||||
obj:remove()
|
||||
return
|
||||
end
|
||||
|
||||
local dir = player:get_look_dir()
|
||||
local bullet_props = self.initial_properties
|
||||
|
||||
obj:set_velocity({
|
||||
x=(dir.x * bullet_props.speed),
|
||||
y=(dir.y * bullet_props.speed),
|
||||
z=(dir.z * bullet_props.speed),
|
||||
})
|
||||
else
|
||||
obj:remove()
|
||||
return
|
||||
end
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount = 80,
|
||||
time = 0,
|
||||
minpos = {x = -0.2, y = 0, z = -0.2},
|
||||
maxpos = {x = 0.2, y = 0.2, z = 0.2},
|
||||
minvel = {x = 0, y = -0.3, z = 0},
|
||||
maxvel = {x = 0, y = -0.3, z = 0},
|
||||
minsize = 4,
|
||||
maxsize = 6,
|
||||
texture = {
|
||||
name = "fbrawl_mage_bullet_entity.png",
|
||||
alpha_tween = {1, 0}
|
||||
},
|
||||
minexptime = 1.5,
|
||||
maxexptime = 1.5,
|
||||
attached = obj
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
|
||||
function magic_bullet:remove()
|
||||
local sound = {name = "fbrawl_magic_bullet", pos = self.object:get_pos(), max_hear_distance = 16}
|
||||
|
||||
minetest.sound_play(sound, sound, true)
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount = 40,
|
||||
time = 0.3,
|
||||
minvel = {x = -2, y = -2, z = -2},
|
||||
maxvel = {x = 2, y = 2, z = 2},
|
||||
minsize = 4,
|
||||
maxsize = 6,
|
||||
texture = {
|
||||
name = "fbrawl_mage_bullet_entity.png",
|
||||
alpha_tween = {1, 0}
|
||||
},
|
||||
minexptime = 1,
|
||||
maxexptime = 1.5,
|
||||
pos = self.object:get_pos()
|
||||
})
|
||||
|
||||
self.object:remove()
|
||||
end
|
||||
|
||||
|
||||
|
||||
function magic_bullet:on_step(dtime, moveresult)
|
||||
local player = minetest.get_player_by_name(self.pl_name)
|
||||
|
||||
if not player or moveresult.collides == true then
|
||||
self:remove()
|
||||
return
|
||||
end
|
||||
|
||||
local arena = arena_lib.get_arena_by_player(self.pl_name)
|
||||
|
||||
-- todo: iterare giocatori in arena
|
||||
for i, 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 bullet_pos = self.object:get_pos()
|
||||
local distance = vector.distance(bullet_pos, hit_pl_pos)
|
||||
|
||||
if hit_pl == player then distance = 9999 end
|
||||
|
||||
if distance <= self.initial_properties.range then
|
||||
fbrawl.hit_player(player, hit_pl, self.initial_properties.damage)
|
||||
self:remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
minetest.register_entity("fantasy_brawl:magic_bullet", magic_bullet)
|
101
_classes/mana.lua
Normal file
@ -0,0 +1,101 @@
|
||||
skillz.register_skill("fbrawl:mana", {
|
||||
name = "fbrawl:mana",
|
||||
passive = true,
|
||||
hud = {{
|
||||
name = "bar",
|
||||
hud_elem_type = "image",
|
||||
text = "fbrawl_manabar_hud.png",
|
||||
position = {x=0.57, y=0.91},
|
||||
scale = {x=13, y=1.1}
|
||||
}},
|
||||
data = {
|
||||
amount = 100
|
||||
},
|
||||
loop_params = {
|
||||
cast_rate = 0.05,
|
||||
},
|
||||
recharge_duration = 10,
|
||||
|
||||
-- "PUBLIC" FUNCTIONS
|
||||
set = function(self, new_amount)
|
||||
if new_amount < 0 then
|
||||
new_amount = 0
|
||||
elseif new_amount > 100 then
|
||||
new_amount = 100
|
||||
end
|
||||
|
||||
self.data.amount = new_amount
|
||||
end,
|
||||
add = function(self, amount)
|
||||
self:set(self.data.amount + amount)
|
||||
end,
|
||||
sub = function(self, amount)
|
||||
self:set(self.data.amount - amount)
|
||||
end,
|
||||
|
||||
-- SKILL LOGIC
|
||||
cast = function(self)
|
||||
local recharge_step = 100 / self.recharge_duration * self.loop_params.cast_rate
|
||||
self:add(recharge_step)
|
||||
self:update_bar_size()
|
||||
self:update_bar_color()
|
||||
end,
|
||||
|
||||
-- "PRIVATE" FUNCTIONS
|
||||
update_bar_size = function(self)
|
||||
local max_length = 13
|
||||
local progress = self.data.amount/100
|
||||
local scale_x = progress * max_length
|
||||
local x_offset = 0.06083 - (progress * 0.06083)
|
||||
|
||||
self.player:hud_change(self.data._hud["bar"], "scale", {x=scale_x, y=1.1})
|
||||
self.player:hud_change(self.data._hud["bar"], "position", {x=0.57-x_offset, y=0.912})
|
||||
end,
|
||||
update_bar_color = function(self)
|
||||
local wielded_item_name = self.player:get_wielded_item():get_name()
|
||||
local skill = self.pl_name:get_skill(wielded_item_name:gsub("fantasy_brawl", "fbrawl"))
|
||||
|
||||
if skill and skill.mana then
|
||||
if not fbrawl.has_enough_mana(skill) then
|
||||
self.player:hud_change(self.data._hud["bar"], "text", "fbrawl_manabar_nomana_hud.png")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
self.player:hud_change(self.data._hud["bar"], "text", "fbrawl_manabar_hud.png")
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
|
||||
function fbrawl.consume_mana(skill)
|
||||
if fbrawl.has_enough_mana(skill) then
|
||||
local mana_skill = skill.pl_name:get_skill("fbrawl:mana")
|
||||
|
||||
if skill.cooldown_timer > 0 then
|
||||
skill:cast() --
|
||||
skill:start() -- this will print an error in the chat
|
||||
return false
|
||||
end
|
||||
|
||||
mana_skill:sub(skill.mana)
|
||||
|
||||
return true
|
||||
else
|
||||
-- todo: sound
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function fbrawl.has_enough_mana(skill)
|
||||
local mana_skill = skill.pl_name:get_skill("fbrawl:mana")
|
||||
|
||||
if skill.mana and mana_skill and mana_skill.is_active then
|
||||
return mana_skill.data.amount >= skill.mana
|
||||
else
|
||||
-- todo: sound
|
||||
return false
|
||||
end
|
||||
end
|
125
_classes/warrior/items.lua
Normal file
@ -0,0 +1,125 @@
|
||||
local T = fbrawl.T
|
||||
|
||||
|
||||
|
||||
minetest.register_craftitem("fantasy_brawl:sword", {
|
||||
description = T("Slice 'em all!"),
|
||||
inventory_image = "fbrawl_sword_item.png",
|
||||
stack_max = 1,
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 1.0,
|
||||
damage_groups = {fleshy = 4},
|
||||
},
|
||||
on_drop = function() return end,
|
||||
wield_image = "fbrawl_sword_item.png"
|
||||
})
|
||||
|
||||
|
||||
|
||||
minetest.register_craftitem("fantasy_brawl:warrior_jump", {
|
||||
description = T("Jump very high to crush them better!"),
|
||||
inventory_image = "fbrawl_smash_skill.png",
|
||||
stack_max = 1,
|
||||
on_drop = function() return end,
|
||||
on_use =
|
||||
function(itemstack, player)
|
||||
if fbrawl.is_on_the_ground(player) then
|
||||
local pl_name = player:get_player_name()
|
||||
local warrior_jump = pl_name:get_skill("fbrawl:warrior_jump")
|
||||
|
||||
if warrior_jump and fbrawl.consume_mana(warrior_jump) then
|
||||
warrior_jump:cast()
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
|
||||
minetest.register_craftitem("fantasy_brawl:smash", {
|
||||
description = T("Time to go back down!"),
|
||||
inventory_image = "fbrawl_smash_item.png",
|
||||
stack_max = 1,
|
||||
on_drop = function() return end,
|
||||
on_use =
|
||||
function(itemstack, player)
|
||||
local pl_name = player:get_player_name()
|
||||
local jump_skill = pl_name:get_skill("fbrawl:warrior_jump")
|
||||
|
||||
if jump_skill then
|
||||
local fall_force = -jump_skill.jump_force * 2
|
||||
|
||||
player:add_player_velocity({x = 0, y = fall_force, z = 0})
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
|
||||
minetest.register_craftitem("fantasy_brawl:iron_skin", {
|
||||
description = T("It's getting pretty tough!"),
|
||||
inventory_image = "fbrawl_iron_skin_skill.png",
|
||||
stack_max = 1,
|
||||
on_drop = function() return end,
|
||||
on_use =
|
||||
function(itemstack, player)
|
||||
local pl_name = player:get_player_name()
|
||||
local iron_skin = pl_name:get_skill("fbrawl:iron_skin")
|
||||
|
||||
if iron_skin and not iron_skin.is_active and fbrawl.consume_mana(iron_skin) then
|
||||
iron_skin:start()
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
|
||||
minetest.register_craftitem("fantasy_brawl:perfect_combo", {
|
||||
description = T("A combo they won't forget!"),
|
||||
inventory_image = "fbrawl_perfect_combo_skill.png",
|
||||
stack_max = 1,
|
||||
on_drop = function() return end,
|
||||
})
|
||||
|
||||
|
||||
|
||||
minetest.register_craftitem("fantasy_brawl:hero_fury", {
|
||||
description = T("Unleash the fury of the strongest warrior alive!"),
|
||||
inventory_image = "fbrawl_hero_fury_skill.png",
|
||||
stack_max = 1,
|
||||
on_drop = function() return end,
|
||||
})
|
||||
|
||||
|
||||
|
||||
minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
|
||||
local pl_name = hitter:get_player_name()
|
||||
local hit_pl_name = player:get_player_name()
|
||||
local wielded_item = hitter:get_wielded_item():get_name()
|
||||
|
||||
local perfect_combo = pl_name:get_skill("fbrawl:perfect_combo")
|
||||
local hero_fury = pl_name:get_skill("fbrawl:hero_fury")
|
||||
|
||||
if
|
||||
wielded_item == "fantasy_brawl:perfect_combo"
|
||||
and perfect_combo
|
||||
and not perfect_combo.is_active
|
||||
and fbrawl.consume_mana(perfect_combo)
|
||||
then
|
||||
perfect_combo:start(player)
|
||||
end
|
||||
|
||||
if
|
||||
wielded_item == "fantasy_brawl:hero_fury"
|
||||
and hero_fury
|
||||
and not hero_fury.is_active
|
||||
and fbrawl.consume_mana(hero_fury)
|
||||
then
|
||||
if not fbrawl.area_raycast_up(player:get_pos(), 10, 25, false) then
|
||||
hero_fury:start(player:get_player_name())
|
||||
else
|
||||
-- todo: funzione error con tanto di suono
|
||||
minetest.chat_send_player(pl_name, T("There's not enough space here!"))
|
||||
end
|
||||
end
|
||||
end)
|
223
_classes/warrior/skills/hero_fury.lua
Normal file
@ -0,0 +1,223 @@
|
||||
local function hit() end
|
||||
local function look_at() end
|
||||
|
||||
|
||||
|
||||
skillz.register_skill("fbrawl:hero_fury", {
|
||||
name = "fbrawl:hero_fury",
|
||||
mana = 0,
|
||||
loop_params = {
|
||||
cast_rate = 0.2,
|
||||
},
|
||||
damage = 4,
|
||||
slot = 4,
|
||||
upward_force = 50,
|
||||
punch_force = 20,
|
||||
data = {
|
||||
hits = 0,
|
||||
hit_player = nil
|
||||
},
|
||||
on_start = function(self)
|
||||
self.data.hits = 0
|
||||
end,
|
||||
cast = function(self, hit_pl_name)
|
||||
local hit_player = minetest.get_player_by_name(hit_pl_name)
|
||||
if not hit_player then return end
|
||||
self.data.hit_player = hit_player
|
||||
|
||||
local hit_pos = hit_player:get_pos()
|
||||
self.data.hits = self.data.hits + 1
|
||||
|
||||
if self.data.hits == 1 then
|
||||
fbrawl.reset_velocity(hit_player)
|
||||
fbrawl.reset_velocity(self.player)
|
||||
|
||||
self.player:set_physics_override({gravity = 0})
|
||||
hit_player:set_physics_override({gravity = 0})
|
||||
|
||||
hit_player:add_velocity({x=0, y=self.upward_force, z=0})
|
||||
|
||||
minetest.add_entity({x=0,y=0,z=0}, "fantasy_brawl:forward_punch", self.player:get_player_name())
|
||||
|
||||
hit_pl_name:unlock_skill("fbrawl:hit_by_hero_fury")
|
||||
minetest.after(0.2, function() hit_pl_name:start_skill("fbrawl:hit_by_hero_fury") end)
|
||||
|
||||
elseif self.data.hits == 3 then
|
||||
hit(self.player, hit_player, {x=1, y=0, z=0})
|
||||
|
||||
elseif self.data.hits == 4 then
|
||||
hit(self.player, hit_player, {x=-1, y=0, z=0})
|
||||
|
||||
elseif self.data.hits == 5 then
|
||||
hit(self.player, hit_player, {x=0, y=0, z=1})
|
||||
|
||||
elseif self.data.hits == 6 then
|
||||
hit(self.player, hit_player, {x=-1, y=0, z=-1})
|
||||
|
||||
elseif self.data.hits == 7 then
|
||||
hit(self.player, hit_player, {x=1, y=0, z=0})
|
||||
|
||||
elseif self.data.hits == 8 then
|
||||
hit(self.player, hit_player, {x=-1, y=0, z=0})
|
||||
|
||||
elseif self.data.hits == 9 then
|
||||
hit(self.player, hit_player, {x=0, y=0, z=1})
|
||||
|
||||
elseif self.data.hits == 10 then
|
||||
hit(self.player, hit_player, {x=-1, y=0, z=-1})
|
||||
|
||||
elseif self.data.hits == 12 then
|
||||
hit(self.player, hit_player, {x=0, y=1.5, z=0}, "last")
|
||||
|
||||
self.player:set_physics_override({gravity = 1})
|
||||
hit_player:set_physics_override({gravity = 1})
|
||||
|
||||
fbrawl.camera_shake(self.pl_name, 6, 0.4)
|
||||
|
||||
minetest.after(3, function() self:stop() end)
|
||||
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
minetest.sound_play({name = "punch"}, {pos = hit_pos, max_hear_distance = 6}, true)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
|
||||
skillz.register_skill("fbrawl:hit_by_hero_fury", {
|
||||
name = "fbrawl:hit_by_hero_fury",
|
||||
mana = 0,
|
||||
sounds = {
|
||||
bgm = {name="while_jumping", max_hear_distance = 6},
|
||||
stop = {name="smash", max_hear_distance = 6},
|
||||
},
|
||||
attachments = {
|
||||
particles = {{
|
||||
amount = 15,
|
||||
time = 0,
|
||||
minpos = {x = -0.3, y = 0, z = -0.3},
|
||||
maxpos = {x = 0.3, y = 0.5, z = 0.3},
|
||||
minvel = {x = 0, y = 0, z = 0},
|
||||
maxvel = {x = 0, y = 0, z = 0},
|
||||
minsize = 4,
|
||||
maxsize = 9,
|
||||
texture = "fbrawl_wjump_particle.png",
|
||||
minexptime = 1.5,
|
||||
maxexptime = 1.5,
|
||||
}}
|
||||
},
|
||||
cast = function(self, hit_player)
|
||||
if fbrawl.is_on_the_ground(self.player) or self.player:get_hp() == 0 then
|
||||
self:stop()
|
||||
end
|
||||
end,
|
||||
on_stop = function(self)
|
||||
minetest.add_particlespawner({
|
||||
amount = 40,
|
||||
time = 1,
|
||||
minpos = self.player:get_pos(),
|
||||
maxpos = self.player:get_pos(),
|
||||
minvel = {x = -4, y = 1, z = -4},
|
||||
maxvel = {x = 4, y = 2, z = 4},
|
||||
minsize = 10,
|
||||
maxsize = 12.2,
|
||||
texture = "fbrawl_wjump_particle.png",
|
||||
minexptime = 0.5,
|
||||
maxexptime = 0.5,
|
||||
})
|
||||
fbrawl.camera_shake(self.pl_name, 6, 0.4)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
|
||||
-------------------
|
||||
-- PUNCH ENTITY --
|
||||
-------------------
|
||||
|
||||
local forward_punch = {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
visual_size = {x = 1, y = 1},
|
||||
textures = {"fbrawl_punch_entity.png"},
|
||||
pointable = false,
|
||||
visual = "sprite",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
function forward_punch:on_activate(pl_name, dtime_s)
|
||||
if pl_name ~= "" then
|
||||
local hero_fury = pl_name:get_skill("fbrawl:hero_fury")
|
||||
local hit_player = hero_fury.data.hit_player
|
||||
|
||||
local entity_duration = 0.32
|
||||
local entity_speed = 9
|
||||
|
||||
local player = minetest.get_player_by_name(pl_name)
|
||||
local obj = self.object
|
||||
|
||||
local player_center = vector.add(player:get_pos(), {x=0, y=1, z=0})
|
||||
|
||||
local look_dir = player:get_look_dir()
|
||||
|
||||
obj:set_pos(player_center)
|
||||
obj:set_velocity(vector.multiply(look_dir, entity_speed))
|
||||
|
||||
-- Preventing the skill from killing the player,
|
||||
-- they have to die falling.k
|
||||
if hit_player:get_hp() > hero_fury.damage then
|
||||
fbrawl.hit_player(hero_fury.player, hit_player, hero_fury.damage)
|
||||
else
|
||||
hit_player:set_hp(1)
|
||||
end
|
||||
|
||||
minetest.after(entity_duration, function() obj:remove() end)
|
||||
else
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
minetest.register_entity("fantasy_brawl:forward_punch", forward_punch)
|
||||
|
||||
|
||||
|
||||
function hit(player, hit_player, offset, last)
|
||||
local hit_pl_pos = hit_player:get_pos()
|
||||
local punch_force = skillz.get_skill_def("fbrawl:hero_fury").punch_force
|
||||
|
||||
fbrawl.reset_velocity(player)
|
||||
fbrawl.reset_velocity(hit_player)
|
||||
|
||||
player:set_pos(vector.add(hit_pl_pos, offset))
|
||||
look_at(player, hit_pl_pos)
|
||||
look_at(hit_player, player:get_pos())
|
||||
|
||||
if last then
|
||||
player:set_look_vertical(2)
|
||||
punch_force = skillz.get_skill_def("fbrawl:hero_fury").upward_force
|
||||
else
|
||||
player:set_look_vertical(0)
|
||||
end
|
||||
|
||||
local hitter_look_dir = player:get_look_dir()
|
||||
|
||||
local push_force = vector.multiply(hitter_look_dir, punch_force)
|
||||
|
||||
minetest.add_entity({x=0,y=0,z=0}, "fantasy_brawl:forward_punch", player:get_player_name())
|
||||
|
||||
hit_player:add_velocity(push_force)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function 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)
|
||||
end
|
72
_classes/warrior/skills/iron_skin.lua
Normal file
@ -0,0 +1,72 @@
|
||||
skillz.register_skill("fbrawl:iron_skin", {
|
||||
name = "fbrawl:iron_skin",
|
||||
mana = 50,
|
||||
slot = 3,
|
||||
cooldown = 20,
|
||||
loop_params = {
|
||||
duration = 5,
|
||||
},
|
||||
chat_warnings = {
|
||||
cooldown = true
|
||||
},
|
||||
sounds = {
|
||||
start = {name = "iron_skin_on", max_hear_distance = 6},
|
||||
stop = {name = "iron_skin_off", max_hear_distance = 6},
|
||||
},
|
||||
attachments = {
|
||||
entities = {{
|
||||
name = "fantasy_brawl:shield",
|
||||
pos = {x = 0, y = 22, z = 0}
|
||||
}}
|
||||
},
|
||||
hud = {{
|
||||
name = "shield",
|
||||
hud_elem_type = "image",
|
||||
text = "fbrawl_iron_skin_skill.png",
|
||||
scale = {x=3, y=3},
|
||||
position = {x=0.5, y=0.82},
|
||||
}},
|
||||
})
|
||||
|
||||
|
||||
|
||||
minetest.register_on_player_hpchange(function(player, hp_change, reason)
|
||||
local pl_name = player:get_player_name()
|
||||
local iron_skin_skill = pl_name:get_skill("fbrawl:iron_skin")
|
||||
|
||||
if iron_skin_skill and iron_skin_skill.is_active and player:get_hp() > 2 then
|
||||
return hp_change / 2
|
||||
else
|
||||
return hp_change
|
||||
end
|
||||
end, true)
|
||||
|
||||
|
||||
|
||||
-------------------
|
||||
-- SHIELD ENTITY --
|
||||
-------------------
|
||||
|
||||
local shield = {
|
||||
initial_properties = {
|
||||
hp_max = 999,
|
||||
physical = false,
|
||||
visual_size = {x = 0.35, y = 0.35},
|
||||
textures = {"fbrawl_iron_skin_skill.png"},
|
||||
pointable = false,
|
||||
visual = "sprite",
|
||||
glow = 1
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
function shield:on_activate(pl_name, dtime_s)
|
||||
if pl_name == "" then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
minetest.register_entity("fantasy_brawl:shield", shield)
|
144
_classes/warrior/skills/perfect_combo.lua
Normal file
@ -0,0 +1,144 @@
|
||||
local random_seed_counter = 0
|
||||
|
||||
|
||||
|
||||
skillz.register_skill("fbrawl:perfect_combo", {
|
||||
name = "fbrawl:perfect_combo",
|
||||
mana = 75,
|
||||
loop_params = {
|
||||
cast_rate = 0.15,
|
||||
},
|
||||
damage = 2,
|
||||
slot = 4,
|
||||
data = {
|
||||
hits = 0
|
||||
},
|
||||
on_start = function(self)
|
||||
self.data.hits = 0
|
||||
end,
|
||||
cast = function(self, hit_player)
|
||||
local pl_name = hit_player:get_player_name()
|
||||
local hit_pos = hit_player:get_pos()
|
||||
self.data.hits = self.data.hits + 1
|
||||
|
||||
if self.data.hits == 1 then
|
||||
minetest.add_entity({x=0,y=0,z=0}, "fantasy_brawl:punch", pl_name)
|
||||
minetest.sound_play({name = "punch"}, {pos = hit_pos, max_hear_distance = 6}, true)
|
||||
|
||||
elseif self.data.hits == 2 then
|
||||
minetest.add_entity({x=0,y=0,z=0}, "fantasy_brawl:punch", pl_name)
|
||||
minetest.sound_play({name = "punch"}, {pos = hit_pos, max_hear_distance = 6}, true)
|
||||
|
||||
elseif self.data.hits == 3 then
|
||||
minetest.add_entity({x=0,y=0,z=0}, "fantasy_brawl:kick", pl_name)
|
||||
minetest.sound_play({name = "kick"}, {pos = hit_pos, max_hear_distance = 6}, true)
|
||||
|
||||
elseif self.data.hits == 4 then
|
||||
minetest.add_entity({x=0,y=0,z=0}, "fantasy_brawl:punch", pl_name)
|
||||
minetest.sound_play({name = "punch"}, {pos = hit_pos, max_hear_distance = 6}, true)
|
||||
|
||||
elseif self.data.hits == 5 then
|
||||
minetest.add_entity({x=0,y=0,z=0}, "fantasy_brawl:kick", pl_name)
|
||||
minetest.sound_play({name = "kick"}, {pos = hit_pos, max_hear_distance = 6}, true)
|
||||
fbrawl.hit_player(self.player, hit_player, self.damage)
|
||||
self:stop()
|
||||
end
|
||||
|
||||
fbrawl.hit_player(self.player, hit_player, self.damage)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
|
||||
local function entity_activate(lua_entity, pl_name)
|
||||
local entity_duration = 0.32
|
||||
local entity_speed = 9
|
||||
local push_multiplier = 5
|
||||
random_seed_counter = random_seed_counter + 1
|
||||
|
||||
local player = minetest.get_player_by_name(pl_name)
|
||||
local obj = lua_entity.object
|
||||
|
||||
local rnd = PseudoRandom(os.time() * random_seed_counter)
|
||||
local rnd_y = rnd:next(30, 50) / 100
|
||||
local rnd_x = rnd:next(-10, 10) / 20
|
||||
local rnd_z = rnd:next(-10, 10) / 20
|
||||
local rnd_offset = {x = rnd_x, y = rnd_y, z = rnd_z}
|
||||
|
||||
local pos = vector.add(player:get_pos(), rnd_offset)
|
||||
local player_center = vector.add(player:get_pos(), {x=0, y=1, z=0})
|
||||
|
||||
local dir_to_player = vector.direction(pos, player_center)
|
||||
local push_force = vector.multiply(dir_to_player, push_multiplier)
|
||||
|
||||
obj:set_pos(pos)
|
||||
obj:set_velocity(vector.multiply(dir_to_player, entity_speed))
|
||||
|
||||
player:add_velocity(push_force)
|
||||
|
||||
minetest.after(entity_duration, function() obj:remove() end)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-------------------
|
||||
-- PUNCH ENTITY --
|
||||
-------------------
|
||||
|
||||
local punch = {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
visual_size = {x = 1, y = 1},
|
||||
textures = {"fbrawl_punch_entity.png"},
|
||||
pointable = false,
|
||||
visual = "sprite",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
function punch:on_activate(pl_name, dtime_s)
|
||||
if pl_name ~= "" then
|
||||
entity_activate(self, pl_name)
|
||||
else
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
minetest.register_entity("fantasy_brawl:punch", punch)
|
||||
|
||||
|
||||
|
||||
-----------------
|
||||
-- KICK ENTITY --
|
||||
-----------------
|
||||
|
||||
local kick = {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
visual_size = {x = 1, y = 1},
|
||||
textures = {"fbrawl_kick_entity.png"},
|
||||
pointable = false,
|
||||
visual = "sprite",
|
||||
speed = 5,
|
||||
duration = 1
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
function kick:on_activate(pl_name, dtime_s)
|
||||
self.pl_name = pl_name
|
||||
|
||||
if pl_name ~= "" then
|
||||
entity_activate(self, pl_name)
|
||||
else
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
minetest.register_entity("fantasy_brawl:kick", kick)
|
196
_classes/warrior/skills/smash.lua
Normal file
@ -0,0 +1,196 @@
|
||||
local T = fbrawl.T
|
||||
|
||||
|
||||
|
||||
skillz.register_skill("fbrawl:warrior_jump", {
|
||||
name = "fbrawl:warrior_jump",
|
||||
mana = 100,
|
||||
slot = 2,
|
||||
jump_force = 25,
|
||||
cooldown = 0.5,
|
||||
sounds = {
|
||||
cast = {name = "wjump", max_hear_distance = 6}
|
||||
},
|
||||
chat_warnings = {
|
||||
cooldown = false
|
||||
},
|
||||
cast = function(self)
|
||||
local push_force = vector.multiply(self.player:get_look_dir(), self.jump_force)
|
||||
push_force.y = self.jump_force
|
||||
|
||||
self.player:add_velocity(push_force)
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount = 40,
|
||||
time = 0.5,
|
||||
minpos = vector.add(self.player:get_pos(), {x=0, y=0.5, z=0}),
|
||||
maxpos = self.player:get_pos(),
|
||||
minvel = {x = -4,y = 0, z = -4},
|
||||
maxvel = {x = 4, y = 0, z = 4},
|
||||
minsize = 8,
|
||||
maxsize = 10,
|
||||
texture = {
|
||||
name = "fbrawl_smoke_particle.png",
|
||||
alpha_tween = {1, 0}
|
||||
},
|
||||
minexptime = 0.5,
|
||||
maxexptime = 0.5,
|
||||
})
|
||||
|
||||
minetest.after(0.2, function() self.pl_name:start_skill("fbrawl:smash") end)
|
||||
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
|
||||
skillz.register_skill("fbrawl:smash", {
|
||||
name = "fbrawl:smash",
|
||||
description = T("Jump very high and then crush to the ground, damaging and slowing near players down."),
|
||||
slot = 2,
|
||||
damage = 4,
|
||||
range = 6,
|
||||
slow_down_factor = 0.5,
|
||||
slow_down_time = 2,
|
||||
sounds = {
|
||||
bgm = {name="while_jumping", max_hear_distance = 6},
|
||||
stop = {name="smash", max_hear_distance = 6}
|
||||
},
|
||||
data = {
|
||||
hit_players = {}
|
||||
},
|
||||
loop_params = {
|
||||
cast_rate = 0
|
||||
},
|
||||
attachments = {
|
||||
particles = {{
|
||||
amount = 35,
|
||||
time = 0,
|
||||
minpos = {x = -0.3, y = 0, z = -0.3},
|
||||
maxpos = {x = 0.3, y = 0.5, z = 0.3},
|
||||
minvel = {x = 0, y = 0, z = -1},
|
||||
maxvel = {x = 0, y = 0, z = -2},
|
||||
minsize = 4,
|
||||
maxsize = 9,
|
||||
texture = {
|
||||
name = "fbrawl_wjump_particle.png",
|
||||
alpha_tween = {1, 0}
|
||||
},
|
||||
minexptime = 1.5,
|
||||
maxexptime = 1.5,
|
||||
}},
|
||||
},
|
||||
on_start = function(self)
|
||||
self.data.hit_players = {}
|
||||
fbrawl.replace_slot_item(self.player, 2, "fantasy_brawl:smash")
|
||||
self.data.fall_damage = false
|
||||
end,
|
||||
on_stop = function(self)
|
||||
fbrawl.replace_slot_item(self.player, 2, "fantasy_brawl:warrior_jump")
|
||||
|
||||
minetest.after(self.slow_down_time, function()
|
||||
if not self.is_active then
|
||||
self.data.fall_damage = true
|
||||
end
|
||||
|
||||
for i, player in ipairs(self.data.hit_players) do
|
||||
local pl_speed = player:get_physics_override().speed
|
||||
player:set_physics_override({speed = pl_speed + self.slow_down_factor})
|
||||
end
|
||||
end)
|
||||
|
||||
fbrawl.camera_shake(self.pl_name, 6, 0.4)
|
||||
end,
|
||||
cast = function(self)
|
||||
if fbrawl.is_on_the_ground(self.player) then
|
||||
for i, player in ipairs(minetest.get_connected_players()) do
|
||||
local pl_name = player:get_player_name()
|
||||
local pl_distance = vector.distance(player:get_pos(), self.player:get_pos())
|
||||
local pl_vertical_distance = math.abs(self.player:get_pos().y - player:get_pos().y)
|
||||
|
||||
if
|
||||
pl_distance <= self.range
|
||||
and pl_vertical_distance < 2
|
||||
and pl_name ~= self.pl_name
|
||||
then
|
||||
local pl_speed = player:get_physics_override().speed
|
||||
|
||||
-- Slow the hit player down
|
||||
player:set_physics_override({speed = pl_speed - self.slow_down_factor})
|
||||
table.insert(self.data.hit_players, player)
|
||||
|
||||
fbrawl.hit_player(self.player, player, self.damage)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.add_entity(self.player:get_pos(), "fantasy_brawl:seismic_wave", self.pl_name)
|
||||
|
||||
self:stop()
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
|
||||
-------------------------
|
||||
-- SEISMIC WAVE ENTITY --
|
||||
-------------------------
|
||||
|
||||
local seismic_wave = {
|
||||
initial_properties = {
|
||||
hp_max = 999,
|
||||
physical = false,
|
||||
collisionbox = {-1, -1, -1, 1, 1.0, 1},
|
||||
visual_size = {x = 1, y = 0.2},
|
||||
textures = {
|
||||
"fbrawl_wave_entity.png", "fbrawl_transparent.png",
|
||||
"fbrawl_transparent.png", "fbrawl_transparent.png",
|
||||
"fbrawl_transparent.png", "fbrawl_transparent.png"
|
||||
},
|
||||
initial_sprite_basepos = {x = 0, y = 0},
|
||||
pointable = false,
|
||||
visual = "cube",
|
||||
},
|
||||
dropped = false,
|
||||
duration = 0.6,
|
||||
speed = 11.3,
|
||||
damage = 4,
|
||||
counter = 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
function seismic_wave:on_activate(pl_name, dtime_s)
|
||||
local obj = self.object
|
||||
|
||||
if pl_name then
|
||||
minetest.after(self.duration, function() if obj then obj:remove() end end)
|
||||
else
|
||||
obj:remove()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function seismic_wave:on_step(dtime)
|
||||
local increase_per_step = self.speed * dtime
|
||||
local props = self.object:get_properties()
|
||||
|
||||
self.counter = self.counter + dtime
|
||||
|
||||
if self.counter > 0.3 then
|
||||
local new_wave = minetest.add_entity(self.object:get_pos(), "fantasy_brawl:seismic_wave", self.pl_name)
|
||||
new_wave:get_luaentity().counter = -10
|
||||
self.counter = 0
|
||||
end
|
||||
|
||||
props.visual_size = vector.add(props.visual_size, increase_per_step)
|
||||
props.visual_size.y = 0.2
|
||||
|
||||
self.object:set_properties(props)
|
||||
end
|
||||
|
||||
|
||||
|
||||
minetest.register_entity("fantasy_brawl:seismic_wave", seismic_wave)
|
45
_classes/warrior/warrior.lua
Normal file
@ -0,0 +1,45 @@
|
||||
fbrawl.register_class("warrior", {
|
||||
name = "Warrior",
|
||||
physics_override = {
|
||||
speed = 1.5,
|
||||
gravity = 0.9
|
||||
},
|
||||
items = {"fbrawl:sword_warrior", "fbrawl:warrior_jump"},
|
||||
skills = {"fbrawl:smash"},
|
||||
sound = "warrior-class"
|
||||
})
|
||||
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/warrior/items.lua")
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/warrior/skills/smash.lua")
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/warrior/skills/iron_skin.lua")
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/warrior/skills/perfect_combo.lua")
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/warrior/skills/hero_fury.lua")
|
||||
|
||||
|
||||
|
||||
-- Preventing fall damage if smash or hero_fury is active
|
||||
minetest.register_on_player_hpchange(function(player, hp_change, reason)
|
||||
local pl_name = player:get_player_name()
|
||||
local hero_fury = pl_name:get_skill("fbrawl:hero_fury")
|
||||
local smash = pl_name:get_skill("fbrawl:smash")
|
||||
|
||||
-- Hero fury
|
||||
if
|
||||
reason.type == "fall"
|
||||
and hero_fury
|
||||
and hero_fury.is_active
|
||||
then
|
||||
return 0
|
||||
end
|
||||
|
||||
-- Smash
|
||||
if
|
||||
reason.type == "fall"
|
||||
and smash
|
||||
and not smash.data.fall_damage
|
||||
then
|
||||
return 0
|
||||
end
|
||||
|
||||
return hp_change
|
||||
end, true)
|
306
chatcmdbuilder.lua
Normal file
@ -0,0 +1,306 @@
|
||||
ChatCmdBuilder = {}
|
||||
|
||||
function ChatCmdBuilder.new(name, func, def)
|
||||
def = def or {}
|
||||
local cmd = ChatCmdBuilder.build(func)
|
||||
cmd.def = def
|
||||
def.func = cmd.run
|
||||
minetest.register_chatcommand(name, def)
|
||||
return cmd
|
||||
end
|
||||
|
||||
local STATE_READY = 1
|
||||
local STATE_PARAM = 2
|
||||
local STATE_PARAM_TYPE = 3
|
||||
local bad_chars = {}
|
||||
bad_chars["("] = true
|
||||
bad_chars[")"] = true
|
||||
bad_chars["."] = true
|
||||
bad_chars["%"] = true
|
||||
bad_chars["+"] = true
|
||||
bad_chars["-"] = true
|
||||
bad_chars["*"] = true
|
||||
bad_chars["?"] = true
|
||||
bad_chars["["] = true
|
||||
bad_chars["^"] = true
|
||||
bad_chars["$"] = true
|
||||
local function escape(char)
|
||||
if bad_chars[char] then
|
||||
return "%" .. char
|
||||
else
|
||||
return char
|
||||
end
|
||||
end
|
||||
|
||||
local dprint = function() end
|
||||
|
||||
ChatCmdBuilder.types = {
|
||||
pos = "%(? *(%-?[%d.]+) *, *(%-?[%d.]+) *, *(%-?[%d.]+) *%)?",
|
||||
text = "(.+)",
|
||||
number = "(%-?[%d.]+)",
|
||||
int = "(%-?[%d]+)",
|
||||
word = "([^ ]+)",
|
||||
alpha = "([A-Za-z]+)",
|
||||
modname = "([a-z0-9_]+)",
|
||||
alphascore = "([A-Za-z_]+)",
|
||||
alphanumeric = "([A-Za-z0-9]+)",
|
||||
username = "([A-Za-z0-9-_]+)",
|
||||
}
|
||||
|
||||
function ChatCmdBuilder.build(func)
|
||||
local cmd = {
|
||||
_subs = {}
|
||||
}
|
||||
function cmd:sub(route, func, def)
|
||||
dprint("Parsing " .. route)
|
||||
|
||||
def = def or {}
|
||||
if string.trim then
|
||||
route = string.trim(route)
|
||||
end
|
||||
|
||||
local sub = {
|
||||
pattern = "^",
|
||||
params = {},
|
||||
func = func
|
||||
}
|
||||
|
||||
-- End of param reached: add it to the pattern
|
||||
local param = ""
|
||||
local param_type = ""
|
||||
local should_be_eos = false
|
||||
local function finishParam()
|
||||
if param ~= "" and param_type ~= "" then
|
||||
dprint(" - Found param " .. param .. " type " .. param_type)
|
||||
|
||||
local pattern = ChatCmdBuilder.types[param_type]
|
||||
if not pattern then
|
||||
error("Unrecognised param_type=" .. param_type)
|
||||
end
|
||||
|
||||
sub.pattern = sub.pattern .. pattern
|
||||
|
||||
table.insert(sub.params, param_type)
|
||||
|
||||
param = ""
|
||||
param_type = ""
|
||||
end
|
||||
end
|
||||
|
||||
-- Iterate through the route to find params
|
||||
local state = STATE_READY
|
||||
local catching_space = false
|
||||
local match_space = " " -- change to "%s" to also catch tabs and newlines
|
||||
local catch_space = match_space.."+"
|
||||
for i = 1, #route do
|
||||
local c = route:sub(i, i)
|
||||
if should_be_eos then
|
||||
error("Should be end of string. Nothing is allowed after a param of type text.")
|
||||
end
|
||||
|
||||
if state == STATE_READY then
|
||||
if c == ":" then
|
||||
dprint(" - Found :, entering param")
|
||||
state = STATE_PARAM
|
||||
param_type = "word"
|
||||
catching_space = false
|
||||
elseif c:match(match_space) then
|
||||
print(" - Found space")
|
||||
if not catching_space then
|
||||
catching_space = true
|
||||
sub.pattern = sub.pattern .. catch_space
|
||||
end
|
||||
else
|
||||
catching_space = false
|
||||
sub.pattern = sub.pattern .. escape(c)
|
||||
end
|
||||
elseif state == STATE_PARAM then
|
||||
if c == ":" then
|
||||
dprint(" - Found :, entering param type")
|
||||
state = STATE_PARAM_TYPE
|
||||
param_type = ""
|
||||
elseif c:match(match_space) then
|
||||
print(" - Found whitespace, leaving param")
|
||||
state = STATE_READY
|
||||
finishParam()
|
||||
catching_space = true
|
||||
sub.pattern = sub.pattern .. catch_space
|
||||
elseif c:match("%W") then
|
||||
dprint(" - Found nonalphanum, leaving param")
|
||||
state = STATE_READY
|
||||
finishParam()
|
||||
sub.pattern = sub.pattern .. escape(c)
|
||||
else
|
||||
param = param .. c
|
||||
end
|
||||
elseif state == STATE_PARAM_TYPE then
|
||||
if c:match(match_space) then
|
||||
print(" - Found space, leaving param type")
|
||||
state = STATE_READY
|
||||
finishParam()
|
||||
catching_space = true
|
||||
sub.pattern = sub.pattern .. catch_space
|
||||
elseif c:match("%W") then
|
||||
dprint(" - Found nonalphanum, leaving param type")
|
||||
state = STATE_READY
|
||||
finishParam()
|
||||
sub.pattern = sub.pattern .. escape(c)
|
||||
else
|
||||
param_type = param_type .. c
|
||||
end
|
||||
end
|
||||
end
|
||||
dprint(" - End of route")
|
||||
finishParam()
|
||||
sub.pattern = sub.pattern .. "$"
|
||||
dprint("Pattern: " .. sub.pattern)
|
||||
|
||||
table.insert(self._subs, sub)
|
||||
end
|
||||
|
||||
if func then
|
||||
func(cmd)
|
||||
end
|
||||
|
||||
cmd.run = function(name, param)
|
||||
for i = 1, #cmd._subs do
|
||||
local sub = cmd._subs[i]
|
||||
local res = { string.match(param, sub.pattern) }
|
||||
if #res > 0 then
|
||||
local pointer = 1
|
||||
local params = { name }
|
||||
for j = 1, #sub.params do
|
||||
local param = sub.params[j]
|
||||
if param == "pos" then
|
||||
local pos = {
|
||||
x = tonumber(res[pointer]),
|
||||
y = tonumber(res[pointer + 1]),
|
||||
z = tonumber(res[pointer + 2])
|
||||
}
|
||||
table.insert(params, pos)
|
||||
pointer = pointer + 3
|
||||
elseif param == "number" or param == "int" then
|
||||
table.insert(params, tonumber(res[pointer]))
|
||||
pointer = pointer + 1
|
||||
else
|
||||
table.insert(params, res[pointer])
|
||||
pointer = pointer + 1
|
||||
end
|
||||
end
|
||||
if table.unpack then
|
||||
-- lua 5.2 or later
|
||||
return sub.func(table.unpack(params))
|
||||
else
|
||||
-- lua 5.1 or earlier
|
||||
return sub.func(unpack(params))
|
||||
end
|
||||
end
|
||||
end
|
||||
return false, "Invalid command"
|
||||
end
|
||||
|
||||
return cmd
|
||||
end
|
||||
|
||||
local function run_tests()
|
||||
if not (ChatCmdBuilder.build(function(cmd)
|
||||
cmd:sub("bar :one and :two:word", function(name, one, two)
|
||||
if name == "singleplayer" and one == "abc" and two == "def" then
|
||||
return true
|
||||
end
|
||||
end)
|
||||
end)).run("singleplayer", "bar abc and def") then
|
||||
error("Test 1 failed")
|
||||
end
|
||||
|
||||
local move = ChatCmdBuilder.build(function(cmd)
|
||||
cmd:sub("move :target to :pos:pos", function(name, target, pos)
|
||||
if name == "singleplayer" and target == "player1" and
|
||||
pos.x == 0 and pos.y == 1 and pos.z == 2 then
|
||||
return true
|
||||
end
|
||||
end)
|
||||
end).run
|
||||
if not move("singleplayer", "move player1 to 0,1,2") then
|
||||
error("Test 2 failed")
|
||||
end
|
||||
if not move("singleplayer", "move player1 to (0,1,2)") then
|
||||
error("Test 3 failed")
|
||||
end
|
||||
if not move("singleplayer", "move player1 to 0, 1,2") then
|
||||
error("Test 4 failed")
|
||||
end
|
||||
if not move("singleplayer", "move player1 to 0 ,1, 2") then
|
||||
error("Test 5 failed")
|
||||
end
|
||||
if not move("singleplayer", "move player1 to 0, 1, 2") then
|
||||
error("Test 6 failed")
|
||||
end
|
||||
if not move("singleplayer", "move player1 to 0 ,1 ,2") then
|
||||
error("Test 7 failed")
|
||||
end
|
||||
if not move("singleplayer", "move player1 to ( 0 ,1 ,2)") then
|
||||
error("Test 8 failed")
|
||||
end
|
||||
if move("singleplayer", "move player1 to abc,def,sdosd") then
|
||||
error("Test 9 failed")
|
||||
end
|
||||
if move("singleplayer", "move player1 to abc def sdosd") then
|
||||
error("Test 10 failed")
|
||||
end
|
||||
|
||||
if not (ChatCmdBuilder.build(function(cmd)
|
||||
cmd:sub("does :one:int plus :two:int equal :three:int", function(name, one, two, three)
|
||||
if name == "singleplayer" and one + two == three then
|
||||
return true
|
||||
end
|
||||
end)
|
||||
end)).run("singleplayer", "does 1 plus 2 equal 3") then
|
||||
error("Test 11 failed")
|
||||
end
|
||||
|
||||
local checknegint = ChatCmdBuilder.build(function(cmd)
|
||||
cmd:sub("checknegint :x:int", function(name, x)
|
||||
return x
|
||||
end)
|
||||
end).run
|
||||
if checknegint("checker","checknegint -2") ~= -2 then
|
||||
error("Test 12 failed")
|
||||
end
|
||||
|
||||
local checknegnumber = ChatCmdBuilder.build(function(cmd)
|
||||
cmd:sub("checknegnumber :x:number", function(name, x)
|
||||
return x
|
||||
end)
|
||||
end).run
|
||||
if checknegnumber("checker","checknegnumber -3.3") ~= -3.3 then
|
||||
error("Test 13 failed")
|
||||
end
|
||||
|
||||
local checknegpos = ChatCmdBuilder.build(function(cmd)
|
||||
cmd:sub("checknegpos :pos:pos", function(name, pos)
|
||||
return pos
|
||||
end)
|
||||
end).run
|
||||
local negpos = checknegpos("checker","checknegpos (-13.3,-4.6,-1234.5)")
|
||||
if negpos.x ~= -13.3 or negpos.y ~= -4.6 or negpos.z ~= -1234.5 then
|
||||
error("Test 14 failed")
|
||||
end
|
||||
|
||||
local checktypes = ChatCmdBuilder.build(function(cmd)
|
||||
cmd:sub("checktypes :int:int :number:number :pos:pos :word:word :text:text", function(name, int, number, pos, word, text)
|
||||
return int, number, pos.x, pos.y, pos.z, word, text
|
||||
end)
|
||||
end).run
|
||||
local int, number, posx, posy, posz, word, text
|
||||
int, number, posx, posy, posz, word, text = checktypes("checker","checktypes -1 -2.4 (-3,-5.3,6.12) some text to finish off with")
|
||||
--dprint(int, number, posx, posy, posz, word, text)
|
||||
if int ~= -1 or number ~= -2.4 or posx ~= -3 or posy ~= -5.3 or posz ~= 6.12 or word ~= "some" or text ~= "text to finish off with" then
|
||||
error("Test 15 failed")
|
||||
end
|
||||
dprint("All tests passed")
|
||||
|
||||
end
|
||||
if not minetest then
|
||||
run_tests()
|
||||
end
|
18
commands.lua
Normal file
@ -0,0 +1,18 @@
|
||||
ChatCmdBuilder.new("fbrawl", function(cmd)
|
||||
|
||||
cmd:sub("list", function(name)
|
||||
minetest.chat_send_player(name, "\nSkillz > Skills list")
|
||||
|
||||
for mod, def in pairs(skillz.get_registered_skills()) do
|
||||
local skill_name = def.name
|
||||
local skill_desc = def.description
|
||||
|
||||
minetest.chat_send_player(name, skill_name:upper() .. " \n" .. skill_desc .. "\n\n")
|
||||
end
|
||||
end)
|
||||
|
||||
end, {
|
||||
description = [[
|
||||
- list: lists every registered skill
|
||||
]]
|
||||
})
|
114
hud.lua
Normal file
@ -0,0 +1,114 @@
|
||||
local saved_huds = {} -- pl_name = {hud name = id}
|
||||
local T = fbrawl.T
|
||||
|
||||
|
||||
|
||||
function fbrawl.generate_HUD(arena, pl_name)
|
||||
local player = minetest.get_player_by_name(pl_name)
|
||||
local pl_class = arena.classes[pl_name]
|
||||
|
||||
local background
|
||||
local timer
|
||||
local class = T(pl_class.internal_name)
|
||||
local vignette
|
||||
|
||||
-- Sets the class background image.
|
||||
background = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 1, y = 0},
|
||||
offset = {x = -179, y = 32},
|
||||
text = pl_class.HUD_timer or "HUD_fbrawl_timer.png",
|
||||
alignment = { x = 1.0},
|
||||
scale = { x = 1.15, y = 1.15},
|
||||
number = 0xFFFFFF,
|
||||
z_index = 100
|
||||
})
|
||||
|
||||
-- Sets the timer text.
|
||||
timer = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0},
|
||||
offset = {x = -51, y = 32},
|
||||
text = arena.initial_time,
|
||||
alignment = { x = 1.0},
|
||||
scale = { x = 2, y = 2},
|
||||
number = 0xFFFFFF,
|
||||
z_index = 100,
|
||||
})
|
||||
|
||||
-- Sets the class text.
|
||||
class = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 1, y = 0},
|
||||
offset = {x = -136, y = 32},
|
||||
text = class,
|
||||
alignment = { x = 0},
|
||||
scale = { x = 100, y = 10},
|
||||
number = 0xFFFFFF,
|
||||
z_index = 100
|
||||
})
|
||||
|
||||
vignette = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0.5, y = 0.5},
|
||||
scale = {
|
||||
x = -100,
|
||||
y = -100
|
||||
},
|
||||
text = pl_class.vignette or "HUD_fbrawl_vignette.png",
|
||||
z_index = 99
|
||||
})
|
||||
|
||||
-- Save the huds IDs for each player.
|
||||
saved_huds[pl_name] = {
|
||||
class_ID = class,
|
||||
backgound_ID = background,
|
||||
timer_ID = timer,
|
||||
vignette_ID = vignette
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
||||
function fbrawl.update_HUD(pl_name, field, new_value)
|
||||
if saved_huds[pl_name] and saved_huds[pl_name][field] then
|
||||
local player = minetest.get_player_by_name(pl_name)
|
||||
player:hud_change(saved_huds[pl_name][field], "text", new_value)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function fbrawl.remove_HUD(pl_name)
|
||||
minetest.after(1, function()
|
||||
local player = minetest.get_player_by_name(pl_name)
|
||||
|
||||
if not player or not saved_huds[pl_name] then return end
|
||||
|
||||
for name, id in pairs(saved_huds[pl_name]) do
|
||||
player:hud_remove(id)
|
||||
end
|
||||
|
||||
saved_huds[pl_name] = {}
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function fbrawl.add_temp_hud(pl_name, hud, time)
|
||||
local player = minetest.get_player_by_name(pl_name)
|
||||
|
||||
hud = player:hud_add(hud)
|
||||
saved_huds[pl_name] = saved_huds[pl_name] or {}
|
||||
saved_huds[pl_name][tostring(hud)] = hud
|
||||
|
||||
-- Removing the hud after "time" seconds if the player still has it.
|
||||
minetest.after(time, function()
|
||||
if saved_huds[pl_name] and saved_huds[pl_name][tostring(hud)] then
|
||||
player:hud_remove(hud)
|
||||
saved_huds[pl_name][tostring(hud)] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
return hud
|
||||
end
|
48
init.lua
Normal file
@ -0,0 +1,48 @@
|
||||
fbrawl = {}
|
||||
fbrawl.T = minetest.get_translator("fantasy_brawl")
|
||||
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/SETTINGS.lua")
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/chatcmdbuilder.lua")
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/utils.lua")
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/classes_system.lua")
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/mana.lua")
|
||||
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/warrior/warrior.lua")
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/_classes/mage/mage.lua")
|
||||
|
||||
dofile(minetest.get_modpath("fantasy_brawl") .. "/commands.lua")
|
||||
|
||||
|
||||
arena_lib.register_minigame("murder", {
|
||||
prefix = fbrawl_settings.prefix,
|
||||
temp_properties = {
|
||||
classes = {}, -- pl_name : string = class : {}
|
||||
match_id = 0,
|
||||
},
|
||||
player_properties = {
|
||||
class = ""
|
||||
},
|
||||
load_time = fbrawl_settings.max_loading_time,
|
||||
show_nametags = false,
|
||||
show_minimap = false,
|
||||
celebration_time = fbrawl_settings.celebration_time,
|
||||
disabled_damage_types = {"fall"},
|
||||
time_mode = "decremental"
|
||||
})
|
||||
|
||||
|
||||
|
||||
minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info)
|
||||
local pl_name = player:get_player_name()
|
||||
|
||||
if arena_lib.is_player_in_arena(pl_name, "fantasy_brawl") then
|
||||
return 0
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
minetest.register_on_joinplayer(function(p, last_login)
|
||||
end)
|
||||
|
||||
|
||||
skillz.register_on_unlock("fbrawl", function(def) minetest.log("+ " .. def.name .. " to " .. def.pl_name) end)
|
4
mod.conf
Normal file
@ -0,0 +1,4 @@
|
||||
name = fantasy_brawl
|
||||
depends = skillz, arena_lib
|
||||
description = To write.
|
||||
author = giov4
|
BIN
sounds/168861__ianslattery__bubble-bursting-popping.aiff
Normal file
BIN
sounds/644114__duisterwho__mouth-plop-repeated.wav
Normal file
BIN
sounds/fbrawl_error.ogg
Normal file
BIN
sounds/fbrawl_mage_staff.ogg
Normal file
BIN
sounds/fbrawl_magic_bullet.ogg
Normal file
BIN
sounds/fbrawl_warrior_teleport.wav
Normal file
BIN
sounds/iron_skin_off.ogg
Normal file
BIN
sounds/iron_skin_on.ogg
Normal file
BIN
sounds/kick.ogg
Normal file
BIN
sounds/punch.ogg
Normal file
BIN
sounds/smash.ogg
Normal file
BIN
sounds/while_jumping.ogg
Normal file
BIN
sounds/wjump.ogg
Normal file
BIN
textures/_fbrawl_mage_bullet_entity.png
Normal file
After Width: | Height: | Size: 219 B |
BIN
textures/fbrawl_fire_sprint_skill.png
Normal file
After Width: | Height: | Size: 368 B |
BIN
textures/fbrawl_hero_fury_skill.png
Normal file
After Width: | Height: | Size: 487 B |
BIN
textures/fbrawl_iron_skin_skill.png
Normal file
After Width: | Height: | Size: 350 B |
BIN
textures/fbrawl_kick_entity.png
Normal file
After Width: | Height: | Size: 185 B |
BIN
textures/fbrawl_mage_bullet_entity.png
Normal file
After Width: | Height: | Size: 135 B |
BIN
textures/fbrawl_mage_staff.png
Normal file
After Width: | Height: | Size: 190 B |
BIN
textures/fbrawl_manabar_hud.png
Normal file
After Width: | Height: | Size: 86 B |
BIN
textures/fbrawl_manabar_nomana_hud.png
Normal file
After Width: | Height: | Size: 86 B |
BIN
textures/fbrawl_perfect_combo_skill.png
Normal file
After Width: | Height: | Size: 411 B |
BIN
textures/fbrawl_punch_entity.png
Normal file
After Width: | Height: | Size: 174 B |
BIN
textures/fbrawl_shield_entity.png
Normal file
After Width: | Height: | Size: 317 B |
BIN
textures/fbrawl_slash_entity.png
Normal file
After Width: | Height: | Size: 150 B |
BIN
textures/fbrawl_smash_item.png
Normal file
After Width: | Height: | Size: 198 B |
BIN
textures/fbrawl_smash_skill.png
Normal file
After Width: | Height: | Size: 509 B |
BIN
textures/fbrawl_smoke_particle.png
Normal file
After Width: | Height: | Size: 178 B |
BIN
textures/fbrawl_sword_item.png
Normal file
After Width: | Height: | Size: 263 B |
BIN
textures/fbrawl_transparent.png
Normal file
After Width: | Height: | Size: 75 B |
BIN
textures/fbrawl_wave_entity.png
Normal file
After Width: | Height: | Size: 173 B |
BIN
textures/fbrawl_wjump_particle.png
Normal file
After Width: | Height: | Size: 163 B |
166
utils.lua
Normal file
@ -0,0 +1,166 @@
|
||||
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
|
||||
|
||||
|
||||
|
||||
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"
|
||||
})
|
||||
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
|
||||
|
||||
|
||||
|
||||
function fbrawl.area_raycast_up(center, radius, range, objects, liquids)
|
||||
local ray_distance = 0.5
|
||||
|
||||
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}
|
||||
local pos2 = vector.add(pos1, {x = 0, y = range, z = 0})
|
||||
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()
|
||||
fbrawl.camera_shake(pl_name, duration, strength, offsets, next_offset, eye_offset, last)
|
||||
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
|
||||
|
||||
|
||||
|
||||
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
|