2021-11-03 18:36:57 +00:00
|
|
|
local size_min, size_max = 20, 59
|
|
|
|
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
|
|
|
|
|
|
|
|
local max_orb_age = 300 -- seconds
|
|
|
|
local gravity = vector.new(0, -((tonumber(minetest.settings:get("movement_gravity"))) or 9.81), 0)
|
|
|
|
|
|
|
|
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
|
|
|
|
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()) < 7.25 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_velocity() or 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.8 then
|
|
|
|
mcl_experience.add_xp(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 > max_orb_age 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 minetest.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},
|
2023-12-30 03:13:13 +00:00
|
|
|
textures = {"mcl_experience_orb.png"},
|
2021-11-03 18:36:57 +00:00
|
|
|
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)
|
2024-03-30 07:27:49 +00:00
|
|
|
|
|
|
|
-- Assign 0 xp in case the entity was persisted even though it should not have been (static_save = false)
|
|
|
|
-- This was a minetest bug for a while: https://github.com/minetest/minetest/issues/14420
|
|
|
|
local xp = tonumber(staticdata) or 0
|
2021-11-03 18:36:57 +00:00
|
|
|
self._xp = xp
|
2024-03-20 21:52:33 +00:00
|
|
|
size = xp_to_size(xp)
|
2024-03-30 07:27:49 +00:00
|
|
|
|
2024-03-20 21:52:33 +00:00
|
|
|
self.object:set_properties({
|
2021-11-03 18:36:57 +00:00
|
|
|
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,
|
|
|
|
})
|