Sticking great into nodes

This commit is contained in:
echoes91 2020-04-19 18:50:54 +02:00
parent bb6c36d7e5
commit 119116b89e
3 changed files with 90 additions and 41 deletions

View File

@ -7,9 +7,26 @@ http://wiki.minetest.com/wiki/Installing_Mods
How to use the mod: How to use the mod:
Craft a spear with | stick | stick | (material) |, also mirrored. 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 fight, but are slower and weaker than swords.
Spears can be used to dig, but are slower and weaker and pickaxes. 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: License:

View File

@ -1,18 +1,35 @@
function spears_shot (itemstack, player) function spears_throw (itemstack, player, pointed_thing)
local spear = itemstack:get_name() .. '_entity' local spear = itemstack:get_name() .. '_entity'
local playerpos = player:getpos() local player_pos = player:get_pos()
local spear_object = minetest.add_entity({x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, spear) 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 direction = player:get_look_dir()
local throw_pos = vector.add(head_pos, vector.multiply(direction,0.5))
local pitch = player:get_look_vertical() local pitch = player:get_look_vertical()
local yaw = player:get_look_horizontal() local yaw = player:get_look_horizontal()
local throw_speed = 15 local throw_speed = 15
local drag = 0.3 local rotation = vector.new(0, yaw + math.pi/2, pitch + math.pi/6)
local gravity = 9.8 -- Stick into node
spear_object:set_velocity({x = direction.x*throw_speed, y = direction.y*throw_speed, z = direction.z*throw_speed}) if pointed_thing.type == "node" then
spear_object:set_acceleration({x = -direction.x*drag, y = -gravity, z = -direction.z*drag}) local node = minetest.get_node(pointed_thing.under)
spear_object:set_rotation({x = 0, y = yaw + math.pi/2, z = pitch + math.pi/6}) if minetest.registered_nodes[node.name].walkable and vector.distance(pointed_thing.above, throw_pos) < 1 then
minetest.sound_play("spears_throw", {pos = playerpos}, true) 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()._wear = itemstack:get_wear()
spear_object:get_luaentity()._stickpos = nil
return true return true
end end
@ -42,39 +59,54 @@ function spears_set_entity(spear_type, base_damage, toughness)
self.object:remove() self.object:remove()
return return
end end
local acceleration = self.object:get_acceleration()
local velocity = self.object:get_velocity() local velocity = self.object:get_velocity()
local speed = vector.length(velocity) local speed = vector.length(velocity)
local yaw = minetest.dir_to_yaw(velocity) if self._stickpos then
local pitch = math.acos(velocity.y/speed) - math.pi/3 local node = minetest.get_node(self._stickpos)
local pos = vector.add(self.object:get_pos(), vector.multiply(velocity, dtime)) if not node or not minetest.registered_nodes[node.name].walkable then
local node = minetest.get_node(pos) self.object:remove()
if speed > 0 then minetest.add_item(self.object:get_pos(), {name='spears:spear_' .. spear_type, wear = self._wear})
if node.name ~= "air" and minetest.get_item_group(node.name, 'attached_node') < 1 then return
self.object:set_acceleration({x = 0, y = 0, z = 0}) end
self.object:set_velocity({x = 0, y = 0, z = 0}) else
minetest.sound_play("default_place_node.2", {pos = pos}, true) local direction = vector.normalize(velocity)
self._wear = self._wear + 65535/toughness local yaw = minetest.dir_to_yaw(velocity)
if self._wear >= 65535 then 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() 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 return
end 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 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
end, end,
} }

View File

@ -6,14 +6,14 @@ function spears_register_spear(spear_type, desc, base_damage, toughness, materia
inventory_image = "spears_spear_" .. spear_type .. ".png^[transform4", inventory_image = "spears_spear_" .. spear_type .. ".png^[transform4",
wield_scale= {x=2,y=1,z=1}, wield_scale= {x=2,y=1,z=1},
on_secondary_use = function(itemstack, user, pointed_thing) 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 if not minetest.setting_getbool("creative_mode") then
itemstack:take_item() itemstack:take_item()
end end
return itemstack return itemstack
end, end,
on_place = function(itemstack, user, pointed_thing) 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 if not minetest.setting_getbool("creative_mode") then
itemstack:take_item() itemstack:take_item()
end end
@ -38,14 +38,14 @@ function spears_register_spear(spear_type, desc, base_damage, toughness, materia
minetest.register_craft({ minetest.register_craft({
output = 'spears:spear_' .. spear_type, output = 'spears:spear_' .. spear_type,
recipe = { recipe = {
{'group:wood', 'group:wood', material}, {'group:stick', 'group:stick', material},
} }
}) })
minetest.register_craft({ minetest.register_craft({
output = 'spears:spear_' .. spear_type, output = 'spears:spear_' .. spear_type,
recipe = { recipe = {
{material, 'group:wood', 'group:wood'}, {material, 'group:stick', 'group:stick'},
} }
}) })
end end