1
0
mirror of https://gitlab.com/echoes91/spears.git synced 2025-06-28 21:56:02 +02:00

1 Commits
2.1 ... master

Author SHA1 Message Date
7694b95d08 Version MFF. 2018-09-08 16:41:47 +02:00
18 changed files with 182 additions and 219 deletions

48
README.txt Normal file → Executable file
View File

@ -1,53 +1,13 @@
=== SPEARS for MINETEST by Echoes91 ===
=== SPEARS for MINETEST ===
This mod adds spears to Minetest.
How to download:
If you have this file, you already know
Forum topic:
https://forum.minetest.net/viewtopic.php?f=11&t=13367
This mod adds spears to Minetest. It aims at improving the ones introduced within throwing enhanced.
How to install:
http://wiki.minetest.com/wiki/Installing_Mods
How to use the mod:
Craft a spear with | stick | stick | (material) |, 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 used to fight, but are slower and weaker than swords.
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.
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).
This mod contains the word "spear" more than 100 times, if you want the exact number count them yourself.
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.
Someone once reported to have hit its own foot but it takes practice to do that.
CHANGELOG
2.1:
- Spears ding hard blocks (cracky < 3)
- Fixed stick-into-node position to avoid spears turning black (#2467)
- Player velocity added to throw (it's physics baby)
2.0:
- Cleaner, streamlined code without deprecated functions
- Spears hurt players
- Spears animated in flight
- Spears stick into nodes
- New textures
- New sound when hitting flesh
- New receipt to fit with default tools
- Drag depends on fluid
- Improved instructions
- New gold-plated spear to celebrate
1.1:
- Make use of new on_secondary_use API, requires Minetest 5.2.0
Spear work similarly to other tools such as swords, even if being a little slower. Moreover, a spear can be thrown using the drop key ('Q') or placed on a node using the place key ('right click'); they have also limited digging capabilities.
License:
Sourcecode: LGPLv2.1 (see http://www.gnu.org/licenses/lgpl-2.1.html)
Grahpics & sounds: CC-BY 3.0 (see http://creativecommons.org/licenses/by/3.0/legalcode)
Grahpics & sounds: CC-BY 3.0 (see http://creativecommons.org/licenses/by/3.0/legalcode)

3
defaults.lua Normal file → Executable file
View File

@ -1,6 +1,5 @@
DISABLE_STONE_SPEAR = false
DISABLE_STEEL_SPEAR = false
DISABLE_COPPER_SPEAR = false
DISABLE_BRONZE_SPEAR = false
DISABLE_DIAMOND_SPEAR = false
DISABLE_OBSIDIAN_SPEAR = false
DISABLE_MITHRIL_SPEAR = false

0
depends.txt Normal file → Executable file
View File

256
functions.lua Normal file → Executable file
View File

@ -1,133 +1,151 @@
function spears_throw (itemstack, player, pointed_thing)
function spears_shot (itemstack, player)
local spear = itemstack:get_name() .. '_entity'
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 rotation = vector.new(0, yaw + math.pi/2, pitch + math.pi/6)
-- Plant 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.divide(vector.add(vector.multiply(pointed_thing.above, 2), pointed_thing.under), 3), spear)
spear_object:set_rotation(rotation)
spear_object:get_luaentity()._wear = itemstack:get_wear()
spear_object:get_luaentity()._stickpos = pointed_thing.under
return
end
end
-- Avoid hitting yourself and throw
local throw_speed = 12
while vector.distance(player_pos, throw_pos) < 1.2 do
throw_pos = vector.add(throw_pos, vector.multiply(direction,0.1))
end
local player_vel = player:get_player_velocity()
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_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
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()
local sp = 14
local dr = .3
local gravity = 9.8
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:setyaw(player:get_look_yaw()+math.pi)
obj:get_luaentity().wear = itemstack:get_wear()
obj:get_luaentity().player = player:get_player_name()
obj:get_luaentity().lastpos = {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}
minetest.sound_play("spears_sound", {pos=playerpos})
return true
end
function spears_set_entity(spear_type, base_damage, toughness)
function spears_set_entity(kind, eq, toughness)
local SPEAR_ENTITY={
initial_properties = {
physical = false,
visual = "item",
visual_size = {x = 0.3, y = 0.3, z = 0.3},
wield_item = "spears:spear_" .. spear_type,
collisionbox = {-0.3, -0.3, -0.3, 0.3, 0.3, 0.3},
},
physical = false,
visual = "wielditem",
visual_size = {x=0.15, y=0.1},
textures = {"spears:spear_" .. kind},
lastpos={},
collisionbox = {0,0,0,0,0,0},
player = "",
wear = 0,
on_activate = function (self, staticdata, dtime_s)
self.object:set_armor_groups({immortal = 1})
end,
on_punch = function (self, puncher)
if puncher:is_player() then -- Grab the spear
local stack = {name='spears:spear_' .. spear_type, wear = self._wear}
local inv = puncher:get_inventory()
if inv:room_for_item("main", stack) then
inv:add_item("main", stack)
self.object:remove()
end
end
end,
on_step = function(self, dtime)
if not self._wear then
self.object:remove()
return
end
local velocity = self.object:get_velocity()
local speed = vector.length(velocity)
-- Spear is stuck ?
if self._stickpos and not self._sticknode then
local node = minetest.get_node(self._stickpos)
local stick_cracky = minetest.registered_nodes[node.name].groups.cracky
if stick_cracky and stick_cracky < 3 then
minetest.sound_play("default_metal_footstep", {pos = pos}, true)
self.object:remove()
minetest.add_item(self.object:get_pos(), {name='spears:spear_' .. spear_type, wear = self._wear})
elseif not self._stick_walkable then
minetest.sound_play("default_place_node", {pos = throw_pos}, true)
end
self._stick_walkable = minetest.registered_nodes[node.name].walkable
if not node or not self._stick_walkable then -- Fall when node is removed
self.object:remove()
minetest.add_item(self.object:get_pos(), {name='spears:spear_' .. spear_type, wear = self._wear})
return
end
else -- Spear is flying
local direction = vector.normalize(velocity)
local yaw = minetest.dir_to_yaw(direction)
local pitch = math.acos(velocity.y/speed) - math.pi/3
local pos = self.object:get_pos()
local next_pos = vector.add(pos, vector.multiply(velocity, dtime))
local node = minetest.get_node(next_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(next_pos, 0.6)
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)
on_punch = function(self, puncher)
if puncher then
if puncher:is_player() then
local stack = {name='spears: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()
minetest.sound_play("spears_hit", {pos = pos}, true)
minetest.add_item(pos, {name='spears:spear_' .. spear_type, wear = self._wear + 65535/toughness})
return
end
end
-- Hit a node?
if node then
if minetest.registered_nodes[node.name].walkable then -- Stick
self.object:set_acceleration({x = 0, y = 0, z = 0})
self.object:set_velocity({x = 0, y = 0, z = 0})
-- Correct position if went too deep to aboid disappearing or turning black
while minetest.registered_nodes[minetest.get_node(pos).name].walkable do
pos = vector.add(pos, vector.multiply(direction, - 0.002))
end
self.object:set_pos(pos)
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 = next_pos
else -- Get drag
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)
self.object:set_acceleration(acceleration)
end
end
end
end,
}
SPEAR_ENTITY.on_step = function(self, dtime)
local pos = self.object:getpos()
local node = minetest.get_node(pos)
if not self.wear then
self.object:remove()
return
end
local newpos = self.object:getpos()
if self.lastpos.x ~= nil then
for _, pos in pairs(spears_get_trajectoire(self, newpos)) do
local node = minetest.get_node(pos)
if node.name ~= "air"
and not string.find(node.name, 'water_')
and not (string.find(node.name, 'grass') and not string.find(node.name, 'dirt'))
and not (string.find(node.name, 'farming:') and not string.find(node.name, 'soil'))
and not string.find(node.name, 'flowers:')
and not string.find(node.name, 'fire:') then
if self.wear+65535/toughness < 65535 then
local spear_item = minetest.add_item(self.lastpos, {name='spears:spear_' .. kind, wear=self.wear+65535/toughness})
if spear_item then
spear_item:get_luaentity().item_drop_min_tstamp = minetest.get_us_time() + 3000000
end
end
self.object:remove()
return
end
local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 2)
for k, obj in pairs(objs) do
local objpos = obj:getpos()
if spears_is_player(self.player, obj) or spears_is_entity(obj) then
if spears_touch(pos, objpos) then
local puncher = self.object
if self.player and minetest.get_player_by_name(self.player) then
puncher = minetest.get_player_by_name(self.player)
end
--local speed = vector.length(self.object:getvelocity()) --MFF crabman(28/09/2015) damage valeur equal eq
local damage = eq --((speed + eq +5)^1.2)/10 --MFF crabman(28/09/2015) damage valeur equal eq
obj:punch(puncher, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=damage},
}, nil)
if self.wear+65535/toughness < 65535 then
local spear_item = minetest.add_item(self.lastpos, {name='spears:spear_' .. kind, wear=self.wear+65535/toughness})
if spear_item then
spear_item:get_luaentity().item_drop_min_tstamp = minetest.get_us_time() + 3000000
end
end
self.object:remove()
return
end
end
end
self.lastpos={x=pos.x, y=pos.y, z=pos.z}
end
end
self.lastpos={x=newpos.x, y=newpos.y, z=newpos.z}
end
return SPEAR_ENTITY
end
function spears_is_player(name, obj)
return (obj:is_player() and obj:get_player_name() ~= name)
end
function spears_is_entity(obj)
return (obj:get_luaentity() ~= nil
and not string.find(obj:get_luaentity().name, "spears:")
and obj:get_luaentity().name ~= "__builtin:item"
and obj:get_luaentity().name ~= "gauges:hp_bar"
and obj:get_luaentity().name ~= "signs:text")
end
function spears_get_trajectoire(self, newpos)
if self.lastpos.x == nil then
return {newpos}
end
local coord = {}
local nx = (newpos["x"] - self.lastpos["x"])/3
local ny = (newpos["y"] - self.lastpos["y"])/3
local nz = (newpos["z"] - self.lastpos["z"])/3
if nx and ny and nz then
table.insert(coord, {x=self.lastpos["x"]+nx, y=self.lastpos["y"]+ny ,z=self.lastpos["z"]+nz })
table.insert(coord, {x=newpos["x"]-nx, y=newpos["y"]-ny ,z=newpos["z"]-nz })
end
table.insert(coord, newpos)
return coord
end
function spears_touch(pos, objpos)
local rx = pos.x - objpos.x
local ry = pos.y - (objpos.y+1)
local rz = pos.z - objpos.z
if (ry < 1 and ry > -1) and (rx < 0.4 and rx > -0.4) and (rz < 0.4 and rz > -0.4) then
return true
end
return false
end

8
init.lua Normal file → Executable file
View File

@ -15,3 +15,11 @@ dofile(minetest.get_modpath("spears").."/tools.lua")
if minetest.setting_get("log_mods") then
minetest.log("action", "spears loaded")
end
--alias
minetest.register_alias("throwing:spear_stone", "spears:spear_stone")
minetest.register_alias("throwing:spear_steel", "spears:spear_steel")
minetest.register_alias("throwing:spear_diamond", "spears:spear_diamond")
minetest.register_alias("throwing:spear_obsidian", "spears:spear_obsidian")
minetest.register_alias("throwing:spear_mithril", "spears:spear_mithril")

Binary file not shown.

BIN
sounds/spears_sound.ogg Executable file

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +0,0 @@
DISABLE_STONE_SPEAR = true
DISABLE_STEEL_SPEAR = true
DISABLE_COPPER_SPEAR = true
DISABLE_BRONZE_SPEAR = true
DISABLE_DIAMOND_SPEAR = true
DISABLE_OBSIDIAN_SPEAR = true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 B

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 B

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 B

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

After

Width:  |  Height:  |  Size: 192 B

80
tools.lua Normal file → Executable file
View File

@ -1,19 +1,11 @@
function spears_register_spear(spear_type, desc, base_damage, toughness, material)
function spears_register_spear(kind, desc, eq, toughness, material)
minetest.register_tool("spears:spear_" .. spear_type, {
minetest.register_tool("spears:spear_" .. kind, {
description = desc .. " spear",
wield_image = "spears_spear_" .. spear_type .. ".png^[transform4",
inventory_image = "spears_spear_" .. spear_type .. ".png",
wield_scale= {x = 1.5, y = 1.5, z = 1.5},
on_secondary_use = function(itemstack, user, pointed_thing)
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_throw(itemstack, user, pointed_thing)
inventory_image = "spears_spear_" .. kind .. ".png",
wield_scale= {x=2,y=1,z=1},
on_drop = function(itemstack, user, pointed_thing)
spears_shot(itemstack, user)
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
@ -25,55 +17,47 @@ function spears_register_spear(spear_type, desc, base_damage, toughness, materia
groupcaps={
cracky = {times={[3]=2}, uses=toughness, maxlevel=1},
},
damage_groups = {fleshy=base_damage},
},
sound = {breaks = "default_tool_breaks"},
groups = {flammable = 1}
})
local SPEAR_ENTITY = spears_set_entity(spear_type, base_damage, toughness)
minetest.register_entity("spears:spear_" .. spear_type .. "_entity", SPEAR_ENTITY)
minetest.register_craft({
output = 'spears:spear_' .. spear_type,
recipe = {
{'group:stick', 'group:stick', material},
damage_groups = {fleshy=eq},
}
})
local SPEAR_ENTITY=spears_set_entity(kind, eq, toughness)
minetest.register_entity("spears:spear_" .. kind .. "_entity", SPEAR_ENTITY)
minetest.register_craft({
output = 'spears:spear_' .. spear_type,
output = 'spears:spear_' .. kind,
recipe = {
{material, 'group:stick', 'group:stick'},
{'group:wood', 'group:wood', material},
}
})
minetest.register_craft({
output = 'spears:spear_' .. kind,
recipe = {
{material, 'group:wood', 'group:wood'},
}
})
end
if not DISABLE_STONE_SPEAR then
spears_register_spear('stone', 'Stone', 4, 20, 'group:stone')
spears_register_spear('stone', 'Stone (Hunter)', 3, 25, 'group:stone') --MFF crabman(28/09/2015) damage and wear
end
if not DISABLE_STEEL_SPEAR then
spears_register_spear('steel', 'Steel', 6, 30, 'default:steel_ingot')
end
if not DISABLE_COPPER_SPEAR then
spears_register_spear('copper', 'Copper', 5, 35, 'default:copper_ingot')
end
if not DISABLE_BRONZE_SPEAR then
spears_register_spear('bronze', 'Bronze', 6, 35, 'default:bronze_ingot')
end
if not DISABLE_OBSIDIAN_SPEAR then
spears_register_spear('obsidian', 'Obsidian', 8, 30, 'default:obsidian')
spears_register_spear('steel', 'Steel (Hunter)', 4, 30, 'default:steel_ingot') --MFF crabman(28/09/2015) damage and wear
end
if not DISABLE_DIAMOND_SPEAR then
spears_register_spear('diamond', 'Diamond', 8, 40, 'default:diamond')
spears_register_spear('diamond', 'Diamond (Hunter)', 7, 50, 'default:diamond') --MFF crabman(28/09/2015) damage and wear
end
if not DISABLE_GOLD_SPEAR then
spears_register_spear('gold', 'Golden', 5, 40, 'default:gold_ingot')
if not DISABLE_OBSIDIAN_SPEAR then
spears_register_spear('obsidian', 'Obsidian (Hunter)', 5, 40, 'default:obsidian') --MFF crabman(28/09/2015) damage and wear
end
if not DISABLE_MITHRIL_SPEAR then
spears_register_spear('mithril', 'Mithril (Hunter)', 8, 200, 'default:mithril_ingot') --MFF crabman(28/09/2015) damage and wear
end