diff --git a/CHANGELOG b/CHANGELOG index 4bc3040..1a53d7c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,12 @@ +Version 2.4: +- Functions rewrite, fixed many vector/variable declarations and unknown node handling +- Added pigiron support + +Version 2.3: +- Updated to Minetest 5.6.0 API +- Changed receipts to avoid being confused with arrows +- Various cleansing and fixes + Version 2.2: - "Hit detection" based on spearhead position - Spears go through buildable_to nodes (snow) diff --git a/README b/README index 9c02ecf..1f42b23 100644 --- a/README +++ b/README @@ -12,14 +12,17 @@ How to install: http://wiki.minetest.com/wiki/Installing_Mods How to use the mod: -Craft a spear with | stick | stick | (material) |, works also mirrored. +Craft a spear with | | | (material) | + | | stick | | + | stick | | |, +works also mirrored. Spears can be thrown using right mouse button, they either hurt someone or stick where they land on; damage depends on speed and material, flight trajectory is ballistic with (unrealistic) drag. Spears can be used to fight, but are slower and weaker than swords. Spears can be used to dig, but are slower and weaker and pickaxes. If you miss the target it's your fault, the spear is fine. You can grab a spear on the fly (or maybe wait until it falls?). You can stick a spear into a block, but if you remove the block then the spear falls (obviously). -This mod contains the word "spear" more than 100 times, if you want the exact number count them yourself. +This mod contains the word "spear" more than 100 times, if you want the exact number you can count them. If you feel clever, throw a spear right above you and look at it to see what happens. You can even throw a spear from above down to your foes, it's even easier to hit. Someone once reported to have hit its own foot but it takes practice to do that. diff --git a/defaults.lua b/defaults.lua index 59e6bae..7b9edaa 100644 --- a/defaults.lua +++ b/defaults.lua @@ -5,3 +5,12 @@ DISABLE_BRONZE_SPEAR = false DISABLE_DIAMOND_SPEAR = false DISABLE_OBSIDIAN_SPEAR = false DISABLE_GOLD_SPEAR = false +DISABLE_IRON_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 1435b51..abc4a11 100644 --- a/functions.lua +++ b/functions.lua @@ -7,36 +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) - -- Plant 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 - if player.is_fake_player then - player_vel = {x=0,y=0,z=0} - else - player_vel = player:get_velocity() - end - 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().lastpos = throw_pos - spear_object:get_luaentity()._stickpos = nil - return true end function spears_set_entity(spear_type, base_damage, toughness) @@ -66,116 +69,98 @@ 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 - local pos = self.object:get_pos() - 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 = self._stickpos}, 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 newpos = self.object:get_pos() - for _, pos in pairs(spears_get_trajectoire(self, newpos)) do - 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, 2.5) - for _,object in ipairs(objects_in_radius) do - if object:get_luaentity() ~= self and object:get_armor_groups().fleshy then - local objpos = object:get_pos() - local collisionbox = object:get_properties().collisionbox or {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5} - if spears_touch(spearhead_pos, objpos, collisionbox) then - local damage = (speed + base_damage)^1.15 - 20 - 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 - end - 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 - minetest.sound_play("default_tool_breaks", {pos = pos}, true) - self.object:remove() - return - end - self._stickpos = spearhead_pos - self.lastpos = pos - return - else -- Get drag - local drag = math.max(minetest.registered_nodes[node.name].liquid_viscosity, 0.1) - local acceleration = vector.multiply(velocity, -drag) - acceleration.y = acceleration.y - 10 * ((7 - drag) / 7) - self.object:set_acceleration(acceleration) + 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)) + 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) + for _,object in ipairs(objects_in_radius) do + if object:get_luaentity() ~= self and object:get_armor_groups().fleshy then + local damage = (speed + base_damage)^1.15 - 20 + 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) + wear = spears_wear(wear, toughness) + minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = wear}) + return true end end - self.lastpos = newpos + -- 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() + 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 + 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) + end end end, } return SPEAR_ENTITY end - -function spears_get_trajectoire(self, newpos) - if self.lastpos.x == nil then - return {newpos} +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 - local coord = {} - local dx = vector.distance({x=newpos["x"], y=0, z=0}, {x=self.lastpos["x"], y=0, z=0} )/2 - local dy = vector.distance({x=0, y=newpos["y"], z=0}, {x=0, y=self.lastpos["y"], z=0} )/2 - local dz = vector.distance({x=0, y=0, z=newpos["z"]}, {x=0, y=0, z=self.lastpos["z"]} )/2 - - if newpos["x"] < self.lastpos["x"] then - dx = -dx - end - if newpos["y"] < self.lastpos["y"] then - dy = -dy - end - if newpos["z"] < self.lastpos["z"] then - dz = -dz - end - table.insert(coord, {x=self.lastpos["x"]+dx, y=self.lastpos["y"]+dy ,z=self.lastpos["z"]+dz }) - table.insert(coord, newpos) - return coord end - -function spears_touch(pos, objpos, cbox) - --colbox format {x1, y1, z1, x2, y2, z2} - if (pos.x < objpos.x + math.max(cbox[1], cbox[4]) and pos.x > objpos.x + math.min(cbox[1], cbox[4])) - and (pos.y < objpos.y + math.max(cbox[2], cbox[5]) and pos.y > objpos.y + math.min(cbox[2], cbox[5])) - and (pos.z < objpos.z + math.max(cbox[3], cbox[6]) and pos.z > objpos.z + math.min(cbox[3], cbox[6])) then - return true +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 - return false end diff --git a/init.lua b/init.lua index 5556e18..eca9a05 100644 --- a/init.lua +++ b/init.lua @@ -11,5 +11,8 @@ dofile(minetest.get_modpath("spears").."/functions.lua") dofile(minetest.get_modpath("spears").."/tools.lua") +local log_mods = minetest.settings:get_bool("log_mods") -minetest.log("action", "[spears] loaded.") +if minetest.settings:get_bool("log_mods") then + minetest.log("action", "[MOD] Spears loaded") +end diff --git a/mod.conf b/mod.conf index e520b80..29dd3d4 100644 --- a/mod.conf +++ b/mod.conf @@ -1,4 +1,6 @@ name = spears -title = Separs -description = Add spears to Minetest depends = default +description = Add spears to Minetest, versatile weapons that can be thrown +author = Echoes91 +title = Spears +min_minetest_version = 5.4 diff --git a/spears.conf.example b/spears.conf.example index 241ce08..a92a86d 100644 --- a/spears.conf.example +++ b/spears.conf.example @@ -3,4 +3,6 @@ DISABLE_STEEL_SPEAR = true DISABLE_COPPER_SPEAR = true DISABLE_BRONZE_SPEAR = true DISABLE_DIAMOND_SPEAR = true -DISABLE_OBSIDIAN_SPEAR = true \ No newline at end of file +DISABLE_OBSIDIAN_SPEAR = true +DISABLE_GOLD_SPEAR = true +SPEARS_THROW_SPEED = 13 diff --git a/textures/spears_spear_iron.png b/textures/spears_spear_iron.png new file mode 100644 index 0000000..659bcda Binary files /dev/null and b/textures/spears_spear_iron.png differ diff --git a/tools.lua b/tools.lua index 92f9097..a17b12d 100644 --- a/tools.lua +++ b/tools.lua @@ -48,18 +48,18 @@ function spears_register_spear(spear_type, desc, base_damage, toughness, materia minetest.register_craft({ output = 'spears:spear_' .. spear_type, recipe = { - {'', '', material}, - {'', 'group:stick', ''}, - {'group:stick', '', ''}, + {"", "", material}, + {"", "group:stick", ""}, + {"group:stick", "", ""} } }) minetest.register_craft({ output = 'spears:spear_' .. spear_type, recipe = { - {material, '', ''}, - {'', 'group:stick', ''}, - {'', '', 'group:stick'}, + {material, "", ""}, + {"", "group:stick", ""}, + {"", "", "group:stick"} } }) end @@ -68,17 +68,31 @@ if not DISABLE_STONE_SPEAR then spears_register_spear('stone', 'Stone', 4, 20, 'group:stone') end -if not DISABLE_STEEL_SPEAR then - spears_register_spear('steel', 'Steel', 6, 30, 'default:steel_ingot') +if minetest.get_modpath("pigiron") then + if not DISABLE_IRON_SPEAR then + spears_register_spear('iron', 'Iron', 5.5, 30, 'pigiron:iron_ingot') + end + if not DISABLE_STEEL_SPEAR then + spears_register_spear('steel', 'Steel', 6, 35, 'default:steel_ingot') + end + if not DISABLE_COPPER_SPEAR then + spears_register_spear('copper', 'Copper', 4.8, 30, 'default:copper_ingot') + end + if not DISABLE_BRONZE_SPEAR then + spears_register_spear('bronze', 'Bronze', 5.5, 35, 'default:bronze_ingot') + end +else + if not DISABLE_STEEL_SPEAR then + spears_register_spear('steel', 'Steel', 6, 30, 'default:steel_ingot') + end + if not DISABLE_COPPER_SPEAR then + spears_register_spear('copper', 'Copper', 5, 30, 'default:copper_ingot') + end + if not DISABLE_BRONZE_SPEAR then + spears_register_spear('bronze', 'Bronze', 6, 35, 'default:bronze_ingot') + end end -if not DISABLE_COPPER_SPEAR then - spears_register_spear('copper', 'Copper', 5, 35, 'default:copper_ingot') -end - -if not DISABLE_BRONZE_SPEAR then - spears_register_spear('bronze', 'Bronze', 6, 35, 'default:bronze_ingot') -end if not DISABLE_OBSIDIAN_SPEAR then spears_register_spear('obsidian', 'Obsidian', 8, 30, 'default:obsidian')