Merge remote-tracking branch 'upstream/master'

This commit is contained in:
bri cassa 2023-06-07 22:47:09 +02:00
commit 4514a8d0a1
9 changed files with 167 additions and 140 deletions

View File

@ -1,3 +1,12 @@
Version 2.4:
- Functions rewrite, fixed many vector/variable declarations and unknown node handling
- Added pigiron support
Version 2.3:
- Updated to Minetest 5.6.0 API
- Changed receipts to avoid being confused with arrows
- Various cleansing and fixes
Version 2.2: Version 2.2:
- "Hit detection" based on spearhead position - "Hit detection" based on spearhead position
- Spears go through buildable_to nodes (snow) - Spears go through buildable_to nodes (snow)

7
README
View File

@ -12,14 +12,17 @@ How to install:
http://wiki.minetest.com/wiki/Installing_Mods http://wiki.minetest.com/wiki/Installing_Mods
How to use the mod: How to use the mod:
Craft a spear with | stick | stick | (material) |, works also mirrored. Craft a spear with | | | (material) |
| | stick | |
| stick | | |,
works 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 (unrealistic) 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 (unrealistic) 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.
If you miss the target it's your fault, the spear is fine. If you miss the target it's your fault, the spear is fine.
You can grab a spear on the fly (or maybe wait until it falls?). You can grab a spear on the fly (or maybe wait until it falls?).
You can stick a spear into a block, but if you remove the block then the spear falls (obviously). You can stick a spear into a block, but if you remove the block then the spear falls (obviously).
This mod contains the word "spear" more than 100 times, if you want the exact number count them yourself. This mod contains the word "spear" more than 100 times, if you want the exact number you can count them.
If you feel clever, throw a spear right above you and look at it to see what happens. If you feel clever, throw a spear right above you and look at it to see what happens.
You can even throw a spear from above down to your foes, it's even easier to hit. You can even throw a spear from above down to your foes, it's even easier to hit.
Someone once reported to have hit its own foot but it takes practice to do that. Someone once reported to have hit its own foot but it takes practice to do that.

View File

@ -5,3 +5,12 @@ DISABLE_BRONZE_SPEAR = false
DISABLE_DIAMOND_SPEAR = false DISABLE_DIAMOND_SPEAR = false
DISABLE_OBSIDIAN_SPEAR = false DISABLE_OBSIDIAN_SPEAR = false
DISABLE_GOLD_SPEAR = false DISABLE_GOLD_SPEAR = false
DISABLE_IRON_SPEAR = false
SPEARS_THROW_SPEED = 13
SPEARS_V_ZERO = {x = 0, y = 0, z = 0}
SPEARS_DRAG_COEFF = 0.1
SPEARS_NODE_UNKNOWN = nil
SPEARS_NODE_THROUGH = 0
SPEARS_NODE_STICKY = 1
SPEARS_NODE_CRACKY = 2
SPEARS_NODE_CRACKY_LIMIT = 3

View File

@ -7,37 +7,40 @@ function spears_throw (itemstack, player, pointed_thing)
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 rotation = vector.new(0, yaw + math.pi/2, pitch + math.pi/6) local rotation = vector.new(0, yaw + math.pi/2, pitch + math.pi/6)
-- Plant into node local wear = itemstack:get_wear()
if pointed_thing.type == "node" then local pointed_a = pointed_thing.above
local node = minetest.get_node(pointed_thing.under) local pointed_b = pointed_thing.under
if minetest.registered_nodes[node.name].walkable and vector.distance(pointed_thing.above, throw_pos) < 1 then if pointed_thing.type == "node" and vector.distance(pointed_a, throw_pos) < 1 then -- Stick into node
local spear_object = minetest.add_entity(vector.divide(vector.add(vector.multiply(pointed_thing.above, 2), pointed_thing.under), 3), spear) local node = minetest.get_node(pointed_b)
local check_node = spears_check_node(node.name)
if check_node == SPEARS_NODE_UNKNOWN then
return false
elseif check_node == SPEARS_NODE_CRACKY then
minetest.sound_play("default_metal_footstep", {pos = pointed_a}, true)
return false
elseif check_node == SPEARS_NODE_STICKY then
local spear_object = minetest.add_entity(vector.divide(vector.add(vector.multiply(pointed_a, 2), pointed_b), 3), spear)
spear_object:set_rotation(rotation) spear_object:set_rotation(rotation)
spear_object:get_luaentity()._wear = itemstack:get_wear() spear_object:get_luaentity()._wear = wear
spear_object:get_luaentity()._stickpos = pointed_thing.under spear_object:get_luaentity()._stickpos = pointed_b
return minetest.sound_play("default_place_node", {pos = pointed_a}, true)
return false
end end
end else -- Avoid hitting yourself and throw
-- Avoid hitting yourself and throw local throw_speed = SPEARS_THROW_SPEED
local throw_speed = 12
while vector.distance(player_pos, throw_pos) < 1.2 do while vector.distance(player_pos, throw_pos) < 1.2 do
throw_pos = vector.add(throw_pos, vector.multiply(direction, 0.1)) throw_pos = vector.add(throw_pos, vector.multiply(direction, 0.1))
end end
local player_vel local player_vel = player:get_velocity()
if player.is_fake_player then
player_vel = {x=0,y=0,z=0}
else
player_vel = player:get_velocity()
end
local spear_object = minetest.add_entity(throw_pos, spear) local spear_object = minetest.add_entity(throw_pos, spear)
spear_object:set_velocity(vector.add(player_vel, vector.multiply(direction, throw_speed))) spear_object:set_velocity(vector.add(player_vel, vector.multiply(direction, throw_speed)))
spear_object:set_rotation(rotation) spear_object:set_rotation(rotation)
minetest.sound_play("spears_throw", {pos = player_pos}, true) minetest.sound_play("spears_throw", {pos = player_pos}, true)
spear_object:get_luaentity()._wear = itemstack:get_wear() spear_object:get_luaentity()._wear = wear
spear_object:get_luaentity().lastpos = throw_pos
spear_object:get_luaentity()._stickpos = nil spear_object:get_luaentity()._stickpos = nil
return true return true
end end
end
function spears_set_entity(spear_type, base_damage, toughness) function spears_set_entity(spear_type, base_damage, toughness)
local SPEAR_ENTITY={ local SPEAR_ENTITY={
@ -66,116 +69,98 @@ function spears_set_entity(spear_type, base_damage, toughness)
end, end,
on_step = function(self, dtime) on_step = function(self, dtime)
if not self._wear then local wear = self._wear
if wear == nil then
self.object:remove() self.object:remove()
return return false
end end
local pos = self.object:get_pos()
local velocity = self.object:get_velocity() local velocity = self.object:get_velocity()
local speed = vector.length(velocity) local speed = vector.length(velocity)
-- Spear is stuck ? if self._stickpos ~= nil then -- Spear is stuck
if self._stickpos then
local node = minetest.get_node(self._stickpos) local node = minetest.get_node(self._stickpos)
local node_cracky = minetest.registered_nodes[node.name].groups.cracky local check_node = spears_check_node(node.name)
local pos = self.object:get_pos() if check_node ~= SPEARS_NODE_STICKY then -- Fall when node is removed
if node_cracky and node_cracky < 3 then
minetest.sound_play("default_metal_footstep", {pos = pos}, true)
self.object:remove() self.object:remove()
minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = self._wear}) minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = wear})
elseif not self._node_walkable then return false
minetest.sound_play("default_place_node", {pos = self._stickpos}, true)
end
self._node_walkable = minetest.registered_nodes[node.name].walkable
if not node or not self._node_walkable then -- Fall when node is removed
self.object:remove()
minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = self._wear})
return
end end
else -- Spear is flying else -- Spear is flying
local newpos = self.object:get_pos()
for _, pos in pairs(spears_get_trajectoire(self, newpos)) do
local direction = vector.normalize(velocity) local direction = vector.normalize(velocity)
local yaw = minetest.dir_to_yaw(direction) local yaw = minetest.dir_to_yaw(direction)
local pitch = math.acos(velocity.y/speed) - math.pi/3 local pitch = math.acos(velocity.y/speed) - math.pi/3
local spearhead_pos = vector.add(pos, vector.multiply(direction, 0.5)) local spearhead_pos = vector.add(pos, vector.multiply(direction, 0.5))
local node = minetest.get_node(spearhead_pos)
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})
-- Hit someone? -- Hit someone?
local objects_in_radius = minetest.get_objects_inside_radius(spearhead_pos, 2.5) local objects_in_radius = minetest.get_objects_inside_radius(spearhead_pos, 0.6)
for _,object in ipairs(objects_in_radius) do for _,object in ipairs(objects_in_radius) do
if object:get_luaentity() ~= self and object:get_armor_groups().fleshy then if object:get_luaentity() ~= self and object:get_armor_groups().fleshy then
local objpos = object:get_pos()
local collisionbox = object:get_properties().collisionbox or {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
if spears_touch(spearhead_pos, objpos, collisionbox) then
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)
minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = self._wear + 65535/toughness}) wear = spears_wear(wear, toughness)
return minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = wear})
end return true
end end
end end
-- Hit a node? -- Hit a node?
if node and minetest.registered_nodes[node.name].walkable local node = minetest.get_node(spearhead_pos)
and not minetest.registered_nodes[node.name].buildable_to local check_node = spears_check_node(node.name)
and not (minetest.registered_nodes[node.name].groups.slab and spearhead_pos.y % 1 < 0.5) if check_node == SPEARS_NODE_UNKNOWN then
then -- Stick self.object:remove()
self.object:set_acceleration({x = 0, y = 0, z = 0}) minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = wear})
self.object:set_velocity({x = 0, y = 0, z = 0}) elseif check_node ~= SPEARS_NODE_THROUGH then
self._wear = self._wear + 65535/toughness wear = spears_wear(wear, toughness)
if self._wear >= 65535 then if wear >= 65535 then
minetest.sound_play("default_tool_breaks", {pos = pos}, true) minetest.sound_play("default_tool_breaks", {pos = pos}, true)
self.object:remove() self.object:remove()
return minetest.add_item(pos, {name='defaut:stick'})
end return false
elseif check_node == SPEARS_NODE_CRACKY then
minetest.sound_play("default_metal_footstep", {pos = pos}, true)
self.object:remove()
minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = wear})
return false
elseif check_node == SPEARS_NODE_STICKY then
self.object:set_acceleration(SPEARS_V_ZERO)
self.object:set_velocity(SPEARS_V_ZERO)
minetest.sound_play("default_place_node", {pos = pos}, true)
self._stickpos = spearhead_pos self._stickpos = spearhead_pos
self.lastpos = pos self._wear = wear
return end
else -- Get drag else -- Get drag
local drag = math.max(minetest.registered_nodes[node.name].liquid_viscosity, 0.1) local viscosity = minetest.registered_nodes[node.name].liquid_viscosity
local drag = math.max(viscosity, SPEARS_DRAG_COEFF)
local acceleration = vector.multiply(velocity, -drag) local acceleration = vector.multiply(velocity, -drag)
acceleration.y = acceleration.y - 10 * ((7 - drag) / 7) acceleration.y = acceleration.y - 10 * ((7 - drag) / 7)
self.object:set_acceleration(acceleration) self.object:set_acceleration(acceleration)
end end
end end
self.lastpos = newpos
end
end, end,
} }
return SPEAR_ENTITY return SPEAR_ENTITY
end end
function spears_check_node(node_name)
function spears_get_trajectoire(self, newpos) local node = minetest.registered_nodes[node_name]
if self.lastpos.x == nil then if node == nil then
return {newpos} return SPEARS_NODE_UNKNOWN
elseif node.groups.cracky ~= nil and node.groups.cracky < SPEARS_NODE_CRACKY_LIMIT then
return SPEARS_NODE_CRACKY
elseif node.walkable and not node.buildable then
return SPEARS_NODE_STICKY
else
return SPEARS_NODE_THROUGH
end end
local coord = {}
local dx = vector.distance({x=newpos["x"], y=0, z=0}, {x=self.lastpos["x"], y=0, z=0} )/2
local dy = vector.distance({x=0, y=newpos["y"], z=0}, {x=0, y=self.lastpos["y"], z=0} )/2
local dz = vector.distance({x=0, y=0, z=newpos["z"]}, {x=0, y=0, z=self.lastpos["z"]} )/2
if newpos["x"] < self.lastpos["x"] then
dx = -dx
end
if newpos["y"] < self.lastpos["y"] then
dy = -dy
end
if newpos["z"] < self.lastpos["z"] then
dz = -dz
end
table.insert(coord, {x=self.lastpos["x"]+dx, y=self.lastpos["y"]+dy ,z=self.lastpos["z"]+dz })
table.insert(coord, newpos)
return coord
end end
function spears_wear(initial_wear, toughness)
function spears_touch(pos, objpos, cbox) if not minetest.settings:get_bool("creative_mode") then
--colbox format {x1, y1, z1, x2, y2, z2} local wear = initial_wear + 65535/toughness
if (pos.x < objpos.x + math.max(cbox[1], cbox[4]) and pos.x > objpos.x + math.min(cbox[1], cbox[4])) return wear
and (pos.y < objpos.y + math.max(cbox[2], cbox[5]) and pos.y > objpos.y + math.min(cbox[2], cbox[5])) else
and (pos.z < objpos.z + math.max(cbox[3], cbox[6]) and pos.z > objpos.z + math.min(cbox[3], cbox[6])) then local wear = initial_wear
return true return wear
end end
return false
end end

View File

@ -11,5 +11,8 @@ dofile(minetest.get_modpath("spears").."/functions.lua")
dofile(minetest.get_modpath("spears").."/tools.lua") dofile(minetest.get_modpath("spears").."/tools.lua")
local log_mods = minetest.settings:get_bool("log_mods")
minetest.log("action", "[spears] loaded.") if minetest.settings:get_bool("log_mods") then
minetest.log("action", "[MOD] Spears loaded")
end

View File

@ -1,4 +1,6 @@
name = spears name = spears
title = Separs
description = Add spears to Minetest
depends = default depends = default
description = Add spears to Minetest, versatile weapons that can be thrown
author = Echoes91
title = Spears
min_minetest_version = 5.4

View File

@ -4,3 +4,5 @@ DISABLE_COPPER_SPEAR = true
DISABLE_BRONZE_SPEAR = true DISABLE_BRONZE_SPEAR = true
DISABLE_DIAMOND_SPEAR = true DISABLE_DIAMOND_SPEAR = true
DISABLE_OBSIDIAN_SPEAR = true DISABLE_OBSIDIAN_SPEAR = true
DISABLE_GOLD_SPEAR = true
SPEARS_THROW_SPEED = 13

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

View File

@ -48,18 +48,18 @@ 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 = {
{'', '', material}, {"", "", material},
{'', 'group:stick', ''}, {"", "group:stick", ""},
{'group:stick', '', ''}, {"group:stick", "", ""}
} }
}) })
minetest.register_craft({ minetest.register_craft({
output = 'spears:spear_' .. spear_type, output = 'spears:spear_' .. spear_type,
recipe = { recipe = {
{material, '', ''}, {material, "", ""},
{'', 'group:stick', ''}, {"", "group:stick", ""},
{'', '', 'group:stick'}, {"", "", "group:stick"}
} }
}) })
end end
@ -68,17 +68,31 @@ if not DISABLE_STONE_SPEAR then
spears_register_spear('stone', 'Stone', 4, 20, 'group:stone') spears_register_spear('stone', 'Stone', 4, 20, 'group:stone')
end end
if minetest.get_modpath("pigiron") then
if not DISABLE_IRON_SPEAR then
spears_register_spear('iron', 'Iron', 5.5, 30, 'pigiron:iron_ingot')
end
if not DISABLE_STEEL_SPEAR then
spears_register_spear('steel', 'Steel', 6, 35, 'default:steel_ingot')
end
if not DISABLE_COPPER_SPEAR then
spears_register_spear('copper', 'Copper', 4.8, 30, 'default:copper_ingot')
end
if not DISABLE_BRONZE_SPEAR then
spears_register_spear('bronze', 'Bronze', 5.5, 35, 'default:bronze_ingot')
end
else
if not DISABLE_STEEL_SPEAR then if not DISABLE_STEEL_SPEAR then
spears_register_spear('steel', 'Steel', 6, 30, 'default:steel_ingot') spears_register_spear('steel', 'Steel', 6, 30, 'default:steel_ingot')
end end
if not DISABLE_COPPER_SPEAR then if not DISABLE_COPPER_SPEAR then
spears_register_spear('copper', 'Copper', 5, 35, 'default:copper_ingot') spears_register_spear('copper', 'Copper', 5, 30, 'default:copper_ingot')
end end
if not DISABLE_BRONZE_SPEAR then if not DISABLE_BRONZE_SPEAR then
spears_register_spear('bronze', 'Bronze', 6, 35, 'default:bronze_ingot') spears_register_spear('bronze', 'Bronze', 6, 35, 'default:bronze_ingot')
end end
end
if not DISABLE_OBSIDIAN_SPEAR then if not DISABLE_OBSIDIAN_SPEAR then
spears_register_spear('obsidian', 'Obsidian', 8, 30, 'default:obsidian') spears_register_spear('obsidian', 'Obsidian', 8, 30, 'default:obsidian')