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:
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:

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 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,
}

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",
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