diff --git a/defaults.lua b/defaults.lua index 59e6bae..7dfa340 100644 --- a/defaults.lua +++ b/defaults.lua @@ -5,3 +5,11 @@ DISABLE_BRONZE_SPEAR = false DISABLE_DIAMOND_SPEAR = false DISABLE_OBSIDIAN_SPEAR = false DISABLE_GOLD_SPEAR = false +SPEARS_THROW_SPEED = 13 +SPEARS_V_ZERO = {x = 0, y = 0, z = 0} +SPEARS_DRAG_COEFF = 0.1 +SPEARS_NODE_UNKNOWN = nil +SPEARS_NODE_THROUGH = 0 +SPEARS_NODE_STICKY = 1 +SPEARS_NODE_CRACKY = 2 +SPEARS_NODE_CRACKY_LIMIT = 3 diff --git a/functions.lua b/functions.lua index 1b9d33f..9f23bd1 100644 --- a/functions.lua +++ b/functions.lua @@ -7,30 +7,39 @@ function spears_throw (itemstack, player, pointed_thing) local pitch = player:get_look_vertical() local yaw = player:get_look_horizontal() local rotation = vector.new(0, yaw + math.pi/2, pitch + math.pi/6) - -- Stick into node - if pointed_thing.type == "node" then - local node = minetest.get_node(pointed_thing.under) - if minetest.registered_nodes[node.name].walkable and vector.distance(pointed_thing.above, throw_pos) < 1 then - local spear_object = minetest.add_entity(vector.divide(vector.add(vector.multiply(pointed_thing.above, 2), pointed_thing.under), 3), spear) + local wear = itemstack:get_wear() + local pointed_a = pointed_thing.above + local pointed_b = pointed_thing.under + if pointed_thing.type == "node" and vector.distance(pointed_a, throw_pos) < 1 then -- Stick into node + local node = minetest.get_node(pointed_b) + local check_node = spears_check_node(node.name) + if check_node == SPEARS_NODE_UNKNOWN then + return false + elseif check_node == SPEARS_NODE_CRACKY then + minetest.sound_play("default_metal_footstep", {pos = pointed_a}, true) + return false + elseif check_node == SPEARS_NODE_STICKY then + local spear_object = minetest.add_entity(vector.divide(vector.add(vector.multiply(pointed_a, 2), pointed_b), 3), spear) spear_object:set_rotation(rotation) - spear_object:get_luaentity()._wear = itemstack:get_wear() - spear_object:get_luaentity()._stickpos = pointed_thing.under - return + spear_object:get_luaentity()._wear = wear + spear_object:get_luaentity()._stickpos = pointed_b + minetest.sound_play("default_place_node", {pos = pointed_a}, true) + return false end + else -- Avoid hitting yourself and throw + local throw_speed = SPEARS_THROW_SPEED + while vector.distance(player_pos, throw_pos) < 1.2 do + throw_pos = vector.add(throw_pos, vector.multiply(direction, 0.1)) + end + local player_vel = player:get_velocity() + local spear_object = minetest.add_entity(throw_pos, spear) + spear_object:set_velocity(vector.add(player_vel, vector.multiply(direction, throw_speed))) + spear_object:set_rotation(rotation) + minetest.sound_play("spears_throw", {pos = player_pos}, true) + spear_object:get_luaentity()._wear = wear + spear_object:get_luaentity()._stickpos = nil + return true end - -- Avoid hitting yourself and throw - local throw_speed = 12 - while vector.distance(player_pos, throw_pos) < 1.2 do - throw_pos = vector.add(throw_pos, vector.multiply(direction, 0.1)) - end - local player_vel = player:get_velocity() - local spear_object = minetest.add_entity(throw_pos, spear) - spear_object:set_velocity(vector.add(player_vel, vector.multiply(direction, throw_speed))) - spear_object:set_rotation(rotation) - minetest.sound_play("spears_throw", {pos = player_pos}, true) - spear_object:get_luaentity()._wear = itemstack:get_wear() - spear_object:get_luaentity()._stickpos = nil - return true end function spears_set_entity(spear_type, base_damage, toughness) @@ -59,36 +68,27 @@ function spears_set_entity(spear_type, base_damage, toughness) end, on_step = function(self, dtime) - if not self._wear then + local wear = self._wear + if wear == nil then self.object:remove() - return + return false end local pos = self.object:get_pos() local velocity = self.object:get_velocity() local speed = vector.length(velocity) - -- Spear is stuck ? - if self._stickpos then + if self._stickpos ~= nil then -- Spear is stuck local node = minetest.get_node(self._stickpos) - local node_cracky = minetest.registered_nodes[node.name].groups.cracky - if node_cracky and node_cracky < 3 then - minetest.sound_play("default_metal_footstep", {pos = pos}, true) + local check_node = spears_check_node(node.name) + if check_node ~= SPEARS_NODE_STICKY then -- Fall when node is removed self.object:remove() - minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = self._wear}) - elseif not self._node_walkable then - minetest.sound_play("default_place_node", {pos = pos}, true) - end - self._node_walkable = minetest.registered_nodes[node.name].walkable - if not node or not self._node_walkable then -- Fall when node is removed - self.object:remove() - minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = self._wear}) - return + minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = wear}) + return false end else -- Spear is flying local direction = vector.normalize(velocity) local yaw = minetest.dir_to_yaw(direction) local pitch = math.acos(velocity.y/speed) - math.pi/3 local spearhead_pos = vector.add(pos, vector.multiply(direction, 0.5)) - local node = minetest.get_node(spearhead_pos) self.object:set_rotation({x = 0, y = yaw + math.pi/2, z = pitch}) -- Hit someone? local objects_in_radius = minetest.get_objects_inside_radius(spearhead_pos, 0.6) @@ -98,26 +98,39 @@ function spears_set_entity(spear_type, base_damage, toughness) object:punch(self.object, 1.0, {full_punch_interval = 1.0, damage_groups = {fleshy=damage},}, direction) self.object:remove() minetest.sound_play("spears_hit", {pos = pos}, true) - minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = self._wear + 65535/toughness}) - return + wear = spears_wear(wear, toughness) + minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = wear}) + return true end end - -- Hit a node? - if node and minetest.registered_nodes[node.name].walkable - and not minetest.registered_nodes[node.name].buildable_to - and not (minetest.registered_nodes[node.name].groups.slab and spearhead_pos.y % 1 < 0.5) - then -- Stick - self.object:set_acceleration({x = 0, y = 0, z = 0}) - self.object:set_velocity({x = 0, y = 0, z = 0}) - self._wear = self._wear + 65535/toughness - if self._wear >= 65535 then + -- Hit a node? + local node = minetest.get_node(spearhead_pos) + local check_node = spears_check_node(node.name) + if check_node == SPEARS_NODE_UNKNOWN then + self.object:remove() + minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = wear}) + elseif check_node ~= SPEARS_NODE_THROUGH then + wear = spears_wear(wear, toughness) + if wear >= 65535 then minetest.sound_play("default_tool_breaks", {pos = pos}, true) self.object:remove() - return + minetest.add_item(pos, {name='defaut:stick'}) + return false + elseif check_node == SPEARS_NODE_CRACKY then + minetest.sound_play("default_metal_footstep", {pos = pos}, true) + self.object:remove() + minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = wear}) + return false + elseif check_node == SPEARS_NODE_STICKY then + self.object:set_acceleration(SPEARS_V_ZERO) + self.object:set_velocity(SPEARS_V_ZERO) + minetest.sound_play("default_place_node", {pos = pos}, true) + self._stickpos = spearhead_pos + self._wear = wear end - self._stickpos = spearhead_pos - else -- Get drag - local drag = math.max(minetest.registered_nodes[node.name].liquid_viscosity, 0.1) + else -- Get drag + local viscosity = minetest.registered_nodes[node.name].liquid_viscosity + local drag = math.max(viscosity, SPEARS_DRAG_COEFF) local acceleration = vector.multiply(velocity, -drag) acceleration.y = acceleration.y - 10 * ((7 - drag) / 7) self.object:set_acceleration(acceleration) @@ -127,3 +140,26 @@ function spears_set_entity(spear_type, base_damage, toughness) } return SPEAR_ENTITY end + +function spears_check_node(node_name) + local node = minetest.registered_nodes[node_name] + if node == nil then + return SPEARS_NODE_UNKNOWN + elseif node.groups.cracky ~= nil and node.groups.cracky < SPEARS_NODE_CRACKY_LIMIT then + return SPEARS_NODE_CRACKY + elseif node.walkable and not node.buildable then + return SPEARS_NODE_STICKY + else + return SPEARS_NODE_THROUGH + end +end + +function spears_wear(initial_wear, toughness) + if not minetest.settings:get_bool("creative_mode") then + local wear = initial_wear + 65535/toughness + return wear + else + local wear = initial_wear + return wear + end +end diff --git a/spears.conf.example b/spears.conf.example index a9bed2d..a92a86d 100644 --- a/spears.conf.example +++ b/spears.conf.example @@ -5,3 +5,4 @@ DISABLE_BRONZE_SPEAR = true DISABLE_DIAMOND_SPEAR = true DISABLE_OBSIDIAN_SPEAR = true DISABLE_GOLD_SPEAR = true +SPEARS_THROW_SPEED = 13