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()._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 return true
end end
@ -42,37 +59,52 @@ 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)
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 yaw = minetest.dir_to_yaw(velocity)
local pitch = math.acos(velocity.y/speed) - math.pi/3 local pitch = math.acos(velocity.y/speed) - math.pi/3
local pos = vector.add(self.object:get_pos(), vector.multiply(velocity, dtime)) local pos = vector.add(self.object:get_pos(), vector.multiply(velocity, dtime))
local node = minetest.get_node(pos) 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
self.object:remove()
return
end
else
self.object:set_rotation({x = 0, y = yaw + math.pi/2, z = pitch}) self.object:set_rotation({x = 0, y = yaw + math.pi/2, z = pitch})
local objects_in_radius = minetest.get_objects_inside_radius(pos, 1) -- Hit someone?
local objects_in_radius = minetest.get_objects_inside_radius(pos, 0.5)
for _,object in ipairs(objects_in_radius) do 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 if object:get_luaentity() ~= self and object:get_armor_groups().fleshy then
local direction = vector.normalize(velocity)
local damage = (speed + base_damage)^1.15 - 20 local damage = (speed + base_damage)^1.15 - 20
object:punch(self.object, 1.0, {full_punch_interval = 1.0, damage_groups = {fleshy=damage},}, direction) 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.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}) minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = self._wear + 65535/toughness})
return
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