Merge branch 'enchanting' of https://git.minetest.land/Wuzzy/MineClone2 into master
commit
280f284867
|
@ -152,6 +152,11 @@ minetest.register_globalstep(function(dtime)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
elseif not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "mcl_experience:orb" then
|
||||||
|
local entity = object:get_luaentity()
|
||||||
|
entity.collector = player:get_player_name()
|
||||||
|
entity.collected = true
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -221,6 +226,12 @@ function minetest.handle_node_drops(pos, drops, digger)
|
||||||
local dug_node = minetest.get_node(pos)
|
local dug_node = minetest.get_node(pos)
|
||||||
local toolcaps
|
local toolcaps
|
||||||
if digger ~= nil then
|
if digger ~= nil then
|
||||||
|
if mcl_experience.throw_experience then
|
||||||
|
local experience_amount = minetest.get_item_group(dug_node.name,"experience")
|
||||||
|
if experience_amount > 0 then
|
||||||
|
mcl_experience.throw_experience(pos, experience_amount)
|
||||||
|
end
|
||||||
|
end
|
||||||
local tool = digger:get_wielded_item()
|
local tool = digger:get_wielded_item()
|
||||||
toolcaps = tool:get_tool_capabilities()
|
toolcaps = tool:get_tool_capabilities()
|
||||||
|
|
||||||
|
|
|
@ -640,6 +640,10 @@ local check_for_death = function(self, cause, cmi_cause)
|
||||||
|
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
|
|
||||||
|
if mcl_experience.throw_experience and self.hp_min and self.hp_max then
|
||||||
|
mcl_experience.throw_experience(pos, math.ceil( math.random(self.hp_min,self.hp_max+5) / 5) )
|
||||||
|
end
|
||||||
|
|
||||||
-- execute custom death function
|
-- execute custom death function
|
||||||
if self.on_die then
|
if self.on_die then
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,11 @@ end
|
||||||
|
|
||||||
-- Load default settings
|
-- Load default settings
|
||||||
dofile(minetest.get_modpath("hudbars").."/default_settings.lua")
|
dofile(minetest.get_modpath("hudbars").."/default_settings.lua")
|
||||||
|
if minetest.get_modpath("mcl_experience") then
|
||||||
|
-- reserve some space for experience bar:
|
||||||
|
hb.settings.start_offset_left.y = hb.settings.start_offset_left.y - 20
|
||||||
|
hb.settings.start_offset_right.y = hb.settings.start_offset_right.y - 20
|
||||||
|
end
|
||||||
|
|
||||||
local function player_exists(player)
|
local function player_exists(player)
|
||||||
return player ~= nil and player:is_player()
|
return player ~= nil and player:is_player()
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
-- eXPerience mod
|
||||||
|
-- This mod has adopted from oil_boi's Crafter-minetest
|
||||||
|
-- ( https://www.patreon.com/oil_boi ) by kay27@bk.ru
|
||||||
|
-- for MineClone 2 under GNU General Public License v3.0.
|
||||||
|
-- Copyright (c) Oil_boi, Wuzzy, kay27,
|
||||||
|
-- experience_orb texture by github.com/Gerold55
|
|
@ -0,0 +1,539 @@
|
||||||
|
local S = minetest.get_translator("mcl_experience")
|
||||||
|
mcl_experience = {}
|
||||||
|
local pool = {}
|
||||||
|
local registered_nodes
|
||||||
|
|
||||||
|
local gravity = {x = 0, y = -((tonumber(minetest.settings:get("movement_gravity"))) or 9.81), z = 0}
|
||||||
|
local size_min, size_max = 20, 59 -- percents
|
||||||
|
local delta_size = size_max - size_min
|
||||||
|
local size_to_xp = {
|
||||||
|
{-32768, 2}, -- 1
|
||||||
|
{ 3, 6}, -- 2
|
||||||
|
{ 7, 16}, -- 3
|
||||||
|
{ 17, 36}, -- 4
|
||||||
|
{ 37, 72}, -- 5
|
||||||
|
{ 73, 148}, -- 6
|
||||||
|
{ 149, 306}, -- 7
|
||||||
|
{ 307, 616}, -- 8
|
||||||
|
{ 617, 1236}, -- 9
|
||||||
|
{ 1237, 2476}, --10
|
||||||
|
{ 2477, 32767} --11
|
||||||
|
}
|
||||||
|
|
||||||
|
local function xp_to_size(xp)
|
||||||
|
local i, l = 1, #size_to_xp
|
||||||
|
while (xp > size_to_xp[i][1]) and (i < l) do
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
return ((i-1) / (l-1) * delta_size + size_min)/100
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_mods_loaded(function()
|
||||||
|
registered_nodes = minetest.registered_nodes
|
||||||
|
end)
|
||||||
|
|
||||||
|
local load_data = function(player)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
pool[name] = {}
|
||||||
|
local temp_pool = pool[name]
|
||||||
|
local meta = player:get_meta()
|
||||||
|
temp_pool.xp = meta:get_int("xp") or 0
|
||||||
|
temp_pool.level = mcl_experience.xp_to_level(temp_pool.xp)
|
||||||
|
temp_pool.bar, temp_pool.xp_next_level = mcl_experience.xp_to_bar(temp_pool.xp, temp_pool.level)
|
||||||
|
temp_pool.last_time= minetest.get_us_time()/1000000
|
||||||
|
end
|
||||||
|
|
||||||
|
-- saves data to be utilized on next login
|
||||||
|
local save_data = function(player)
|
||||||
|
name = player:get_player_name()
|
||||||
|
local temp_pool = pool[name]
|
||||||
|
local meta = player:get_meta()
|
||||||
|
meta:set_int("xp", temp_pool.xp)
|
||||||
|
pool[name] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local player_huds = {} -- the list of players hud lists (3d array)
|
||||||
|
hud_manager = {} -- hud manager class
|
||||||
|
|
||||||
|
-- terminate the player's list on leave
|
||||||
|
minetest.register_on_leaveplayer(function(player)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
player_huds[name] = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- create instance of new hud
|
||||||
|
hud_manager.add_hud = function(player,hud_name,def)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
local local_hud = player:hud_add({
|
||||||
|
hud_elem_type = def.hud_elem_type,
|
||||||
|
position = def.position,
|
||||||
|
text = def.text,
|
||||||
|
number = def.number,
|
||||||
|
direction = def.direction,
|
||||||
|
size = def.size,
|
||||||
|
offset = def.offset,
|
||||||
|
})
|
||||||
|
-- create new 3d array here
|
||||||
|
-- depends.txt is not needed
|
||||||
|
-- with it here
|
||||||
|
if not player_huds[name] then
|
||||||
|
player_huds[name] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
player_huds[name][hud_name] = local_hud
|
||||||
|
end
|
||||||
|
|
||||||
|
-- delete instance of hud
|
||||||
|
hud_manager.remove_hud = function(player,hud_name)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if player_huds[name] and player_huds[name][hud_name] then
|
||||||
|
player:hud_remove(player_huds[name][hud_name])
|
||||||
|
player_huds[name][hud_name] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- change element of hud
|
||||||
|
hud_manager.change_hud = function(data)
|
||||||
|
local name = data.player:get_player_name()
|
||||||
|
if player_huds[name] and player_huds[name][data.hud_name] then
|
||||||
|
data.player:hud_change(player_huds[name][data.hud_name], data.element, data.data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- gets if hud exists
|
||||||
|
hud_manager.hud_exists = function(player,hud_name)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if player_huds[name] and player_huds[name][hud_name] then
|
||||||
|
return(true)
|
||||||
|
else
|
||||||
|
return(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
-- saves specific users data for when they relog
|
||||||
|
minetest.register_on_leaveplayer(function(player)
|
||||||
|
save_data(player)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- is used for shutdowns to save all data
|
||||||
|
local save_all = function()
|
||||||
|
for name,_ in pairs(pool) do
|
||||||
|
local player = minetest.get_player_by_name(name)
|
||||||
|
if player then
|
||||||
|
save_data(player)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- save all data to mod storage on shutdown
|
||||||
|
minetest.register_on_shutdown(function()
|
||||||
|
save_all()
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
local name
|
||||||
|
function mcl_experience.get_player_xp_level(player)
|
||||||
|
name = player:get_player_name()
|
||||||
|
return(pool[name].level)
|
||||||
|
end
|
||||||
|
|
||||||
|
local name
|
||||||
|
local temp_pool
|
||||||
|
function mcl_experience.set_player_xp_level(player,level)
|
||||||
|
name = player:get_player_name()
|
||||||
|
pool[name].level = level
|
||||||
|
pool[name].xp = mcl_experience.level_to_xp(level)
|
||||||
|
--todo: update bar
|
||||||
|
hud_manager.change_hud({
|
||||||
|
player = player,
|
||||||
|
hud_name = "xp_level_fg",
|
||||||
|
element = "text",
|
||||||
|
data = tostring(level)
|
||||||
|
})
|
||||||
|
hud_manager.change_hud({
|
||||||
|
player = player,
|
||||||
|
hud_name = "xp_level_bg",
|
||||||
|
element = "text",
|
||||||
|
data = tostring(level)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local name
|
||||||
|
local temp_pool
|
||||||
|
minetest.register_on_joinplayer(function(player)
|
||||||
|
|
||||||
|
load_data(player)
|
||||||
|
|
||||||
|
name = player:get_player_name()
|
||||||
|
temp_pool = pool[name]
|
||||||
|
|
||||||
|
hud_manager.add_hud(player, "experience_bar_background",
|
||||||
|
{
|
||||||
|
hud_elem_type = "statbar", position = {x=0.5, y=1},
|
||||||
|
name = "experience bar background", text = "experience_bar_background.png",
|
||||||
|
number = 36, direction = 0,
|
||||||
|
offset = {x = (-8 * 28) - 29, y = -(48 + 24 + 16)},
|
||||||
|
size = { x=28, y=28 }, z_index = 3,
|
||||||
|
})
|
||||||
|
|
||||||
|
hud_manager.add_hud(player,"experience_bar",
|
||||||
|
{
|
||||||
|
hud_elem_type = "statbar", position = {x=0.5, y=1},
|
||||||
|
name = "experience bar", text = "experience_bar.png",
|
||||||
|
number = temp_pool.bar, direction = 0,
|
||||||
|
offset = {x = (-8 * 28) - 29, y = -(48 + 24 + 16)},
|
||||||
|
size = { x=28, y=28 }, z_index = 4,
|
||||||
|
})
|
||||||
|
|
||||||
|
hud_manager.add_hud(player,"xp_level_bg",
|
||||||
|
{
|
||||||
|
hud_elem_type = "text", position = {x=0.5, y=1},
|
||||||
|
name = "xp_level_bg", text = tostring(temp_pool.level),
|
||||||
|
number = 0x000000,
|
||||||
|
offset = {x = 0, y = -(48 + 24 + 24)},
|
||||||
|
z_index = 5,
|
||||||
|
})
|
||||||
|
|
||||||
|
hud_manager.add_hud(player,"xp_level_fg",
|
||||||
|
{
|
||||||
|
hud_elem_type = "text", position = {x=0.5, y=1},
|
||||||
|
name = "xp_level_fg", text = tostring(temp_pool.level),
|
||||||
|
number = 0xFFFFFF,
|
||||||
|
offset = {x = -1, y = -(48 + 24 + 25)},
|
||||||
|
z_index = 6,
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
|
function mcl_experience.xp_to_level(xp)
|
||||||
|
local xp = xp or 0
|
||||||
|
local a, b, c, D
|
||||||
|
if xp > 1507 then
|
||||||
|
a, b, c = 4.5, -162.5, 2220-xp
|
||||||
|
elseif xp > 352 then
|
||||||
|
a, b, c = 2.5, -40.5, 360-xp
|
||||||
|
else
|
||||||
|
a, b, c = 1, 6, -xp
|
||||||
|
end
|
||||||
|
D = b*b-4*a*c
|
||||||
|
if D == 0 then
|
||||||
|
return math.floor(-b/2/a)
|
||||||
|
elseif D > 0 then
|
||||||
|
local v1, v2 = -b/2/a, math.sqrt(D)/2/a
|
||||||
|
return math.floor((math.max(v1-v2, v1+v2)))
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_experience.level_to_xp(level)
|
||||||
|
if (level >= 1 and level <= 16) then
|
||||||
|
return math.floor(math.pow(level, 2) + 6 * level)
|
||||||
|
elseif (level >= 17 and level <= 31) then
|
||||||
|
return math.floor(2.5 * math.pow(level, 2) - 40.5 * level + 360)
|
||||||
|
elseif level >= 32 then
|
||||||
|
return math.floor(4.5 * math.pow(level, 2) - 162.5 * level + 2220);
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_experience.xp_to_bar(xp, level)
|
||||||
|
local level = level or mcl_experience.xp_to_level(xp)
|
||||||
|
local xp_this_level = mcl_experience.level_to_xp(level)
|
||||||
|
local xp_next_level = mcl_experience.level_to_xp(level+1)
|
||||||
|
local bar = math.floor((xp-xp_this_level)/(xp_next_level-xp_this_level)*35)
|
||||||
|
return bar, xp_next_level
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_experience.add_experience(player, experience)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
local temp_pool = pool[name]
|
||||||
|
|
||||||
|
local old_bar, old_xp, old_level = temp_pool.bar, temp_pool.xp, temp_pool.level
|
||||||
|
temp_pool.xp = math.max(temp_pool.xp + experience, 0)
|
||||||
|
temp_pool.level = mcl_experience.xp_to_level(temp_pool.xp)
|
||||||
|
temp_pool.bar, temp_pool.xp_next_level = mcl_experience.xp_to_bar(temp_pool.xp, temp_pool.level)
|
||||||
|
if old_level ~= temp_pool.level then
|
||||||
|
if minetest.get_us_time()/1000000 - temp_pool.last_time > 0.04 then
|
||||||
|
minetest.sound_play("level_up",{gain=0.2,to_player = name})
|
||||||
|
temp_pool.last_time = minetest.get_us_time()/1000000
|
||||||
|
end
|
||||||
|
hud_manager.change_hud({player = player, hud_name = "xp_level_fg", element = "text", data = tostring(temp_pool.level)})
|
||||||
|
hud_manager.change_hud({player = player, hud_name = "xp_level_bg", element = "text", data = tostring(temp_pool.level)})
|
||||||
|
elseif minetest.get_us_time()/1000000 - temp_pool.last_time > 0.01 then
|
||||||
|
temp_pool.last_time = minetest.get_us_time()/1000000
|
||||||
|
minetest.sound_play("experience",{gain=0.1,to_player = name,pitch=math.random(75,99)/100})
|
||||||
|
end
|
||||||
|
|
||||||
|
if old_bar ~= temp_pool.bar then
|
||||||
|
hud_manager.change_hud({player = player, hud_name = "experience_bar", element = "number", data = temp_pool.bar})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--reset player level
|
||||||
|
local name
|
||||||
|
local temp_pool
|
||||||
|
local xp_amount
|
||||||
|
minetest.register_on_dieplayer(function(player)
|
||||||
|
if minetest.settings:get_bool("mcl_keepInventory", false) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
name = player:get_player_name()
|
||||||
|
temp_pool = pool[name]
|
||||||
|
xp_amount = temp_pool.xp
|
||||||
|
|
||||||
|
temp_pool.bar = 0
|
||||||
|
temp_pool.level = 0
|
||||||
|
temp_pool.xp = 0
|
||||||
|
|
||||||
|
hud_manager.change_hud({player = player, hud_name = "xp_level_fg", element = "text", data = tostring(temp_pool.level)})
|
||||||
|
hud_manager.change_hud({player = player, hud_name = "xp_level_bg", element = "text", data = tostring(temp_pool.level)})
|
||||||
|
hud_manager.change_hud({player = player, hud_name = "experience_bar", element = "number", data = temp_pool.bar})
|
||||||
|
|
||||||
|
mcl_experience.throw_experience(player:get_pos(), xp_amount)
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
local name
|
||||||
|
local collector, pos, pos2
|
||||||
|
local direction, distance, player_velocity, goal
|
||||||
|
local currentvel, acceleration, multiplier, velocity
|
||||||
|
local node, vel, def
|
||||||
|
local is_moving, is_slippery, slippery, slip_factor
|
||||||
|
local size, data
|
||||||
|
local function xp_step(self, dtime)
|
||||||
|
--if item set to be collected then only execute go to player
|
||||||
|
if self.collected == true then
|
||||||
|
if not self.collector then
|
||||||
|
self.collected = false
|
||||||
|
return
|
||||||
|
end
|
||||||
|
collector = minetest.get_player_by_name(self.collector)
|
||||||
|
if collector and collector:get_hp() > 0 and vector.distance(self.object:get_pos(),collector:get_pos()) < 5 then
|
||||||
|
self.object:set_acceleration(vector.new(0,0,0))
|
||||||
|
self.disable_physics(self)
|
||||||
|
--get the variables
|
||||||
|
pos = self.object:get_pos()
|
||||||
|
pos2 = collector:get_pos()
|
||||||
|
|
||||||
|
player_velocity = collector:get_player_velocity()
|
||||||
|
|
||||||
|
pos2.y = pos2.y + 0.8
|
||||||
|
|
||||||
|
direction = vector.direction(pos,pos2)
|
||||||
|
distance = vector.distance(pos2,pos)
|
||||||
|
multiplier = distance
|
||||||
|
if multiplier < 1 then
|
||||||
|
multiplier = 1
|
||||||
|
end
|
||||||
|
goal = vector.multiply(direction,multiplier)
|
||||||
|
currentvel = self.object:get_velocity()
|
||||||
|
|
||||||
|
if distance > 1 then
|
||||||
|
multiplier = 20 - distance
|
||||||
|
velocity = vector.multiply(direction,multiplier)
|
||||||
|
goal = velocity
|
||||||
|
acceleration = vector.new(goal.x-currentvel.x,goal.y-currentvel.y,goal.z-currentvel.z)
|
||||||
|
self.object:add_velocity(vector.add(acceleration,player_velocity))
|
||||||
|
elseif distance < 0.4 then
|
||||||
|
mcl_experience.add_experience(collector, self._xp)
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
return
|
||||||
|
else
|
||||||
|
self.collector = nil
|
||||||
|
self.enable_physics(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
self.age = self.age + dtime
|
||||||
|
if self.age > 300 then
|
||||||
|
self.object:remove()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
pos = self.object:get_pos()
|
||||||
|
|
||||||
|
if pos then
|
||||||
|
node = minetest.get_node_or_nil({
|
||||||
|
x = pos.x,
|
||||||
|
y = pos.y -0.25,
|
||||||
|
z = pos.z
|
||||||
|
})
|
||||||
|
else
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove nodes in 'ignore'
|
||||||
|
if node and node.name == "ignore" then
|
||||||
|
self.object:remove()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self.physical_state then
|
||||||
|
return -- Don't do anything
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Slide on slippery nodes
|
||||||
|
vel = self.object:get_velocity()
|
||||||
|
def = node and registered_nodes[node.name]
|
||||||
|
is_moving = (def and not def.walkable) or
|
||||||
|
vel.x ~= 0 or vel.y ~= 0 or vel.z ~= 0
|
||||||
|
is_slippery = false
|
||||||
|
|
||||||
|
if def and def.walkable then
|
||||||
|
slippery = minetest.get_item_group(node.name, "slippery")
|
||||||
|
is_slippery = slippery ~= 0
|
||||||
|
if is_slippery and (math.abs(vel.x) > 0.2 or math.abs(vel.z) > 0.2) then
|
||||||
|
-- Horizontal deceleration
|
||||||
|
slip_factor = 4.0 / (slippery + 4)
|
||||||
|
self.object:set_acceleration({
|
||||||
|
x = -vel.x * slip_factor,
|
||||||
|
y = 0,
|
||||||
|
z = -vel.z * slip_factor
|
||||||
|
})
|
||||||
|
elseif vel.y == 0 then
|
||||||
|
is_moving = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.moving_state == is_moving and self.slippery_state == is_slippery then
|
||||||
|
-- Do not update anything until the moving state changes
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
self.moving_state = is_moving
|
||||||
|
self.slippery_state = is_slippery
|
||||||
|
|
||||||
|
if is_moving then
|
||||||
|
self.object:set_acceleration(gravity)
|
||||||
|
else
|
||||||
|
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||||
|
self.object:set_velocity({x = 0, y = 0, z = 0})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_entity("mcl_experience:orb", {
|
||||||
|
initial_properties = {
|
||||||
|
hp_max = 1,
|
||||||
|
physical = true,
|
||||||
|
collide_with_objects = false,
|
||||||
|
collisionbox = {-0.2, -0.2, -0.2, 0.2, 0.2, 0.2},
|
||||||
|
visual = "sprite",
|
||||||
|
visual_size = {x = 0.4, y = 0.4},
|
||||||
|
textures = {name="experience_orb.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}},
|
||||||
|
spritediv = {x = 1, y = 14},
|
||||||
|
initial_sprite_basepos = {x = 0, y = 0},
|
||||||
|
is_visible = true,
|
||||||
|
pointable = false,
|
||||||
|
static_save = false,
|
||||||
|
},
|
||||||
|
moving_state = true,
|
||||||
|
slippery_state = false,
|
||||||
|
physical_state = true,
|
||||||
|
-- Item expiry
|
||||||
|
age = 0,
|
||||||
|
-- Pushing item out of solid nodes
|
||||||
|
force_out = nil,
|
||||||
|
force_out_start = nil,
|
||||||
|
--Collection Variables
|
||||||
|
collectable = false,
|
||||||
|
try_timer = 0,
|
||||||
|
collected = false,
|
||||||
|
delete_timer = 0,
|
||||||
|
radius = 4,
|
||||||
|
|
||||||
|
|
||||||
|
on_activate = function(self, staticdata, dtime_s)
|
||||||
|
self.object:set_velocity(vector.new(
|
||||||
|
math.random(-2,2)*math.random(),
|
||||||
|
math.random(2,5),
|
||||||
|
math.random(-2,2)*math.random()
|
||||||
|
))
|
||||||
|
self.object:set_armor_groups({immortal = 1})
|
||||||
|
self.object:set_velocity({x = 0, y = 2, z = 0})
|
||||||
|
self.object:set_acceleration(gravity)
|
||||||
|
local xp = tonumber(staticdata)
|
||||||
|
self._xp = xp
|
||||||
|
size = xp_to_size(xp)
|
||||||
|
self.object:set_properties({
|
||||||
|
visual_size = {x = size, y = size},
|
||||||
|
glow = 14,
|
||||||
|
})
|
||||||
|
self.object:set_sprite({x=1,y=math.random(1,14)}, 14, 0.05, false)
|
||||||
|
end,
|
||||||
|
|
||||||
|
enable_physics = function(self)
|
||||||
|
if not self.physical_state then
|
||||||
|
self.physical_state = true
|
||||||
|
self.object:set_properties({physical = true})
|
||||||
|
self.object:set_velocity({x=0, y=0, z=0})
|
||||||
|
self.object:set_acceleration(gravity)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
disable_physics = function(self)
|
||||||
|
if self.physical_state then
|
||||||
|
self.physical_state = false
|
||||||
|
self.object:set_properties({physical = false})
|
||||||
|
self.object:set_velocity({x=0, y=0, z=0})
|
||||||
|
self.object:set_acceleration({x=0, y=0, z=0})
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_step = function(self, dtime)
|
||||||
|
xp_step(self, dtime)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("xp", {
|
||||||
|
params = S("[<player>] [<xp>]"),
|
||||||
|
description = S("Gives [[player <player>] <xp>] XP"),
|
||||||
|
privs = {server=true},
|
||||||
|
func = function(name, params)
|
||||||
|
local player, xp = nil, 1000
|
||||||
|
local P, i = {}, 0
|
||||||
|
for str in string.gmatch(params, "([^ ]+)") do
|
||||||
|
i = i + 1
|
||||||
|
P[i] = str
|
||||||
|
end
|
||||||
|
if i > 2 then
|
||||||
|
return false, S("Error: Too many parameters!")
|
||||||
|
end
|
||||||
|
if i > 0 then
|
||||||
|
xp = tonumber(P[i])
|
||||||
|
end
|
||||||
|
if i < 2 then
|
||||||
|
player = minetest.get_player_by_name(name)
|
||||||
|
end
|
||||||
|
if i == 2 then
|
||||||
|
player = minetest.get_player_by_name(P[1])
|
||||||
|
end
|
||||||
|
if not xp then
|
||||||
|
return false, S("Error: Incorrect value of XP")
|
||||||
|
end
|
||||||
|
if not player then
|
||||||
|
return false, S("Error: Player not found")
|
||||||
|
end
|
||||||
|
mcl_experience.add_experience(player, xp)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
function mcl_experience.throw_experience(pos, amount)
|
||||||
|
local i, j = 0, 0
|
||||||
|
local obj, xp
|
||||||
|
while i < amount and j < 100 do
|
||||||
|
xp = math.min(math.random(1, math.min(32767, amount-math.floor(i/2))), amount-i)
|
||||||
|
obj = minetest.add_entity(pos, "mcl_experience:orb", tostring(xp))
|
||||||
|
if not obj then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
obj:set_velocity({
|
||||||
|
x=math.random(-2,2)*math.random(),
|
||||||
|
y=math.random(2,5),
|
||||||
|
z=math.random(-2,2)*math.random()
|
||||||
|
})
|
||||||
|
i = i + xp
|
||||||
|
j = j + 1
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
[<player>] [<xp>]=[<игрок>] [<xp>]
|
||||||
|
Gives [[player <player>] <xp>] XP=Даёт [[игроку <игрок> [<xp>]] единиц опыта XP
|
||||||
|
Error: Too many parameters!=Ошибка: слишком много параметров!
|
||||||
|
Error: Incorrect value of XP=Ошибка: Недопустимое значение XP
|
||||||
|
Error: Player not found=Ошибка: Игрок не найден
|
|
@ -0,0 +1,5 @@
|
||||||
|
[<player>] [<xp>]=
|
||||||
|
Gives [[player <player>] <xp>] XP=
|
||||||
|
Error: Too many parameters!=
|
||||||
|
Error: Incorrect value of XP=
|
||||||
|
Error: Player not found=
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
experience/level_up - https://freesound.org/people/geraldfiebig/sounds/323123/
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
experience_orb - https://github.com/Gerold55/Experience-Mod/blob/master/textures/orb.png
|
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 891 B |
|
@ -31,7 +31,7 @@ minetest.register_node("mcl_core:stone_with_coal", {
|
||||||
tiles = {"mcl_core_coal_ore.png"},
|
tiles = {"mcl_core_coal_ore.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
stack_max = 64,
|
stack_max = 64,
|
||||||
groups = {pickaxey=1, building_block=1, material_stone=1},
|
groups = {pickaxey=1, building_block=1, material_stone=1, experience=1},
|
||||||
drop = 'mcl_core:coal_lump',
|
drop = 'mcl_core:coal_lump',
|
||||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||||
_mcl_blast_resistance = 3,
|
_mcl_blast_resistance = 3,
|
||||||
|
@ -77,7 +77,7 @@ minetest.register_node("mcl_core:stone_with_redstone", {
|
||||||
tiles = {"mcl_core_redstone_ore.png"},
|
tiles = {"mcl_core_redstone_ore.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
stack_max = 64,
|
stack_max = 64,
|
||||||
groups = {pickaxey=4, building_block=1, material_stone=1},
|
groups = {pickaxey=4, building_block=1, material_stone=1, experience=7},
|
||||||
drop = {
|
drop = {
|
||||||
items = {
|
items = {
|
||||||
max_items = 1,
|
max_items = 1,
|
||||||
|
@ -110,7 +110,7 @@ minetest.register_node("mcl_core:stone_with_redstone_lit", {
|
||||||
light_source = 9,
|
light_source = 9,
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
stack_max = 64,
|
stack_max = 64,
|
||||||
groups = {pickaxey=4, not_in_creative_inventory=1, material_stone=1},
|
groups = {pickaxey=4, not_in_creative_inventory=1, material_stone=1, experience=7},
|
||||||
drop = {
|
drop = {
|
||||||
items = {
|
items = {
|
||||||
max_items = 1,
|
max_items = 1,
|
||||||
|
@ -141,7 +141,7 @@ minetest.register_node("mcl_core:stone_with_lapis", {
|
||||||
tiles = {"mcl_core_lapis_ore.png"},
|
tiles = {"mcl_core_lapis_ore.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
stack_max = 64,
|
stack_max = 64,
|
||||||
groups = {pickaxey=3, building_block=1, material_stone=1},
|
groups = {pickaxey=3, building_block=1, material_stone=1, experience=6},
|
||||||
drop = {
|
drop = {
|
||||||
max_items = 1,
|
max_items = 1,
|
||||||
items = {
|
items = {
|
||||||
|
@ -163,7 +163,7 @@ minetest.register_node("mcl_core:stone_with_emerald", {
|
||||||
tiles = {"mcl_core_emerald_ore.png"},
|
tiles = {"mcl_core_emerald_ore.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
stack_max = 64,
|
stack_max = 64,
|
||||||
groups = {pickaxey=4, building_block=1, material_stone=1},
|
groups = {pickaxey=4, building_block=1, material_stone=1, experience=6},
|
||||||
drop = "mcl_core:emerald",
|
drop = "mcl_core:emerald",
|
||||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||||
_mcl_blast_resistance = 3,
|
_mcl_blast_resistance = 3,
|
||||||
|
@ -176,7 +176,7 @@ minetest.register_node("mcl_core:stone_with_diamond", {
|
||||||
tiles = {"mcl_core_diamond_ore.png"},
|
tiles = {"mcl_core_diamond_ore.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
stack_max = 64,
|
stack_max = 64,
|
||||||
groups = {pickaxey=4, building_block=1, material_stone=1},
|
groups = {pickaxey=4, building_block=1, material_stone=1, experience=4},
|
||||||
drop = "mcl_core:diamond",
|
drop = "mcl_core:diamond",
|
||||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||||
_mcl_blast_resistance = 3,
|
_mcl_blast_resistance = 3,
|
||||||
|
|
|
@ -39,6 +39,9 @@ local fish = function(itemstack, player)
|
||||||
if ent then
|
if ent then
|
||||||
if ent.player and ent.objtype=="fishing" then
|
if ent.player and ent.objtype=="fishing" then
|
||||||
if (player:get_player_name() == ent.player) then
|
if (player:get_player_name() == ent.player) then
|
||||||
|
if mcl_experience.throw_experience then
|
||||||
|
mcl_experience.throw_experience(pos, math.random(1,6))
|
||||||
|
end
|
||||||
noent = false
|
noent = false
|
||||||
if ent._dive == true then
|
if ent._dive == true then
|
||||||
local itemname
|
local itemname
|
||||||
|
|
|
@ -344,6 +344,11 @@ local function furnace_node_timer(pos, elapsed)
|
||||||
|
|
||||||
srclist = inv:get_list("src")
|
srclist = inv:get_list("src")
|
||||||
src_time = 0
|
src_time = 0
|
||||||
|
|
||||||
|
if mcl_experience.throw_experience then
|
||||||
|
local dir = vector.divide(minetest.facedir_to_dir(minetest.get_node(pos).param2),-1.95)
|
||||||
|
mcl_experience.throw_experience(vector.add(pos, dir), 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ minetest.register_node("mcl_nether:quartz_ore", {
|
||||||
stack_max = 64,
|
stack_max = 64,
|
||||||
tiles = {"mcl_nether_quartz_ore.png"},
|
tiles = {"mcl_nether_quartz_ore.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
groups = {pickaxey=1, building_block=1, material_stone=1},
|
groups = {pickaxey=1, building_block=1, material_stone=1, experience=3},
|
||||||
drop = 'mcl_nether:quartz',
|
drop = 'mcl_nether:quartz',
|
||||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||||
_mcl_blast_resistance = 3,
|
_mcl_blast_resistance = 3,
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
--[[
|
||||||
|
swiftness - how fast you mine
|
||||||
|
hardness - allows the tool to go way above it's level
|
||||||
|
durable - makes the tool last longer
|
||||||
|
slippery - you drop the tool randomly
|
||||||
|
careful - "not silk touch"
|
||||||
|
fortune - drops extra items and experience
|
||||||
|
autorepair - tool will repair itself randomly
|
||||||
|
spiky - the tool will randomly hurt you when used
|
||||||
|
sharpness - the tool does more damage
|
||||||
|
]]--
|
||||||
|
local S = minetest.get_translator("mcl_tools")
|
||||||
|
|
||||||
|
local enchantment_list = {"swiftness", "durable", "careful", "fortune", "autorepair", "sharpness"}
|
||||||
|
|
||||||
|
local hexer = {"a","b","c","d","e","f","1","2","3","4","5","6","7","8","9","0"}
|
||||||
|
minetest.register_node("mcl_tools:enchantingtable", {
|
||||||
|
description = S("Enchanting Table"),
|
||||||
|
tiles = {"mcl_core_bedrock.png"},
|
||||||
|
groups = {wood = 1, pathable = 1},
|
||||||
|
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||||
|
is_ground_content = false,
|
||||||
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
|
minetest.after(0,function(clicker)
|
||||||
|
local stack = clicker:get_wielded_item()
|
||||||
|
|
||||||
|
local meta = stack:get_meta()
|
||||||
|
|
||||||
|
if meta:get_string("enchanted") == "true" then return end
|
||||||
|
|
||||||
|
if not minetest.registered_tools[itemstack:get_name()] then return end
|
||||||
|
|
||||||
|
local tool_caps = itemstack:get_tool_capabilities()
|
||||||
|
local groupcaps = tool_caps.groupcaps
|
||||||
|
|
||||||
|
if not groupcaps then return end
|
||||||
|
|
||||||
|
local able_enchantments = table.copy(enchantment_list)
|
||||||
|
|
||||||
|
|
||||||
|
local player_level = mcl_experience.get_player_xp_level(clicker)
|
||||||
|
|
||||||
|
local enchants_available = math.floor(player_level/5)
|
||||||
|
local max_enchant_level = math.floor(player_level/5)
|
||||||
|
if enchants_available <= 0 then return end
|
||||||
|
if enchants_available > 3 then enchants_available = 3 end
|
||||||
|
local stock_name = minetest.registered_tools[stack:get_name()].name
|
||||||
|
local description = minetest.registered_tools[stack:get_name()].description
|
||||||
|
for i = 1,enchants_available do
|
||||||
|
local new_enchant = enchantment_list[math.random(1,table.getn(enchantment_list))]
|
||||||
|
local level = math.random(1,max_enchant_level)
|
||||||
|
if meta:get_int(new_enchant) == 0 then
|
||||||
|
player_level = player_level - 5
|
||||||
|
meta:set_int(new_enchant, level)
|
||||||
|
description = description.."\n"..new_enchant:gsub("^%l", string.upper)..": "..tostring(level)
|
||||||
|
if new_enchant == "swiftness" then
|
||||||
|
for index,table in pairs(groupcaps) do
|
||||||
|
for index2,time in pairs(table.times) do
|
||||||
|
tool_caps["groupcaps"][index]["times"][index2] = time/(level+1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if new_enchant == "durable" then
|
||||||
|
for index,table in pairs(groupcaps) do
|
||||||
|
tool_caps["groupcaps"][index]["uses"] = table.uses*(level+1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if new_enchant == "sharpness" then
|
||||||
|
for index,data in pairs(tool_caps.damage_groups) do
|
||||||
|
tool_caps.damage_groups[index] = data*(level+1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
meta:set_string("description", S("Enchanted @1", description))
|
||||||
|
meta:set_string("enchanted", "true")
|
||||||
|
meta:set_tool_capabilities(tool_caps)
|
||||||
|
|
||||||
|
mcl_experience.set_player_xp_level(clicker,player_level)
|
||||||
|
|
||||||
|
|
||||||
|
--create truly random hex
|
||||||
|
local colorstring = "#"
|
||||||
|
for i = 1,6 do
|
||||||
|
colorstring = colorstring..hexer[math.random(1,16)]
|
||||||
|
end
|
||||||
|
stack = minetest.itemstring_with_color(stack, colorstring)
|
||||||
|
clicker:set_wielded_item(stack)
|
||||||
|
end,clicker)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "mcl_tools:enchantingtable",
|
||||||
|
recipe = {
|
||||||
|
{"mcl_core:obsidian", "mcl_core:obsidian", "mcl_core:obsidian"},
|
||||||
|
{"mcl_core:obsidian", "mcl_core:diamond", "mcl_core:obsidian"},
|
||||||
|
{"mcl_core:obsidian", "mcl_core:obsidian", "mcl_core:obsidian"},
|
||||||
|
},
|
||||||
|
})
|
|
@ -592,3 +592,4 @@ minetest.register_tool("mcl_tools:shears", {
|
||||||
|
|
||||||
dofile(minetest.get_modpath("mcl_tools").."/crafting.lua")
|
dofile(minetest.get_modpath("mcl_tools").."/crafting.lua")
|
||||||
dofile(minetest.get_modpath("mcl_tools").."/aliases.lua")
|
dofile(minetest.get_modpath("mcl_tools").."/aliases.lua")
|
||||||
|
dofile(minetest.get_modpath("mcl_tools").."/enchanting.lua")
|
||||||
|
|
|
@ -30,3 +30,5 @@ Iron Sword=Eisenschwert
|
||||||
Golden Sword=Goldschwert
|
Golden Sword=Goldschwert
|
||||||
Diamond Sword=Diamantschwert
|
Diamond Sword=Diamantschwert
|
||||||
Shears=Schere
|
Shears=Schere
|
||||||
|
Enchanted @1=
|
||||||
|
Enchanting Table=
|
||||||
|
|
|
@ -30,3 +30,5 @@ Iron Sword=Espada de hierro
|
||||||
Golden Sword=Espada de oro
|
Golden Sword=Espada de oro
|
||||||
Diamond Sword=Espada de diamante
|
Diamond Sword=Espada de diamante
|
||||||
Shears=Tijeras
|
Shears=Tijeras
|
||||||
|
Enchanted @1=
|
||||||
|
Enchanting Table=
|
||||||
|
|
|
@ -30,3 +30,5 @@ Iron Sword=Épée en Fer
|
||||||
Golden Sword=Épée en Or
|
Golden Sword=Épée en Or
|
||||||
Diamond Sword=Épée en Diamant
|
Diamond Sword=Épée en Diamant
|
||||||
Shears=Cisailles
|
Shears=Cisailles
|
||||||
|
Enchanted @1=
|
||||||
|
Enchanting Table=
|
||||||
|
|
|
@ -30,3 +30,5 @@ Iron Sword=Железный меч
|
||||||
Golden Sword=Золотой меч
|
Golden Sword=Золотой меч
|
||||||
Diamond Sword=Алмазный меч
|
Diamond Sword=Алмазный меч
|
||||||
Shears=Ножницы
|
Shears=Ножницы
|
||||||
|
Enchanted @1=@1 зачарованный(ая)
|
||||||
|
Enchanting Table=Волшебный стол
|
||||||
|
|
|
@ -30,3 +30,5 @@ Iron Sword=
|
||||||
Golden Sword=
|
Golden Sword=
|
||||||
Diamond Sword=
|
Diamond Sword=
|
||||||
Shears=
|
Shears=
|
||||||
|
Enchanted @1=
|
||||||
|
Enchanting Table=
|
||||||
|
|
Loading…
Reference in New Issue