-local minetest,math,vector,os = minetest,math,vector,os
+local
+minetest,math,vector,os,pairs,type
+=
+minetest,math,vector,os,pairs,type
+
local mod_storage = minetest.get_mod_storage()
-local pool = {}
-local experience_bar_max = 36
+-- minetest library
+local get_node_or_nil = minetest.get_node_or_nil
+local get_time = minetest.get_us_time
+local get_player_by_name = minetest.get_player_by_name
+local yaw_to_dir = minetest.yaw_to_dir
+local dir_to_yaw = minetest.dir_to_yaw
+local get_item_group = minetest.get_item_group
+local serialize = minetest.serialize
+local deserialize = minetest.deserialize
+local play_sound = minetest.sound_play
+local registered_nodes
+minetest.register_on_mods_loaded(function()
+ registered_nodes = minetest.registered_nodes
+end)
+
+-- vector library
+local new_vec = vector.new
+local vec_distance = vector.distance
+local add_vec = vector.add
+local multiply_vec = vector.multiply
+local vec_direction = vector.direction
+
+-- math library
+local pi = math.pi
+local random = math.random
+local abs = math.abs
+
+-- string library
+local s_sub = string.sub
+local s_len = string.len
+
+local pool = {}
-- loads data from mod storage
local name
local temp_pool
temp_pool.xp_level = mod_storage:get_int(name.."xp_level")
temp_pool.xp_bar = mod_storage:get_int(name.."xp_bar" )
temp_pool.buffer = 0
- temp_pool.last_time= os.clock()
+ temp_pool.last_time= get_time()/1000000
else
temp_pool.xp_level = 0
temp_pool.xp_bar = 0
temp_pool.buffer = 0
- temp_pool.last_time= os.clock()
+ temp_pool.last_time= get_time()/1000000
end
end
end)
+local name
+function get_player_xp_level(player)
+ name = player:get_player_name()
+ return(pool[name].xp_level)
+end
+
+local name
+local temp_pool
+function set_player_xp_level(player,level)
+ name = player:get_player_name()
+ pool[name].xp_level = level
+ 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
+
minetest.hud_replace_builtin("health",{
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
temp_pool.xp_bar = temp_pool.xp_bar + experience
if temp_pool.xp_bar > 36 then
- if os.clock() - temp_pool.last_time > 0.04 then
- minetest.sound_play("level_up",{gain=0.2,to_player = name})
- temp_pool.last_time = os.clock()
+ if get_time()/1000000 - temp_pool.last_time > 0.04 then
+ play_sound("level_up",{gain=0.2,to_player = name})
+ temp_pool.last_time = get_time()/1000000
end
temp_pool.xp_bar = temp_pool.xp_bar - 36
level_up_experience(player)
else
- if os.clock() - temp_pool.last_time > 0.01 then
- temp_pool.last_time = os.clock()
- minetest.sound_play("experience",{gain=0.1,to_player = name,pitch=math.random(75,99)/100})
+ if get_time()/1000000 - temp_pool.last_time > 0.01 then
+ temp_pool.last_time = get_time()/1000000
+ play_sound("experience",{gain=0.1,to_player = name,pitch=random(75,99)/100})
end
end
hud_manager.change_hud({
local name
local temp_pool
local collector
+local pos
+local pos2
+local direction
+local distance
+local player_velocity
+local goal
+local currentvel
+local acceleration
+local multiplier
+local velocity
+local node
+local vel
+local def
+local is_moving
+local is_slippery
+local slippery
+local slip_factor
+local size
+local 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 = get_player_by_name(self.collector)
+ if collector and collector:get_hp() > 0 and vec_distance(self.object:get_pos(),collector:get_pos()) < 5 then
+ temp_pool = pool[self.collector]
+
+ self.object:set_acceleration(new_vec(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 = vec_direction(pos,pos2)
+ distance = vec_distance(pos2,pos)
+ multiplier = distance
+ if multiplier < 1 then
+ multiplier = 1
+ end
+ goal = multiply_vec(direction,multiplier)
+ currentvel = self.object:get_velocity()
+
+ if distance > 1 then
+ multiplier = 20 - distance
+ velocity = multiply_vec(direction,multiplier)
+ goal = velocity
+ acceleration = new_vec(goal.x-currentvel.x,goal.y-currentvel.y,goal.z-currentvel.z)
+ self.object:add_velocity(add_vec(acceleration,player_velocity))
+ elseif distance > 0.9 and temp_pool.buffer > 0 then
+ temp_pool.buffer = temp_pool.buffer - dtime
+ multiplier = 20 - distance
+ velocity = multiply_vec(direction,multiplier)
+ goal = multiply_vec(yaw_to_dir(dir_to_yaw(vec_direction(new_vec(pos.x,0,pos.z),new_vec(pos2.x,0,pos2.z)))+pi/2),10)
+ goal = add_vec(player_velocity,goal)
+ acceleration = new_vec(goal.x-currentvel.x,goal.y-currentvel.y,goal.z-currentvel.z)
+ self.object:add_velocity(acceleration)
+ end
+ if distance < 0.4 and temp_pool.buffer <= 0 then
+ temp_pool.buffer = 0.04
+ add_experience(collector,2)
+ 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 = 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 = get_item_group(node.name, "slippery")
+ is_slippery = slippery ~= 0
+ if is_slippery and (abs(vel.x) > 0.2 or 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({x = 0, y = -9.81, z = 0})
+ 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("experience:orb", {
initial_properties = {
hp_max = 1,
force_out = nil,
force_out_start = nil,
--Collection Variables
- collection_timer = 2,
- collection_timer_goal = collection.collection_time,
- collection_height = 0.8,
collectable = false,
try_timer = 0,
collected = false,
radius = 4,
get_staticdata = function(self)
- return minetest.serialize({
+ return serialize({
age = self.age,
- collection_timer = self.collection_timer,
collectable = self.collectable,
try_timer = self.try_timer,
collected = self.collected,
end,
on_activate = function(self, staticdata, dtime_s)
- if string.sub(staticdata, 1, string.len("return")) == "return" then
- local data = minetest.deserialize(staticdata)
+ if s_sub(staticdata, 1, s_len("return")) == "return" then
+ data = deserialize(staticdata)
if data and type(data) == "table" then
self.age = (data.age or 0) + dtime_s
- self.collection_timer = data.collection_timer
self.collectable = data.collectable
self.try_timer = data.try_timer
self.collected = data.collected
self.delete_timer = data.delete_timer
self.collector = data.collector
- --print("restored timer: "..self.collection_timer)
end
else
-
- local x=math.random(-2,2)*math.random()
- local y=math.random(2,5)
- local z=math.random(-2,2)*math.random()
- self.object:set_velocity(vector.new(x,y,z))
- -- print(self.collection_timer)
+ self.object:set_velocity(new_vec(
+ random(-2,2)*random(),
+ random(2,5),
+ random(-2,2)*random()
+ ))
end
self.object:set_armor_groups({immortal = 1})
self.object:set_velocity({x = 0, y = 2, z = 0})
self.object:set_acceleration({x = 0, y = -9.81, z = 0})
- local size = math.random(20,36)/100
+ size = random(20,36)/100
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)
+ self.object:set_sprite({x=1,y=random(1,14)}, 14, 0.05, false)
end,
enable_physics = function(self)
end
end,
on_step = function(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
- temp_pool = pool[self.collector]
-
- self.object:set_acceleration(vector.new(0,0,0))
- self.disable_physics(self)
- --get the variables
- local pos = self.object:get_pos()
- local pos2 = collector:get_pos()
-
- local player_velocity = collector:get_player_velocity()
-
- pos2.y = pos2.y + self.collection_height
-
- local direction = vector.direction(pos,pos2)
- local distance = vector.distance(pos2,pos)
- local multiplier = distance
- if multiplier < 1 then
- multiplier = 1
- end
- local goal = vector.multiply(direction,multiplier)
- local currentvel = self.object:get_velocity()
- local acceleration
-
- if distance > 1 then
- local multiplier = 20 - distance
- local velocity = vector.multiply(direction,multiplier)
- local goal = velocity--vector.add(player_velocity,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.9 and temp_pool.buffer > 0 then
- temp_pool.buffer = temp_pool.buffer - dtime
- local multiplier = 20 - distance
- local velocity = vector.multiply(direction,multiplier)
- local goal = vector.multiply(minetest.yaw_to_dir(minetest.dir_to_yaw(vector.direction(vector.new(pos.x,0,pos.z),vector.new(pos2.x,0,pos2.z)))+math.pi/2),10)
- goal = vector.add(player_velocity,goal)
- acceleration = vector.new(goal.x-currentvel.x,goal.y-currentvel.y,goal.z-currentvel.z)
- self.object:add_velocity(acceleration)
- end
- if distance < 0.4 and temp_pool.buffer <= 0 then
- temp_pool.buffer = 0.04
- add_experience(collector,2)
- self.object:remove()
- end
- return
- else
- self.collector = nil
- self.enable_physics(self)
- end
- end
-
- --allow entity to be collected after timer
- if self.collectable == false and self.collection_timer >= self.collection_timer_goal then
- self.collectable = true
- elseif self.collectable == false then
- self.collection_timer = self.collection_timer + dtime
- end
-
- self.age = self.age + dtime
- if self.age > 300 then
- self.object:remove()
- return
- end
-
- local pos = self.object:get_pos()
- local node
- if pos then
- node = minetest.get_node_or_nil({
- x = pos.x,
- y = pos.y + self.object:get_properties().collisionbox[2] - 0.05,
- z = pos.z
- })
- else
- return
- end
-
- -- Remove nodes in 'ignore'
- if node and node.name == "ignore" then
- self.object:remove()
- return
- end
-
- local is_stuck = false
- local snode = minetest.get_node_or_nil(pos)
- if snode then
- local sdef = minetest.registered_nodes[snode.name] or {}
- is_stuck = (sdef.walkable == nil or sdef.walkable == true)
- and (sdef.collision_box == nil or sdef.collision_box.type == "regular")
- and (sdef.node_box == nil or sdef.node_box.type == "regular")
- end
-
- -- Push item out when stuck inside solid node
- if is_stuck then
- local shootdir
- local order = {
- {x=1, y=0, z=0}, {x=-1, y=0, z= 0},
- {x=0, y=0, z=1}, {x= 0, y=0, z=-1},
- }
-
- -- Check which one of the 4 sides is free
- for o = 1, #order do
- local cnode = minetest.get_node(vector.add(pos, order[o])).name
- local cdef = minetest.registered_nodes[cnode] or {}
- if cnode ~= "ignore" and cdef.walkable == false then
- shootdir = order[o]
- break
- end
- end
- -- If none of the 4 sides is free, check upwards
- if not shootdir then
- shootdir = {x=0, y=1, z=0}
- local cnode = minetest.get_node(vector.add(pos, shootdir)).name
- if cnode == "ignore" then
- shootdir = nil -- Do not push into ignore
- end
- end
-
- if shootdir then
- -- Set new item moving speed accordingly
- local newv = vector.multiply(shootdir, 3)
- self:disable_physics()
- self.object:set_velocity(newv)
-
- self.force_out = newv
- self.force_out_start = vector.round(pos)
- return
- end
- elseif self.force_out then
- -- This code runs after the entity got a push from the above code.
- -- It makes sure the entity is entirely outside the solid node
- local c = self.object:get_properties().collisionbox
- local s = self.force_out_start
- local f = self.force_out
- local ok = (f.x > 0 and pos.x + c[1] > s.x + 0.5) or
- (f.y > 0 and pos.y + c[2] > s.y + 0.5) or
- (f.z > 0 and pos.z + c[3] > s.z + 0.5) or
- (f.x < 0 and pos.x + c[4] < s.x - 0.5) or
- (f.z < 0 and pos.z + c[6] < s.z - 0.5)
- if ok then
- -- Item was successfully forced out
- self.force_out = nil
- self:enable_physics()
- end
- end
-
- if not self.physical_state then
- return -- Don't do anything
- end
-
- -- Slide on slippery nodes
- local vel = self.object:get_velocity()
- local def = node and minetest.registered_nodes[node.name]
- local is_moving = (def and not def.walkable) or
- vel.x ~= 0 or vel.y ~= 0 or vel.z ~= 0
- local is_slippery = false
-
- if def and def.walkable then
- local 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
- local 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({x = 0, y = -9.81, z = 0})
- else
- self.object:set_acceleration({x = 0, y = 0, z = 0})
- self.object:set_velocity({x = 0, y = 0, z = 0})
- end
+ xp_step(self, dtime)
end,
})
description = "Spawn x amount of a mob, used as /spawn 'mob' 10 or /spawn 'mob' for one",
privs = {server=true},
func = function(name)
- local player = minetest.get_player_by_name(name)
+ local player = get_player_by_name(name)
local pos = player:get_pos()
pos.y = pos.y + 1.2
minetest.throw_experience(pos, 1000)