X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=mods%2Fexperience%2Finit.lua;h=f40f107564aeb83b528fb47dcb6274b6243f9a23;hb=753549dc8fb7b824691b4741f1fc68cf836c8605;hp=7c1c9af3de6a8877d5ad6670895eb24210a11d0b;hpb=7b150036b88c3c9dc67e435bb2cce595527b852f;p=Crafter.git diff --git a/mods/experience/init.lua b/mods/experience/init.lua index 7c1c9af..f40f107 100644 --- a/mods/experience/init.lua +++ b/mods/experience/init.lua @@ -1,8 +1,42 @@ -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 @@ -14,12 +48,12 @@ local load_data = function(player) 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 @@ -58,6 +92,31 @@ minetest.register_on_shutdown(function() 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}, @@ -165,16 +224,16 @@ local function add_experience(player,experience) 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({ @@ -225,6 +284,150 @@ end) 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, @@ -248,9 +451,6 @@ minetest.register_entity("experience:orb", { 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, @@ -258,9 +458,8 @@ minetest.register_entity("experience:orb", { 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, @@ -270,35 +469,32 @@ minetest.register_entity("experience:orb", { 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) @@ -319,198 +515,7 @@ minetest.register_entity("experience:orb", { 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, }) @@ -520,7 +525,7 @@ minetest.register_chatcommand("xp", { 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)