From 119116b89ed7309d4c77352de7e1a89160779a63 Mon Sep 17 00:00:00 2001 From: echoes91 Date: Sun, 19 Apr 2020 18:50:54 +0200 Subject: [PATCH] Sticking great into nodes --- README.txt | 19 ++++++++- functions.lua | 104 +++++++++++++++++++++++++++++++++----------------- tools.lua | 8 ++-- 3 files changed, 90 insertions(+), 41 deletions(-) diff --git a/README.txt b/README.txt index 2226bbe..b66d590 100644 --- a/README.txt +++ b/README.txt @@ -7,9 +7,26 @@ http://wiki.minetest.com/wiki/Installing_Mods How to use the mod: Craft a spear with | stick | stick | (material) |, 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 drag. +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 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. +You can grab a spear on the fly (or maybe wait until it falls). +If you feel even clever, throw a spear right above you and look at it to see what happens. +Someone was reported to have hit its own foot but it takes practice. + + +CHANGELOG + +2.0: +- Cleaned, streamlined code without deprecated functions +- Spears animated in flight +- Spears stick into nodes +- New sound when hitting flesh +- Changed receipt to fit with default tools +- + +1.1: +- Make use of new on_secondary_use API, requires Minetest 5.2.0 License: diff --git a/functions.lua b/functions.lua index 5757417..8be4c87 100644 --- a/functions.lua +++ b/functions.lua @@ -1,18 +1,35 @@ -function spears_shot (itemstack, player) +function spears_throw (itemstack, player, pointed_thing) local spear = itemstack:get_name() .. '_entity' - local playerpos = player:getpos() - local spear_object = minetest.add_entity({x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, spear) + local player_pos = player:get_pos() + local head_pos = vector.new(player_pos.x, player_pos.y + player:get_properties().eye_height, player_pos.z) local direction = player:get_look_dir() + local throw_pos = vector.add(head_pos, vector.multiply(direction,0.5)) local pitch = player:get_look_vertical() local yaw = player:get_look_horizontal() local throw_speed = 15 - local drag = 0.3 - local gravity = 9.8 - spear_object:set_velocity({x = direction.x*throw_speed, y = direction.y*throw_speed, z = direction.z*throw_speed}) - spear_object:set_acceleration({x = -direction.x*drag, y = -gravity, z = -direction.z*drag}) - spear_object:set_rotation({x = 0, y = yaw + math.pi/2, z = pitch + math.pi/6}) - minetest.sound_play("spears_throw", {pos = playerpos}, true) + 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.add(throw_pos, vector.multiply(direction,0.5)), spear) + spear_object:set_rotation(rotation) + minetest.sound_play("default_place_node", {pos = throw_pos}, true) + spear_object:get_luaentity()._wear = itemstack:get_wear() + spear_object:get_luaentity()._stickpos = pointed_thing.under + return + end + end + -- Avoid hitting yourself and throw + while vector.distance(player_pos, throw_pos) < 1 do + throw_pos = vector.add(throw_pos, vector.multiply(direction,0.1)) + end + local spear_object = minetest.add_entity(throw_pos, spear) + spear_object:set_velocity(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 @@ -42,39 +59,54 @@ function spears_set_entity(spear_type, base_damage, toughness) self.object:remove() return end - local acceleration = self.object:get_acceleration() local velocity = self.object:get_velocity() local speed = vector.length(velocity) - local yaw = minetest.dir_to_yaw(velocity) - local pitch = math.acos(velocity.y/speed) - math.pi/3 - local pos = vector.add(self.object:get_pos(), vector.multiply(velocity, dtime)) - local node = minetest.get_node(pos) - if speed > 0 then - if node.name ~= "air" and minetest.get_item_group(node.name, 'attached_node') < 1 then - self.object:set_acceleration({x = 0, y = 0, z = 0}) - self.object:set_velocity({x = 0, y = 0, z = 0}) - minetest.sound_play("default_place_node.2", {pos = pos}, true) - self._wear = self._wear + 65535/toughness - if self._wear >= 65535 then + if self._stickpos then + local node = minetest.get_node(self._stickpos) + if not node or not minetest.registered_nodes[node.name].walkable then + self.object:remove() + minetest.add_item(self.object:get_pos(), {name='spears:spear_' .. spear_type, wear = self._wear}) + return + end + else + local direction = vector.normalize(velocity) + local yaw = minetest.dir_to_yaw(velocity) + local pitch = math.acos(velocity.y/speed) - math.pi/3 + local pos = vector.add(self.object:get_pos(), vector.multiply(velocity, dtime)) + local node = minetest.get_node(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(pos, 0.5) + 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) + minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = self._wear + 65535/toughness}) return end - else - self.object:set_rotation({x = 0, y = yaw + math.pi/2, z = pitch}) - local objects_in_radius = minetest.get_objects_inside_radius(pos, 1) - for _,object in ipairs(objects_in_radius) do - if object:is_player() or (object:get_luaentity().name ~= self.name and object:get_luaentity().name ~= "_builtin:item") then - local direction = vector.normalize(velocity) - 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) - if self._wear + 65535/toughness < 65535 then - minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = self._wear + 65535/toughness}) - end - end - end end + -- Stick or get drag + if node then + if minetest.registered_nodes[node.name].walkable then + self.object:set_acceleration({x = 0, y = 0, z = 0}) + self.object:set_velocity({x = 0, y = 0, z = 0}) + minetest.sound_play("default_place_node", {pos = pos}, true) + 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 = pos + else + 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)^2 + self.object:set_acceleration(acceleration) + end + end end end, } diff --git a/tools.lua b/tools.lua index 1c7d65a..283f45e 100644 --- a/tools.lua +++ b/tools.lua @@ -6,14 +6,14 @@ function spears_register_spear(spear_type, desc, base_damage, toughness, materia inventory_image = "spears_spear_" .. spear_type .. ".png^[transform4", wield_scale= {x=2,y=1,z=1}, on_secondary_use = function(itemstack, user, pointed_thing) - spears_shot(itemstack, user) + spears_throw(itemstack, user, pointed_thing) if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end return itemstack end, on_place = function(itemstack, user, pointed_thing) - spears_shot(itemstack, user) + spears_throw(itemstack, user, pointed_thing) if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end @@ -38,14 +38,14 @@ function spears_register_spear(spear_type, desc, base_damage, toughness, materia minetest.register_craft({ output = 'spears:spear_' .. spear_type, recipe = { - {'group:wood', 'group:wood', material}, + {'group:stick', 'group:stick', material}, } }) minetest.register_craft({ output = 'spears:spear_' .. spear_type, recipe = { - {material, 'group:wood', 'group:wood'}, + {material, 'group:stick', 'group:stick'}, } }) end