From a860f0bd974c76ee80e800c0d99db898872c5a5d Mon Sep 17 00:00:00 2001 From: Tai Kedzierski Date: Sat, 5 Jan 2019 01:54:24 +0000 Subject: [PATCH] Fix spears * only place one spear entity for multiple mobs hit * widen the area of effect of it * remove delay for effect * remove tons of duplicate code!! * reduce wear when no hit * generalize which nodes can be shot through --- tools/spears.lua | 240 +++++++++++++++++++---------------------------- 1 file changed, 95 insertions(+), 145 deletions(-) diff --git a/tools/spears.lua b/tools/spears.lua index 7f7acae..5af641f 100644 --- a/tools/spears.lua +++ b/tools/spears.lua @@ -1,38 +1,65 @@ -function spears_shot (itemstack, player) +local creative_mode = minetest.settings:get_bool("creative_mode") + +local function is_walkable(node_name) + if not minetest.registered_nodes[node_name] then + return true -- non-existent, we should stop the spear ! + end + if minetest.registered_nodes[node_name].walkable == true + or minetest.registered_nodes[node_name].walkable == nil + then + return true + end + return false +end + +local function spears_shot(itemstack, player) local spear = itemstack:get_name() .. '_entity' + + if spear == "nssm:spear_of_peace_entity" then + speed = 32 + gravity = 9.8 + else + speed = 16 + gravity = 9.8 + end + local drag = .3 + local playerpos = player:getpos() local obj = minetest.add_entity({x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, spear) local dir = player:get_look_dir() - if spear == "nssm:spear_of_peace_entity" then - sp = 32 - gravity = 9.8 - else - sp = 16 - gravity = 9.8 - end - local dr = .3 - obj:setvelocity({x=dir.x*sp, y=dir.y*sp, z=dir.z*sp}) - obj:setacceleration({x=-dir.x*dr, y=-gravity, z=-dir.z*dr}) + + obj:setvelocity({x=dir.x*speed, y=dir.y*speed, z=dir.z*speed}) + obj:setacceleration({x=-dir.x*drag, y=-gravity, z=-dir.z*drag}) obj:setyaw(player:get_look_yaw()+math.pi) minetest.sound_play("spears_sound", {pos=playerpos}) obj:get_luaentity().wear = itemstack:get_wear() + obj:get_luaentity().shooter = player return true end -function spears_set_entity(kind, eq, toughness) - local SPEAR_ENTITY={ +local function spears_set_entity(kind, eq, toughness, breadth) + local spearname = "nssm:spear_"..kind + local spearentityname = spearname.."_entity" + local maxwear = 65535 + local weardown = maxwear/toughness + + breadth = breadth or 1 + + local SPEAR_ENTITY = { physical = false, - timer=0, + timer = 0, visual = "wielditem", visual_size = {x=0.15, y=0.1}, - textures = {"nssm:spear_" .. kind}, - lastpos={}, + textures = {spearname}, + lastpos = {}, collisionbox = {0,0,0,0,0,0}, + on_punch = function(self, puncher) + -- pick up item if puncher then if puncher:is_player() then - local stack = {name='nssm:spear_' .. kind, wear=self.wear+65535/toughness} + local stack = {name=spearname, wear=self.wear} local inv = puncher:get_inventory() if inv:room_for_item("main", stack) then inv:add_item("main", stack) @@ -44,63 +71,89 @@ function spears_set_entity(kind, eq, toughness) } SPEAR_ENTITY.on_step = function(self, dtime) - self.timer=self.timer+dtime + self.timer = self.timer+dtime + local pos = self.object:getpos() local node = minetest.get_node(pos) + if not self.wear then self.object:remove() return end - if self.lastpos.x~=nil then - if node.name ~= "air" and not (string.find(node.name, 'grass') and not string.find(node.name, 'dirt')) and not string.find(node.name, 'flowers:') and not string.find(node.name, 'farming:') then + + -- pos exists --> entity has moved at least once + if self.lastpos.x then + if node.name ~= "air" -- not air, walkable + and is_walkable(node.name) + then + self.object:remove() - if self.wear+65535/toughness < 65535 then - minetest.add_item(self.lastpos, {name='nssm:spear_' .. kind, wear=self.wear+65535/toughness}) + local halfweardown = weardown/2 + if self.wear+halfweardown < maxwear then + minetest.add_item(self.lastpos, {name=spearname, wear=self.wear+halfweardown}) end - elseif self.timer>0.2 then - local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1) + + -- air or non-walkable + else + local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1.5*breadth) + local add_at for k, obj in pairs(objs) do if obj:get_luaentity() ~= nil then - if obj:get_luaentity().name ~= "nssm:spear_" .. kind .. "_entity" and obj:get_luaentity().name ~= "__builtin:item" then - local speed = vector.length(self.object:getvelocity()) - local damage = (speed + eq)^1.12-20 - obj:punch(self.object, 1.0, { - full_punch_interval=1.0, - damage_groups={fleshy=damage}, - }, nil) - self.object:remove() - if self.wear+65535/toughness < 65535 then - minetest.add_item(self.lastpos, {name='nssm:spear_' .. kind, wear=self.wear+65535/toughness}) + if obj:get_luaentity().name ~= spearentityname and obj:get_luaentity().name ~= "__builtin:item" then + if not (obj:is_player() and obj:get_luaentity().shooter:get_player_name() == obj:get_player_name() ) then + local speed = vector.length(self.object:getvelocity()) + local damage = (speed + eq)^1.12-20 + + obj:punch(self.object, 1.0, { + full_punch_interval=1.0, + damage_groups={fleshy=damage}, + }, nil) + + self.object:remove() + + -- Wear down for each mob hit + if self.wear+weardown < maxwear then + self.wear = self.wear+weardown + add_at = {pos = self.lastpos, def={name=spearname, wear=self.wear}} + end end end end end + + if add_at then + minetest.add_item(add_at.pos, add_at.def) + end end end + self.lastpos={x=pos.x, y=pos.y, z=pos.z} - end + end -- entity step definition + + return SPEAR_ENTITY end --Tools -function spears_register_spear(kind, desc, eq, toughness, material) +function spears_register_spear(kind, desc, eq, toughness, material, scale) + scale = scale or 1 minetest.register_tool("nssm:spear_" .. kind, { description = desc .. " Spear", - wield_image = "spear_" .. kind .. ".png", + wield_image = "spear_" .. kind .. ".png", inventory_image = "spear_" .. kind .. ".png^[transform4", - wield_scale= {x=2,y=1,z=1}, + wield_scale= {x=2*scale, y=1*scale, z=1*scale}, on_drop = function(itemstack, user, pointed_thing) spears_shot(itemstack, user) - if not minetest.setting_getbool("creative_mode") then + if not creative_mode then itemstack:take_item() end return itemstack end, on_place = function(itemstack, user, pointed_thing) minetest.add_item(pointed_thing.above, itemstack) - if not minetest.setting_getbool("creative_mode") then + if not creative_mode then itemstack:take_item() end return itemstack @@ -115,7 +168,7 @@ function spears_register_spear(kind, desc, eq, toughness, material) } }) - local SPEAR_ENTITY=spears_set_entity(kind, eq, toughness) + local SPEAR_ENTITY=spears_set_entity(kind, eq, toughness, scale) minetest.register_entity("nssm:spear_" .. kind .. "_entity", SPEAR_ENTITY) @@ -149,107 +202,4 @@ spears_register_spear('duck_beak', 'Duck Beak', 5, 6, 'nssm:duck_beak') spears_register_spear('felucco_horn', 'Felucco Horn', 7, 9, 'nssm:felucco_horn') - ---Spear of peace -minetest.register_tool("nssm:spear_of_peace", { - description = "Spear of Peace", - wield_image = "spear_of_peace.png", - inventory_image = "spear_of_peace.png^[transform4", - wield_scale= {x=4,y=2,z=2}, - on_drop = function(itemstack, user, pointed_thing) - spears_shot(itemstack, user) - if not minetest.setting_getbool("creative_mode") then - itemstack:take_item() - end - return itemstack - end, - on_place = function(itemstack, user, pointed_thing) - minetest.add_item(pointed_thing.above, itemstack) - if not minetest.setting_getbool("creative_mode") then - itemstack:take_item() - end - return itemstack - end, - tool_capabilities = { - full_punch_interval = 0.7, - max_drop_level=1, - groupcaps={ - snappy = {times={[3]=0.2, [2]=0.2, [1]=0.2}, uses=500, maxlevel=1}, - }, - damage_groups = {fleshy=18}, - } -}) - -function spears_set_sentity(kind, eq, toughness) - local SUPERSPEAR_ENTITY={ - physical = false, - timer=0, - visual = "wielditem", - visual_size = {x=0.15, y=0.1}, - textures = {"nssm:spear_" .. kind}, - lastpos={}, - collisionbox = {0,0,0,0,0,0}, - on_punch = function(self, puncher) - if puncher then - if puncher:is_player() then - local stack = {name='nssm:spear_' .. kind, wear=self.wear+65535/toughness} - local inv = puncher:get_inventory() - if inv:room_for_item("main", stack) then - inv:add_item("main", stack) - self.object:remove() - end - end - end - end, - } - - SUPERSPEAR_ENTITY.on_step = function(self, dtime) - self.timer=self.timer+dtime - local pos = self.object:getpos() - local node = minetest.get_node(pos) - if not self.wear then - self.object:remove() - return - end - if self.lastpos.x~=nil then - if node.name ~= "air" and not (string.find(node.name, 'grass') and not string.find(node.name, 'dirt')) and not string.find(node.name, 'flowers:') and not string.find(node.name, 'farming:') then - self.object:remove() - if self.wear+65535/toughness < 65535 then - minetest.add_item(self.lastpos, {name='nssm:spear_' .. kind, wear=self.wear+65535/toughness}) - end - elseif self.timer>0.2 then - local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1) - for k, obj in pairs(objs) do - if obj:get_luaentity() ~= nil then - if obj:get_luaentity().name ~= "nssm:spear_" .. kind .. "_entity" and obj:get_luaentity().name ~= "__builtin:item" then - local speed = vector.length(self.object:getvelocity()) - --minetest.chat_send_all(speed) - local damage = (speed + eq)^1.12-20 - obj:punch(self.object, 1.0, { - full_punch_interval=1.0, - damage_groups={fleshy=damage}, - }, nil) - self.object:remove() - if self.wear+65535/toughness < 65535 then - minetest.add_item(self.lastpos, {name='nssm:spear_' .. kind, wear=self.wear+65535/toughness}) - end - end - end - end - end - end - self.lastpos={x=pos.x, y=pos.y, z=pos.z} - end - return SUPERSPEAR_ENTITY -end - -SUPERSPEAR_ENTITY=spears_set_sentity("of_peace", 30, 300) - -minetest.register_entity("nssm:spear_of_peace_entity", SUPERSPEAR_ENTITY) - - minetest.register_craft({ - output = 'nssm:spear_of_peace', - recipe = { - {'nssm:wrathful_moranga', 'group:wood', 'group:wood'}, - } -}) +spears_register_spear('of_peace', 'Grand Peace', 30, 300, 'nssm:wrathful_moranga', 2)