initial commit

master
stub 2017-09-27 18:08:49 +03:00
commit 5fcb2bd3e8
95 changed files with 1748 additions and 0 deletions

11
README.md Normal file
View File

@ -0,0 +1,11 @@
## Throwing mod reloaded
#### This is a mirror of throwing mod for minetest by Echoes91, which was further improved by MinetestForFun team.
* Being an excellent ranged weapons mod for minetest already, it was further improved by MinetestForFun team, enabling PvP-damage, mob anger towards the attacker, resolved many bugs and optimized the code. It's fully suited and ready for survival and pvp gameplay. Since MinetestForFun didn't have separate repo for this mod (it only exists as a part of their server modpack), I decided to fork it (so it would be easily accesible for git clone) and make some changes to have less dependencies.
* Changes: I restored original, low-res textures by Echoes91, changed parameters of bows to shoot further and removed some items to not depend on some mods (minotaur horn bow and mithril arrows).
#### Credits
All copyright belongs to MinetestForFun team, Echoes91, PilzAdam and Jeija.
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)

117
build_arrow.lua Executable file
View File

@ -0,0 +1,117 @@
minetest.register_craftitem("throwing:arrow_build", {
description = "Build Arrow",
inventory_image = "throwing_arrow_build.png",
})
minetest.register_node("throwing:arrow_build_box", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-- Shaft
{-6.5/17, -1.5/17, -1.5/17, 6.5/17, 1.5/17, 1.5/17},
--Spitze
{-4.5/17, 2.5/17, 2.5/17, -3.5/17, -2.5/17, -2.5/17},
{-8.5/17, 0.5/17, 0.5/17, -6.5/17, -0.5/17, -0.5/17},
--Federn
{6.5/17, 1.5/17, 1.5/17, 7.5/17, 2.5/17, 2.5/17},
{7.5/17, -2.5/17, 2.5/17, 6.5/17, -1.5/17, 1.5/17},
{7.5/17, 2.5/17, -2.5/17, 6.5/17, 1.5/17, -1.5/17},
{6.5/17, -1.5/17, -1.5/17, 7.5/17, -2.5/17, -2.5/17},
{7.5/17, 2.5/17, 2.5/17, 8.5/17, 3.5/17, 3.5/17},
{8.5/17, -3.5/17, 3.5/17, 7.5/17, -2.5/17, 2.5/17},
{8.5/17, 3.5/17, -3.5/17, 7.5/17, 2.5/17, -2.5/17},
{7.5/17, -2.5/17, -2.5/17, 8.5/17, -3.5/17, -3.5/17},
}
},
tiles = {"throwing_arrow_build.png", "throwing_arrow_build.png", "throwing_arrow_build_back.png", "throwing_arrow_build_front.png", "throwing_arrow_build_2.png", "throwing_arrow_build.png"},
groups = {not_in_creative_inventory=1},
})
local THROWING_ARROW_ENTITY={
physical = false,
timer=0,
visual = "wielditem",
visual_size = {x=0.1, y=0.1},
textures = {"throwing:arrow_build_box"},
lastpos={},
collisionbox = {0,0,0,0,0,0},
node = "",
player = "",
inventory = false,
stack = false,
bow_damage = 0,
}
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
self.timer=self.timer+dtime
local newpos = self.object:getpos()
if self.lastpos.x ~= nil then
for _, pos in pairs(throwing_get_trajectoire(self, newpos)) do
local node = minetest.get_node(pos)
local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1)
for k, obj in pairs(objs) do
if throwing_is_player(self.player, obj) or throwing_is_entity(obj) then
if self.inventory and self.stack and not minetest.setting_getbool("creative_mode") then
self.inventory:remove_item("main", {name=self.stack:get_name()})
end
if self.stack then
minetest.add_item(pos, {name=self.stack:get_name()})
end
local toughness = 0.95
if math.random() < toughness then
minetest.add_item(pos, 'throwing:arrow_build')
else
minetest.add_item(pos, 'default:stick')
end
self.object:remove()
return
end
end
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 node.name ~= "ignore" and self.inventory and self.stack then
if not minetest.is_protected(self.lastpos, "")
and not string.find(node.name, "lava")
and not string.find(node.name, "torch")
and self.stack:get_definition().type == "node"
and self.stack:get_name() ~= "default:torch" then
minetest.place_node(self.lastpos, {name=self.stack:get_name()})
else
minetest.add_item(self.lastpos, {name=self.stack:get_name()})
end
if not minetest.setting_getbool("creative_mode") then
self.inventory:remove_item("main", {name=self.stack:get_name()})
end
end
minetest.add_item(self.lastpos, 'default:shovel_steel')
self.object:remove()
return
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
minetest.register_entity("throwing:arrow_build_entity", THROWING_ARROW_ENTITY)
minetest.register_craft({
output = 'throwing:arrow_build',
recipe = {
{'default:stick', 'default:stick', 'default:shovel_steel'},
}
})
minetest.register_craft({
output = 'throwing:arrow_build',
recipe = {
{'default:shovel_steel', 'default:stick', 'default:stick'},
}
})

25
defaults.lua Executable file
View File

@ -0,0 +1,25 @@
DISABLE_WOODEN_BOW = false
DISABLE_LONGBOW = false
DISABLE_COMPOSITE_BOW = false
DISABLE_STEEL_BOW = false
DISABLE_ROYAL_BOW = false
DISABLE_CROSSBOW = false
DISABLE_ARBALEST = false
DISABLE_AUTOMATED_ARBALEST = false
DISABLE_TELEPORT_ARROW = true
DISABLE_DIG_ARROW = true
DISABLE_BUILD_ARROW = true
DISABLE_TNT_ARROW = true
DISABLE_FIRE_ARROW = true
DISABLE_TORCH_ARROW = false
DISABLE_SHELL_ARROW = false
DISABLE_FIREWORKS_BLUE_ARROW = false
DISABLE_FIREWORKS_RED_ARROW = false
DISABLE_STONE_ARROW = false
DISABLE_STEEL_ARROW = false
DISABLE_DIAMOND_ARROW = false
DISABLE_OBSIDIAN_ARROW = false

6
depends.txt Executable file
View File

@ -0,0 +1,6 @@
default
farming
dye
bucket?
fire?
tnt?

1
description.txt Executable file
View File

@ -0,0 +1 @@
This mod adds many bows and arrows to Minetest.

109
dig_arrow.lua Executable file
View File

@ -0,0 +1,109 @@
minetest.register_craftitem("throwing:arrow_dig", {
description = "Dig Arrow",
inventory_image = "throwing_arrow_dig.png",
})
minetest.register_node("throwing:arrow_dig_box", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-- Shaft
{-6.5/17, -1.5/17, -1.5/17, 6.5/17, 1.5/17, 1.5/17},
--Spitze
{-4.5/17, 2.5/17, 2.5/17, -3.5/17, -2.5/17, -2.5/17},
{-8.5/17, 0.5/17, 0.5/17, -6.5/17, -0.5/17, -0.5/17},
--Federn
{6.5/17, 1.5/17, 1.5/17, 7.5/17, 2.5/17, 2.5/17},
{7.5/17, -2.5/17, 2.5/17, 6.5/17, -1.5/17, 1.5/17},
{7.5/17, 2.5/17, -2.5/17, 6.5/17, 1.5/17, -1.5/17},
{6.5/17, -1.5/17, -1.5/17, 7.5/17, -2.5/17, -2.5/17},
{7.5/17, 2.5/17, 2.5/17, 8.5/17, 3.5/17, 3.5/17},
{8.5/17, -3.5/17, 3.5/17, 7.5/17, -2.5/17, 2.5/17},
{8.5/17, 3.5/17, -3.5/17, 7.5/17, 2.5/17, -2.5/17},
{7.5/17, -2.5/17, -2.5/17, 8.5/17, -3.5/17, -3.5/17},
}
},
tiles = {"throwing_arrow_dig.png", "throwing_arrow_dig.png", "throwing_arrow_dig_back.png", "throwing_arrow_dig_front.png", "throwing_arrow_dig_2.png", "throwing_arrow_dig.png"},
groups = {not_in_creative_inventory=1},
})
local THROWING_ARROW_ENTITY={
physical = false,
timer=0,
visual = "wielditem",
visual_size = {x=0.1, y=0.1},
textures = {"throwing:arrow_dig_box"},
lastpos={},
collisionbox = {0,0,0,0,0,0},
player = "",
bow_damage = 0,
}
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
local newpos = self.object:getpos()
if self.lastpos.x ~= nil then
for _, pos in pairs(throwing_get_trajectoire(self, newpos)) do
local node = minetest.get_node(pos)
local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 1)
for k, obj in pairs(objs) do
if throwing_is_player(self.player, obj) or throwing_is_entity(obj) then
if throwing_touch(pos, obj:getpos()) 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 damage = 1.5
if self.bow_damage and self.bow_damage > 0 then
damage = damage + (self.bow_damage/12)
end
obj:punch(puncher, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=damage},
}, nil)
if math.random(0,100) % 2 == 0 then -- 50% of chance to drop //MFF (Mg|07/27/15)
minetest.add_item(pos, "throwing:arrow_dig")
end
self.object:remove()
return
end
end
end
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 node.name ~= "ignore" and minetest.get_item_group(node.name, "unbreakable") == 0
and not minetest.is_protected(pos, self.player)
and node.diggable ~= false then
minetest.set_node(pos, {name = "air"})
minetest.add_item(pos, node.name)
end
self.object:remove()
return
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
minetest.register_entity("throwing:arrow_dig_entity", THROWING_ARROW_ENTITY)
minetest.register_craft({
output = 'throwing:arrow_dig',
recipe = {
{'default:stick', 'default:stick', 'default:pick_steel'},
}
})
minetest.register_craft({
output = 'throwing:arrow_dig',
recipe = {
{'default:pick_steel', 'default:stick', 'default:stick'},
}
})

145
fire_arrow.lua Executable file
View File

@ -0,0 +1,145 @@
minetest.register_craftitem("throwing:arrow_fire", {
description = "Fire Arrow",
inventory_image = "throwing_arrow_fire.png",
})
minetest.register_node("throwing:arrow_fire_box", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-- Shaft
{-6.5/17, -1.5/17, -1.5/17, 6.5/17, 1.5/17, 1.5/17},
--Spitze
{-4.5/17, 2.5/17, 2.5/17, -3.5/17, -2.5/17, -2.5/17},
{-8.5/17, 0.5/17, 0.5/17, -6.5/17, -0.5/17, -0.5/17},
--Federn
{6.5/17, 1.5/17, 1.5/17, 7.5/17, 2.5/17, 2.5/17},
{7.5/17, -2.5/17, 2.5/17, 6.5/17, -1.5/17, 1.5/17},
{7.5/17, 2.5/17, -2.5/17, 6.5/17, 1.5/17, -1.5/17},
{6.5/17, -1.5/17, -1.5/17, 7.5/17, -2.5/17, -2.5/17},
{7.5/17, 2.5/17, 2.5/17, 8.5/17, 3.5/17, 3.5/17},
{8.5/17, -3.5/17, 3.5/17, 7.5/17, -2.5/17, 2.5/17},
{8.5/17, 3.5/17, -3.5/17, 7.5/17, 2.5/17, -2.5/17},
{7.5/17, -2.5/17, -2.5/17, 8.5/17, -3.5/17, -3.5/17},
}
},
tiles = {"throwing_arrow_fire.png", "throwing_arrow_fire.png", "throwing_arrow_fire_back.png", "throwing_arrow_fire_front.png", "throwing_arrow_fire_2.png", "throwing_arrow_fire.png"},
groups = {not_in_creative_inventory=1},
})
local THROWING_ARROW_ENTITY={
physical = false,
visual = "wielditem",
visual_size = {x=0.1, y=0.1},
textures = {"throwing:arrow_fire_box"},
lastpos={},
collisionbox = {0,0,0,0,0,0},
player = "",
bow_damage = 0,
}
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
local newpos = self.object:getpos()
if self.lastpos.x ~= nil then
for _, pos in pairs(throwing_get_trajectoire(self, newpos)) do
local node = minetest.get_node(pos)
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 throwing_is_player(self.player, obj) or throwing_is_entity(obj) then
if throwing_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 damage = 4
if self.bow_damage and self.bow_damage > 0 then
damage = damage + (self.bow_damage/12)
end
obj:punch(puncher, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=damage},
}, nil)
if math.random(0,100) % 2 == 0 then -- 50% of chance to drop //MFF (Mg|07/27/15)
minetest.add_item(pos, 'default:stick')
end
self.object:remove()
return
end
end
end
if node.name ~= "air"
and node.name ~= "throwing:light"
and node.name ~= "fire:basic_flame"
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 node.name ~= "ignore" then
minetest.set_node(self.lastpos, {name="fire:basic_flame"})
end
self.object:remove()
return
end
if minetest.get_node(pos).name == "air" then
minetest.set_node(pos, {name="throwing:light"})
end
if minetest.get_node(self.lastpos).name == "throwing:light" then
minetest.remove_node(self.lastpos)
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
minetest.register_entity("throwing:arrow_fire_entity", THROWING_ARROW_ENTITY)
minetest.register_node("throwing:light", {
drawtype = "airlike",
paramtype = "light",
sunlight_propagates = true,
tiles = {"throwing_empty.png"},
light_source = default.LIGHT_MAX-4,
selection_box = {
type = "fixed",
fixed = {
{0,0,0,0,0,0}
}
},
groups = {not_in_creative_inventory=1}
})
minetest.register_abm({
nodenames = {"throwing:light"},
interval = 10,
chance = 1,
action = function(pos, node)
minetest.remove_node(pos)
end
})
minetest.register_craft({
output = 'throwing:arrow_fire 4',
recipe = {
{'default:stick', 'default:stick', 'bucket:bucket_lava'},
},
replacements = {
{"bucket:bucket_lava", "bucket:bucket_empty"}
}
})
minetest.register_craft({
output = 'throwing:arrow_fire 4',
recipe = {
{'bucket:bucket_lava', 'default:stick', 'default:stick'},
},
replacements = {
{"bucket:bucket_lava", "bucket:bucket_empty"}
}
})

197
fireworks_arrows.lua Executable file
View File

@ -0,0 +1,197 @@
local function throwing_register_fireworks(color, desc)
minetest.register_craftitem("throwing:arrow_fireworks_" .. color, {
description = desc .. "fireworks arrow",
inventory_image = "throwing_arrow_fireworks_" .. color .. ".png",
})
minetest.register_node("throwing:arrow_fireworks_" .. color .. "_box", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-- Shaft
{-6.5/17, -1.5/17, -1.5/17, 6.5/17, 1.5/17, 1.5/17},
--Spitze
{-4.5/17, 2.5/17, 2.5/17, -3.5/17, -2.5/17, -2.5/17},
{-8.5/17, 0.5/17, 0.5/17, -6.5/17, -0.5/17, -0.5/17},
--Federn
{6.5/17, 1.5/17, 1.5/17, 7.5/17, 2.5/17, 2.5/17},
{7.5/17, -2.5/17, 2.5/17, 6.5/17, -1.5/17, 1.5/17},
{7.5/17, 2.5/17, -2.5/17, 6.5/17, 1.5/17, -1.5/17},
{6.5/17, -1.5/17, -1.5/17, 7.5/17, -2.5/17, -2.5/17},
{7.5/17, 2.5/17, 2.5/17, 8.5/17, 3.5/17, 3.5/17},
{8.5/17, -3.5/17, 3.5/17, 7.5/17, -2.5/17, 2.5/17},
{8.5/17, 3.5/17, -3.5/17, 7.5/17, 2.5/17, -2.5/17},
{7.5/17, -2.5/17, -2.5/17, 8.5/17, -3.5/17, -3.5/17},
}
},
tiles = {"throwing_arrow_fireworks_" .. color .. ".png", "throwing_arrow_fireworks_" .. color .. ".png", "throwing_arrow_fireworks_" .. color .. "_back.png", "throwing_arrow_fireworks_" .. color .. "_front.png", "throwing_arrow_fireworks_" .. color .. "_2.png", "throwing_arrow_fireworks_" .. color .. ".png"},
groups = {not_in_creative_inventory=1},
})
local THROWING_ARROW_ENTITY={
physical = false,
timer=0,
visual = "wielditem",
visual_size = {x=0.1, y=0.1},
textures = {"throwing:arrow_fireworks_" .. color .. "_box"},
lastpos={},
collisionbox = {0,0,0,0,0,0},
player = "",
bow_damage = 0,
}
local radius = 0.5
local function add_effects(pos, radius)
minetest.add_particlespawner({
amount = 256,
time = 0.2,
minpos = vector.subtract(pos, radius / 2),
maxpos = vector.add(pos, radius / 2),
minvel = {x=-5, y=-5, z=-5},
maxvel = {x=5, y=5, z=5},
minacc = {x=0, y=-8, z=0},
--~ maxacc = {x=-20, y=-50, z=-50},
minexptime = 2.5,
maxexptime = 3,
minsize = 1,
maxsize = 2.5,
texture = "throwing_sparkle_" .. color .. ".png",
})
end
local function boom(pos)
minetest.sound_play("throwing_firework_boom", {pos=pos, gain=1, max_hear_distance=2*64})
if minetest.get_node(pos).name == 'air' or minetest.get_node(pos).name == 'throwing:firework_trail' then
minetest.add_node(pos, {name="throwing:firework_boom"})
minetest.get_node_timer(pos):start(0.2)
end
add_effects(pos, radius)
end
-- Back to the arrow
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
self.timer=self.timer+dtime
local newpos = self.object:getpos()
if self.timer < 0.07 then
minetest.sound_play("throwing_firework_launch", {pos=newpos, gain=0.8, max_hear_distance=2*64})
end
minetest.add_particlespawner({
amount = 16,
time = 0.1,
minpos = newpos,
maxpos = newpos,
minvel = {x=-5, y=-5, z=-5},
maxvel = {x=5, y=5, z=5},
minacc = vector.new(),
maxacc = vector.new(),
minexptime = 0.3,
maxexptime = 0.5,
minsize = 0.5,
maxsize = 1,
texture = "throwing_sparkle.png",
})
if self.lastpos.x ~= nil then
for _, pos in pairs(throwing_get_trajectoire(self, newpos)) do
local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 2)
for k, obj in pairs(objs) do
if throwing_is_player(self.player, obj) or throwing_is_entity(obj) then
local damage = 2
if self.bow_damage and self.bow_damage > 0 then
damage = damage + (self.bow_damage/12)
end
obj:punch(self.object, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=damage},
}, nil)
boom(pos)
self.object:remove()
return
end
end
end
local node = minetest.get_node(newpos)
if self.timer > 2 or node.name ~= "air" and node.name ~= "throwing:firework_trail" then
boom(self.lastpos)
self.object:remove()
return
end
if node.name == 'air' then
minetest.add_node(newpos, {name="throwing:firework_trail"})
minetest.get_node_timer(newpos):start(0.1)
end
end
self.lastpos={x=newpos.x, y=newpos.y, z=newpos.z}
end
minetest.register_entity("throwing:arrow_fireworks_" .. color .. "_entity", THROWING_ARROW_ENTITY)
minetest.register_craft({
output = 'throwing:arrow_fireworks_' .. color .. ' 8',
recipe = {
{'default:stick', 'tnt:gunpowder', 'dye:' .. color},
}
})
minetest.register_craft({
output = 'throwing:arrow_fireworks_' .. color .. ' 8',
recipe = {
{'dye:' .. color, 'tnt:gunpowder', 'default:stick'},
}
})
end
--~ Arrows
if not DISABLE_FIREWORKS_BLUE_ARROW then
throwing_register_fireworks('blue', 'Blue')
end
if not DISABLE_FIREWORKS_RED_ARROW then
throwing_register_fireworks('red', 'Red')
end
--~ Nodes
minetest.register_node("throwing:firework_trail", {
drawtype = "airlike",
light_source = 9,
walkable = false,
drop = "",
groups = {dig_immediate=3},
on_timer = function(pos, elapsed)
minetest.remove_node(pos)
end,
})
minetest.register_node("throwing:firework_boom", {
drawtype = "plantlike",
tiles = {"throwing_sparkle.png"},
light_source = default.LIGHT_MAX,
walkable = false,
drop = "",
groups = {dig_immediate=3},
on_timer = function(pos, elapsed)
minetest.remove_node(pos)
end,
after_destruct = function(pos, oldnode)
minetest.set_node(pos, {name="throwing:firework_light"})
minetest.get_node_timer(pos):start(3)
end,
})
minetest.register_node("throwing:firework_light", {
drawtype = "airlike",
light_source = default.LIGHT_MAX,
walkable = false,
drop = "",
groups = {dig_immediate=3},
on_timer = function(pos, elapsed)
minetest.remove_node(pos)
end,
})

191
functions.lua Executable file
View File

@ -0,0 +1,191 @@
--~
--~ Shot and reload system
--~
local players = {}
minetest.register_on_joinplayer(function(player)
local playerName = player:get_player_name()
players[playerName] = {
reloading=false,
}
end)
minetest.register_on_leaveplayer(function(player)
local playerName = player:get_player_name()
players[playerName] = nil
end)
function throwing_is_player(name, obj)
return (obj:is_player() and obj:get_player_name() ~= name)
end
function throwing_is_entity(obj)
return (obj:get_luaentity() ~= nil
and not string.find(obj:get_luaentity().name, "throwing:")
and obj:get_luaentity().name ~= "__builtin:item"
and obj:get_luaentity().name ~= "gauges:hp_bar"
and obj:get_luaentity().name ~= "signs:text")
end
function throwing_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 throwing_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 < 1 and rx > -1) and (rz < 1 and rz > -1) then
return true
end
return false
end
function throwing_shoot_arrow (itemstack, player, stiffness, is_cross)
if not player then return end
local arrow = itemstack:get_metadata()
itemstack:set_metadata("")
player:set_wielded_item(itemstack)
local playerpos = player:getpos()
local obj = minetest.add_entity({x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, arrow)
if not obj then return end
local dir = player:get_look_dir()
obj:setvelocity({x=dir.x*stiffness, y=dir.y*stiffness, z=dir.z*stiffness})
obj:setacceleration({x=dir.x*-3, y=-10, z=dir.z*-3})
obj:setyaw(player:get_look_yaw()+math.pi)
if is_cross then
minetest.sound_play("throwing_crossbow_sound", {pos=playerpos})
else
minetest.sound_play("throwing_bow_sound", {pos=playerpos})
end
if obj:get_luaentity() then
obj:get_luaentity().player = player:get_player_name()
obj:get_luaentity().inventory = player:get_inventory()
obj:get_luaentity().stack = player:get_inventory():get_stack("main", player:get_wield_index()-1)
obj:get_luaentity().lastpos = {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}
obj:get_luaentity().bow_damage = stiffness
end
return true
end
function throwing_unload (itemstack, player, unloaded, wear)
if itemstack:get_metadata() then
for _,arrow in ipairs(throwing_arrows) do
if itemstack:get_metadata() == arrow[2] then
if not minetest.setting_getbool("creative_mode") then
player:get_inventory():add_item("main", arrow[1])
end
break
end
end
end
if wear >= 65535 then
player:set_wielded_item({})
else
player:set_wielded_item({name=unloaded, wear=wear})
end
end
function throwing_reload (itemstack, player, pos, is_cross, loaded)
local playerName = player:get_player_name()
players[playerName]['reloading'] = false
if itemstack:get_name() == player:get_wielded_item():get_name() then
if (pos.x == player:getpos().x and pos.y == player:getpos().y and pos.z == player:getpos().z) or not is_cross then
local wear = itemstack:get_wear()
for _,arrow in ipairs(throwing_arrows) do
if player:get_inventory():get_stack("main", player:get_wield_index()+1):get_name() == arrow[1] then
if not minetest.setting_getbool("creative_mode") then
player:get_inventory():remove_item("main", arrow[1])
end
local meta = arrow[2]
player:set_wielded_item({name=loaded, wear=wear, metadata=meta})
break
end
end
end
end
end
-- Bows and crossbows
function throwing_register_bow (name, desc, scale, stiffness, reload_time, toughness, is_cross, craft)
minetest.register_tool("throwing:" .. name, {
description = desc,
inventory_image = "throwing_" .. name .. ".png",
wield_scale = scale,
stack_max = 1,
on_use = function(itemstack, user, pointed_thing)
local pos = user:getpos()
local playerName = user:get_player_name()
if not players[playerName]['reloading'] then
players[playerName]['reloading'] = true
minetest.after(reload_time, throwing_reload, itemstack, user, pos, is_cross, "throwing:" .. name .. "_loaded")
end
return itemstack
end,
})
minetest.register_tool("throwing:" .. name .. "_loaded", {
description = desc,
inventory_image = "throwing_" .. name .. "_loaded.png",
wield_scale = scale,
stack_max = 1,
on_use = function(itemstack, user, pointed_thing)
local wear = itemstack:get_wear()
if not minetest.setting_getbool("creative_mode") then
wear = wear + (65535/toughness)
end
local unloaded = "throwing:" .. name
throwing_shoot_arrow(itemstack, user, stiffness, is_cross)
minetest.after(0, throwing_unload, itemstack, user, unloaded, wear)
return itemstack
end,
on_drop = function(itemstack, dropper, pointed_thing)
local wear = itemstack:get_wear()
local unloaded = "throwing:" .. name
minetest.after(0, throwing_unload, itemstack, dropper, unloaded, wear)
end,
groups = {not_in_creative_inventory=1},
})
minetest.register_craft({
output = 'throwing:' .. name,
recipe = craft
})
local craft_width = 1
-- Since # isn't stable especially when there are nils in the table, count by hand
for _,v in ipairs(craft) do
for i,__ in ipairs(v) do
if i > craft_width then
craft_width = i
end
end
end
local rev_craft = {}
for i,y in ipairs(craft) do
rev_craft[i] = {}
for j,x in ipairs(y) do
rev_craft[i][craft_width-j+1] = x
end
end
minetest.register_craft({
output = 'throwing:' .. name,
recipe = rev_craft
})
end

67
init.lua Executable file
View File

@ -0,0 +1,67 @@
throwing_arrows = {
{"throwing:arrow_steel", "throwing:arrow_steel_entity"},
{"throwing:arrow_stone", "throwing:arrow_stone_entity"},
{"throwing:arrow_obsidian", "throwing:arrow_obsidian_entity"},
{"throwing:arrow_diamond", "throwing:arrow_diamond_entity"},
{"throwing:arrow_fire", "throwing:arrow_fire_entity"},
{"throwing:arrow_teleport", "throwing:arrow_teleport_entity"},
{"throwing:arrow_dig", "throwing:arrow_dig_entity"},
{"throwing:arrow_build", "throwing:arrow_build_entity"},
{"throwing:arrow_tnt", "throwing:arrow_tnt_entity"},
{"throwing:arrow_torch", "throwing:arrow_torch_entity"},
{"throwing:arrow_shell", "throwing:arrow_shell_entity"},
{"throwing:arrow_fireworks_blue", "throwing:arrow_fireworks_blue_entity"},
{"throwing:arrow_fireworks_red", "throwing:arrow_fireworks_red_entity"},
}
dofile(minetest.get_modpath("throwing").."/defaults.lua")
local input = io.open(minetest.get_modpath("throwing").."/throwing.conf", "r")
if input then
dofile(minetest.get_modpath("throwing").."/throwing.conf")
input:close()
input = nil
end
dofile(minetest.get_modpath("throwing").."/functions.lua")
dofile(minetest.get_modpath("throwing").."/tools.lua")
dofile(minetest.get_modpath("throwing").."/standard_arrows.lua")
if minetest.get_modpath('fire') and minetest.get_modpath('bucket') and not DISABLE_FIRE_ARROW then
dofile(minetest.get_modpath("throwing").."/fire_arrow.lua")
end
if not DISABLE_TELEPORT_ARROW then
dofile(minetest.get_modpath("throwing").."/teleport_arrow.lua")
end
if not DISABLE_DIG_ARROW then
dofile(minetest.get_modpath("throwing").."/dig_arrow.lua")
end
if not DISABLE_BUILD_ARROW then
dofile(minetest.get_modpath("throwing").."/build_arrow.lua")
end
if minetest.get_modpath('fire') and minetest.get_modpath('tnt') and not DISABLE_TNT_ARROW then
dofile(minetest.get_modpath("throwing").."/tnt_arrow.lua")
end
if not DISABLE_TORCH_ARROW then
dofile(minetest.get_modpath("throwing").."/torch_arrow.lua")
end
if minetest.get_modpath('tnt') and not DISABLE_SHELL_ARROW then
dofile(minetest.get_modpath("throwing").."/shell_arrow.lua")
end
if minetest.get_modpath('tnt') then
dofile(minetest.get_modpath("throwing").."/fireworks_arrows.lua")
end
if minetest.setting_get("log_mods") then
minetest.log("action", "throwing loaded")
end

126
shell_arrow.lua Executable file
View File

@ -0,0 +1,126 @@
minetest.register_craftitem("throwing:arrow_shell", {
description = "Shell arrow",
inventory_image = "throwing_arrow_shell.png",
})
minetest.register_node("throwing:arrow_shell_box", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-- Shaft
{-6.5/17, -1.5/17, -1.5/17, 6.5/17, 1.5/17, 1.5/17},
--Spitze
{-4.5/17, 2.5/17, 2.5/17, -3.5/17, -2.5/17, -2.5/17},
{-8.5/17, 0.5/17, 0.5/17, -6.5/17, -0.5/17, -0.5/17},
--Federn
{6.5/17, 1.5/17, 1.5/17, 7.5/17, 2.5/17, 2.5/17},
{7.5/17, -2.5/17, 2.5/17, 6.5/17, -1.5/17, 1.5/17},
{7.5/17, 2.5/17, -2.5/17, 6.5/17, 1.5/17, -1.5/17},
{6.5/17, -1.5/17, -1.5/17, 7.5/17, -2.5/17, -2.5/17},
{7.5/17, 2.5/17, 2.5/17, 8.5/17, 3.5/17, 3.5/17},
{8.5/17, -3.5/17, 3.5/17, 7.5/17, -2.5/17, 2.5/17},
{8.5/17, 3.5/17, -3.5/17, 7.5/17, 2.5/17, -2.5/17},
{7.5/17, -2.5/17, -2.5/17, 8.5/17, -3.5/17, -3.5/17},
}
},
tiles = {"throwing_arrow_shell.png", "throwing_arrow_shell.png", "throwing_arrow_shell_back.png", "throwing_arrow_shell_front.png", "throwing_arrow_shell_2.png", "throwing_arrow_shell.png"},
groups = {not_in_creative_inventory=1},
})
local THROWING_ARROW_ENTITY={
physical = false,
timer=0,
visual = "wielditem",
visual_size = {x=0.1, y=0.1},
textures = {"throwing:arrow_shell_box"},
lastpos={},
collisionbox = {0,0,0,0,0,0},
player = "",
bow_damage = 0,
}
local radius = 1
local function add_effects(pos, radius)
minetest.add_particlespawner({
amount = 8,
time = 0.5,
minpos = vector.subtract(pos, radius / 2),
maxpos = vector.add(pos, radius / 2),
minvel = {x=-10, y=-10, z=-10},
maxvel = {x=10, y=10, z=10},
minacc = vector.new(),
maxacc = vector.new(),
minexptime = 0.5,
maxexptime = 1,
minsize = 0.5,
maxsize = 1,
texture = "tnt_smoke.png",
})
end
local function boom(pos)
minetest.sound_play("shell_explode", {pos=pos, gain=1.5, max_hear_distance=2*64})
minetest.set_node(pos, {name="tnt:boom"})
minetest.get_node_timer(pos):start(0.1)
add_effects(pos, radius)
end
-- Back to the arrow
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
local newpos = self.object:getpos()
if self.lastpos.x ~= nil then
for _, pos in pairs(throwing_get_trajectoire(self, newpos)) do
local node = minetest.get_node(pos)
local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 2)
for k, obj in pairs(objs) do
if throwing_is_player(self.player, obj) or throwing_is_entity(obj) then
local speed = vector.length(self.object:getvelocity())
local damage = ((speed + 5)^1.2)/10 + 12
if self.bow_damage and self.bow_damage > 0 then
damage = damage + (self.bow_damage/12)
end
obj:punch(self.object, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=damage},
}, nil)
boom(pos)
self.object:remove()
return
end
end
if node.name ~= "air"
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
boom(self.lastpos)
self.object:remove()
return
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
minetest.register_entity("throwing:arrow_shell_entity", THROWING_ARROW_ENTITY)
minetest.register_craft({
output = 'throwing:arrow_shell 8',
recipe = {
{'default:stick', 'tnt:gunpowder', 'default:bronze_ingot'},
}
})
minetest.register_craft({
output = 'throwing:arrow_shell 8',
recipe = {
{'default:bronze_ingot', 'tnt:gunpowder', 'default:stick'},
}
})

BIN
sounds/throwing_bow_sound.ogg Executable file

Binary file not shown.

Binary file not shown.

BIN
sounds/throwing_firework_boom.ogg Executable file

Binary file not shown.

Binary file not shown.

BIN
sounds/throwing_shell_explode.ogg Executable file

Binary file not shown.

131
standard_arrows.lua Executable file
View File

@ -0,0 +1,131 @@
function throwing_register_arrow_standard (kind, desc, eq, toughness, craft)
minetest.register_craftitem("throwing:arrow_" .. kind, {
description = desc .. " arrow",
inventory_image = "throwing_arrow_" .. kind .. ".png",
})
minetest.register_node("throwing:arrow_" .. kind .. "_box", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-- Shaft
{-6.5/17, -1.5/17, -1.5/17, 6.5/17, 1.5/17, 1.5/17},
--Spitze
{-4.5/17, 2.5/17, 2.5/17, -3.5/17, -2.5/17, -2.5/17},
{-8.5/17, 0.5/17, 0.5/17, -6.5/17, -0.5/17, -0.5/17},
--Federn
{6.5/17, 1.5/17, 1.5/17, 7.5/17, 2.5/17, 2.5/17},
{7.5/17, -2.5/17, 2.5/17, 6.5/17, -1.5/17, 1.5/17},
{7.5/17, 2.5/17, -2.5/17, 6.5/17, 1.5/17, -1.5/17},
{6.5/17, -1.5/17, -1.5/17, 7.5/17, -2.5/17, -2.5/17},
{7.5/17, 2.5/17, 2.5/17, 8.5/17, 3.5/17, 3.5/17},
{8.5/17, -3.5/17, 3.5/17, 7.5/17, -2.5/17, 2.5/17},
{8.5/17, 3.5/17, -3.5/17, 7.5/17, 2.5/17, -2.5/17},
{7.5/17, -2.5/17, -2.5/17, 8.5/17, -3.5/17, -3.5/17},
}
},
tiles = {"throwing_arrow_" .. kind .. ".png", "throwing_arrow_" .. kind .. ".png", "throwing_arrow_" .. kind .. "_back.png", "throwing_arrow_" .. kind .. "_front.png",
"throwing_arrow_" .. kind .. "_2.png", "throwing_arrow_" .. kind .. ".png"},
groups = {not_in_creative_inventory=1},
})
local THROWING_ARROW_ENTITY={
physical = false,
visual = "wielditem",
visual_size = {x=0.1, y=0.1},
textures = {"throwing:arrow_" .. kind .. "_box"},
lastpos={},
collisionbox = {0,0,0,0,0,0},
player = "",
bow_damage = 0,
}
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
local newpos = self.object:getpos()
if self.lastpos.x ~= nil then
for _, pos in pairs(throwing_get_trajectoire(self, newpos)) do
local node = minetest.get_node(pos)
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 throwing_is_player(self.player, obj) or throwing_is_entity(obj) then
if throwing_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 damage = eq
if self.bow_damage and self.bow_damage > 0 then
damage = damage + (self.bow_damage/12)
end
obj:punch(puncher, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=damage},
}, nil)
if math.random() < toughness then
if math.random(0,100) % 2 == 0 then
minetest.add_item(self.lastpos, 'throwing:arrow_' .. kind)
end
else
minetest.add_item(self.lastpos, 'default:stick')
end
self.object:remove()
return
end
end
end
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 math.random() < toughness then
minetest.add_item(self.lastpos, 'throwing:arrow_' .. kind)
else
minetest.add_item(self.lastpos, 'default:stick')
end
self.object:remove()
return
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
minetest.register_entity("throwing:arrow_" .. kind .. "_entity", THROWING_ARROW_ENTITY)
minetest.register_craft({
output = 'throwing:arrow_' .. kind .. ' 16',
recipe = {
{'default:stick', 'default:stick', craft},
}
})
minetest.register_craft({
output = 'throwing:arrow_' .. kind .. ' 16',
recipe = {
{craft, 'default:stick', 'default:stick'},
}
})
end
if not DISABLE_STONE_ARROW then
throwing_register_arrow_standard ('stone', 'Stone', 4, 0.40, 'group:stone')
end
if not DISABLE_STEEL_ARROW then
throwing_register_arrow_standard ('steel', 'Steel', 5, 0.50, 'default:steel_ingot')
end
if not DISABLE_OBSIDIAN_ARROW then
throwing_register_arrow_standard ('obsidian', 'Obsidian', 6, 0.60, 'default:obsidian')
end
if not DISABLE_DIAMOND_ARROW then
throwing_register_arrow_standard ('diamond', 'Diamond', 7, 0.70, 'default:diamond')
end

96
teleport_arrow.lua Executable file
View File

@ -0,0 +1,96 @@
minetest.register_craftitem("throwing:arrow_teleport", {
description = "Teleport Arrow",
inventory_image = "throwing_arrow_teleport.png",
})
minetest.register_node("throwing:arrow_teleport_box", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-- Shaft
{-6.5/17, -1.5/17, -1.5/17, 6.5/17, 1.5/17, 1.5/17},
--Spitze
{-4.5/17, 2.5/17, 2.5/17, -3.5/17, -2.5/17, -2.5/17},
{-8.5/17, 0.5/17, 0.5/17, -6.5/17, -0.5/17, -0.5/17},
--Federn
{6.5/17, 1.5/17, 1.5/17, 7.5/17, 2.5/17, 2.5/17},
{7.5/17, -2.5/17, 2.5/17, 6.5/17, -1.5/17, 1.5/17},
{7.5/17, 2.5/17, -2.5/17, 6.5/17, 1.5/17, -1.5/17},
{6.5/17, -1.5/17, -1.5/17, 7.5/17, -2.5/17, -2.5/17},
{7.5/17, 2.5/17, 2.5/17, 8.5/17, 3.5/17, 3.5/17},
{8.5/17, -3.5/17, 3.5/17, 7.5/17, -2.5/17, 2.5/17},
{8.5/17, 3.5/17, -3.5/17, 7.5/17, 2.5/17, -2.5/17},
{7.5/17, -2.5/17, -2.5/17, 8.5/17, -3.5/17, -3.5/17},
}
},
tiles = {"throwing_arrow_teleport.png", "throwing_arrow_teleport.png", "throwing_arrow_teleport_back.png", "throwing_arrow_teleport_front.png", "throwing_arrow_teleport_2.png", "throwing_arrow_teleport.png"},
groups = {not_in_creative_inventory=1},
})
local THROWING_ARROW_ENTITY={
physical = false,
visual = "wielditem",
visual_size = {x=0.1, y=0.1},
textures = {"throwing:arrow_teleport_box"},
lastpos={},
collisionbox = {0,0,0,0,0,0},
player = "",
bow_damage = 0,
}
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
local newpos = self.object:getpos()
if self.lastpos.x ~= nil then
for _, pos in pairs(throwing_get_trajectoire(self, newpos)) do
local node = minetest.get_node(pos)
local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 2)
for k, obj in pairs(objs) do
if throwing_is_player(self.player, obj) or throwing_is_entity(obj) then
if self.player ~= "" then
local player = minetest.get_player_by_name(self.player)
if player then
player:setpos(self.lastpos)
end
end
self.object:remove()
return
end
end
if node.name ~= "air"
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.player ~= "" then
local player = minetest.get_player_by_name(self.player)
if player then
player:setpos(self.lastpos)
end
end
self.object:remove()
return
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
minetest.register_entity("throwing:arrow_teleport_entity", THROWING_ARROW_ENTITY)
minetest.register_craft({
output = 'throwing:arrow_teleport',
recipe = {
{'default:stick', 'default:stick', 'default:mese_crystal_fragment'}
}
})
minetest.register_craft({
output = 'throwing:arrow_teleport',
recipe = {
{'default:mese_crystal_fragment', 'default:stick', 'default:stick'}
}
})

4
textures/.directory Normal file
View File

@ -0,0 +1,4 @@
[Dolphin]
PreviewsShown=true
Timestamp=2017,9,27,1,19,11
Version=4

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

BIN
textures/throwing_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

33
throwing.conf Executable file
View File

@ -0,0 +1,33 @@
-- Bows
DISABLE_WOODEN_BOW = false
DISABLE_LONGBOW = false
DISABLE_COMPOSITE_BOW = false
DISABLE_STEEL_BOW = false
DISABLE_ROYAL_BOW = false
-- Crossbows
DISABLE_CROSSBOW = false
DISABLE_ARBALEST = false
DISABLE_AUTOMATED_ARBALEST = false
-- Special Arrows
DISABLE_TELEPORT_ARROW = false
DISABLE_DIG_ARROW = true -- Deactivated to prevent griefing
DISABLE_BUILD_ARROW = true -- Deactivated to prevent griefing
DISABLE_TNT_ARROW = true -- Deactivated to prevent griefing
DISABLE_FIRE_ARROW = true -- Deactivated to prevent griefing
DISABLE_TORCH_ARROW = false
DISABLE_SHELL_ARROW = true -- Deactivated until crash bug related to this arrow is resolved
-- Fireworks arrows
DISABLE_FIREWORKS_BLUE_ARROW = false
DISABLE_FIREWORKS_RED_ARROW = false
-- Normal arrows
DISABLE_STONE_ARROW = false
DISABLE_STEEL_ARROW = false
DISABLE_OBSIDIAN_ARROW = false
DISABLE_DIAMOND_ARROW = false
-- lesser damages to better damages

284
tnt_arrow.lua Executable file
View File

@ -0,0 +1,284 @@
minetest.register_craftitem("throwing:arrow_tnt", {
description = "TNT arrow",
inventory_image = "throwing_arrow_tnt.png",
})
minetest.register_node("throwing:arrow_tnt_box", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-- Shaft
{-6.5/17, -1.5/17, -1.5/17, 6.5/17, 1.5/17, 1.5/17},
--Spitze
{-4.5/17, 2.5/17, 2.5/17, -3.5/17, -2.5/17, -2.5/17},
{-8.5/17, 0.5/17, 0.5/17, -6.5/17, -0.5/17, -0.5/17},
--Federn
{6.5/17, 1.5/17, 1.5/17, 7.5/17, 2.5/17, 2.5/17},
{7.5/17, -2.5/17, 2.5/17, 6.5/17, -1.5/17, 1.5/17},
{7.5/17, 2.5/17, -2.5/17, 6.5/17, 1.5/17, -1.5/17},
{6.5/17, -1.5/17, -1.5/17, 7.5/17, -2.5/17, -2.5/17},
{7.5/17, 2.5/17, 2.5/17, 8.5/17, 3.5/17, 3.5/17},
{8.5/17, -3.5/17, 3.5/17, 7.5/17, -2.5/17, 2.5/17},
{8.5/17, 3.5/17, -3.5/17, 7.5/17, 2.5/17, -2.5/17},
{7.5/17, -2.5/17, -2.5/17, 8.5/17, -3.5/17, -3.5/17},
}
},
tiles = {"throwing_arrow_tnt.png", "throwing_arrow_tnt.png", "throwing_arrow_tnt_back.png", "throwing_arrow_tnt_front.png", "throwing_arrow_tnt_2.png", "throwing_arrow_tnt.png"},
groups = {not_in_creative_inventory=1},
})
local THROWING_ARROW_ENTITY={
physical = false,
timer=0,
visual = "wielditem",
visual_size = {x=0.1, y=0.1},
textures = {"throwing:arrow_tnt_box"},
lastpos={},
collisionbox = {0,0,0,0,0,0},
}
-- TNT functions copied, would be nice to directly call them through an API...
-- loss probabilities array (one in X will be lost)
local loss_prob = {}
loss_prob["default:cobble"] = 3
loss_prob["default:dirt"] = 4
local radius = tonumber(minetest.setting_get("tnt_radius") or 3)
-- Fill a list with data for content IDs, after all nodes are registered
local cid_data = {}
minetest.after(0, function()
for name, def in pairs(minetest.registered_nodes) do
cid_data[minetest.get_content_id(name)] = {
name = name,
drops = def.drops,
flammable = def.groups.flammable,
}
end
end)
local function rand_pos(center, pos, radius)
pos.x = center.x + math.random(-radius, radius)
pos.z = center.z + math.random(-radius, radius)
end
local function eject_drops(drops, pos, radius)
local drop_pos = vector.new(pos)
for _, item in pairs(drops) do
local count = item:get_count()
local max = item:get_stack_max()
if count > max then
item:set_count(max)
end
while count > 0 do
if count < max then
item:set_count(count)
end
rand_pos(pos, drop_pos, radius)
local obj = minetest.add_item(drop_pos, item)
if obj then
obj:get_luaentity().collect = true
obj:setacceleration({x=0, y=-10, z=0})
obj:setvelocity({x=math.random(-3, 3), y=10,
z=math.random(-3, 3)})
end
count = count - max
end
end
end
local function add_drop(drops, item)
item = ItemStack(item)
local name = item:get_name()
if loss_prob[name] ~= nil and math.random(1, loss_prob[name]) == 1 then
return
end
local drop = drops[name]
if drop == nil then
drops[name] = item
else
drop:set_count(drop:get_count() + item:get_count())
end
end
local fire_node = {name="fire:basic_flame"}
local function destroy(drops, pos, cid)
if minetest.is_protected(pos, "") then
return
end
local def = cid_data[cid]
if def and def.flammable then
minetest.set_node(pos, fire_node)
else
minetest.dig_node(pos)
if def then
local node_drops = minetest.get_node_drops(def.name, "")
for _, item in ipairs(node_drops) do
add_drop(drops, item)
end
end
end
end
local function calc_velocity(pos1, pos2, old_vel, power)
local vel = vector.direction(pos1, pos2)
vel = vector.normalize(vel)
vel = vector.multiply(vel, power)
-- Divide by distance
local dist = vector.distance(pos1, pos2)
dist = math.max(dist, 1)
vel = vector.divide(vel, dist)
-- Add old velocity
vel = vector.add(vel, old_vel)
return vel
end
local function entity_physics(pos, radius)
-- Make the damage radius larger than the destruction radius
radius = radius * 2
local objs = minetest.get_objects_inside_radius(pos, radius)
for _, obj in pairs(objs) do
local obj_pos = obj:getpos()
local obj_vel = obj:getvelocity()
local dist = math.max(1, vector.distance(pos, obj_pos))
if obj_vel ~= nil then
obj:setvelocity(calc_velocity(pos, obj_pos,
obj_vel, radius * 10))
end
local damage = (5 / dist) * radius
obj:set_hp(obj:get_hp() - damage)
end
end
local function add_effects(pos, radius)
minetest.add_particlespawner({
amount = 128,
time = 1,
minpos = vector.subtract(pos, radius / 2),
maxpos = vector.add(pos, radius / 2),
minvel = {x=-20, y=-20, z=-20},
maxvel = {x=20, y=20, z=20},
minacc = vector.new(),
maxacc = vector.new(),
minexptime = 1,
maxexptime = 3,
minsize = 8,
maxsize = 16,
texture = "tnt_smoke.png",
})
end
local function explode(pos, radius)
local pos = vector.round(pos)
local vm = VoxelManip()
local pr = PseudoRandom(os.time())
local p1 = vector.subtract(pos, radius)
local p2 = vector.add(pos, radius)
local minp, maxp = vm:read_from_map(p1, p2)
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
local data = vm:get_data()
local drops = {}
local p = {}
local c_air = minetest.get_content_id("air")
local c_tnt = minetest.get_content_id("tnt:tnt")
local c_tnt_burning = minetest.get_content_id("tnt:tnt_burning")
local c_gunpowder = minetest.get_content_id("tnt:gunpowder")
local c_gunpowder_burning = minetest.get_content_id("tnt:gunpowder_burning")
local c_boom = minetest.get_content_id("tnt:boom")
local c_fire = minetest.get_content_id("fire:basic_flame")
for z = -radius, radius do
for y = -radius, radius do
local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z)
for x = -radius, radius do
if (x * x) + (y * y) + (z * z) <=
(radius * radius) + pr:next(-radius, radius) then
local cid = data[vi]
p.x = pos.x + x
p.y = pos.y + y
p.z = pos.z + z
if cid == c_tnt or cid == c_gunpowder then
burn(p)
elseif cid ~= c_tnt_burning and
cid ~= c_gunpowder_burning and
cid ~= c_air and
cid ~= c_fire and
cid ~= c_boom then
destroy(drops, p, cid)
end
end
vi = vi + 1
end
end
end
return drops
end
local function boom(pos)
minetest.sound_play("tnt_explode", {pos=pos, gain=1.5, max_hear_distance=2*64})
minetest.set_node(pos, {name="tnt:boom"})
minetest.get_node_timer(pos):start(0.5)
local drops = explode(pos, radius)
entity_physics(pos, radius)
eject_drops(drops, pos, radius)
add_effects(pos, radius)
end
-- Back to the arrow
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
local newpos = self.object:getpos()
if self.lastpos.x ~= nil then
for _, pos in pairs(throwing_get_trajectoire(self, newpos)) do
local node = minetest.get_node(pos)
local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 2)
for k, obj in pairs(objs) do
if throwing_is_player(self.player, obj) or throwing_is_entity(obj) then
boom(pos)
self.object:remove()
return
end
end
if node.name ~= "air" then
boom(pos)
self.object:remove()
return
end
end
end
self.lastpos={x=pos.x, y=pos.y, z=pos.z}
end
minetest.register_entity("throwing:arrow_tnt_entity", THROWING_ARROW_ENTITY)
minetest.register_craft({
output = 'throwing:arrow_tnt',
recipe = {
{'default:stick', 'tnt:tnt', 'default:bronze_ingot'},
}
})
minetest.register_craft({
output = 'throwing:arrow_tnt',
recipe = {
{'default:bronze_ingot', 'tnt:tnt', 'default:stick'},
}
})

65
tools.lua Executable file
View File

@ -0,0 +1,65 @@
if not DISABLE_WOODEN_BOW then
throwing_register_bow ('bow_wood', 'Wooden bow', {x=1, y=1, z=0.5}, 15, 1.5, 50, false, {
{'', 'default:stick', ''},
{'farming:string', '', 'default:stick'},
{'', 'default:stick', ''},
})
end
if not DISABLE_LONGBOW then
throwing_register_bow ('longbow', 'Longbow', {x=1, y=2.5, z=0.5}, 20, 1.5, 100, false, {
{'farming:string', 'group:wood', ''},
{'farming:string', '', 'group:wood'},
{'farming:string', 'group:wood', ''},
})
end
if not DISABLE_COMPOSITE_BOW then
throwing_register_bow ('bow_composite', 'Composite bow', {x=1, y=1.4, z=0.5}, 25, 2, 150, false, {
{'farming:string', 'group:wood', ''},
{'farming:string', '', 'default:steel_ingot'},
{'farming:string', 'group:wood', ''},
})
end
if not DISABLE_STEEL_BOW then
throwing_register_bow ('bow_steel', 'Steel bow', {x=1, y=1.4, z=0.5}, 30, 2, 250, false, {
{'farming:string', 'default:steel_ingot', ''},
{'farming:string', '', 'default:steel_ingot'},
{'farming:string', 'default:steel_ingot', ''},
})
end
if not DISABLE_ROYAL_BOW then
throwing_register_bow ('bow_royal', 'Royal bow', {x=1, y=1.5, z=0.5}, 35, 1, 750, false, {
{'farming:string', 'group:wood', 'default:diamond'},
{'farming:string', '', 'default:gold_ingot'},
{'farming:string', 'group:wood', 'default:diamond'},
})
end
--function throwing_register_bow (name, desc, scale, stiffness, reload_time, toughness, is_cross, craft)
if not DISABLE_CROSSBOW then
throwing_register_bow ('crossbow', 'Crossbow', {x=1, y=1.3, z=0.5}, 40, 5, 80, true, {
{'group:wood', 'farming:string', ''},
{'default:steel_ingot', 'farming:string', 'group:wood'},
{'group:wood', 'farming:string', ''},
})
end
if not DISABLE_ARBALEST then
throwing_register_bow ('arbalest', 'Arbalest', {x=1, y=1.3, z=0.5}, 50, 5, 120, true, {
{'default:steel_ingot', 'farming:string', 'default:stick'},
{'default:steel_ingot', 'farming:string', 'default:steel_ingot'},
{'default:steel_ingot', 'farming:string', 'default:stick'},
})
end
if not DISABLE_AUTOMATED_ARBALEST then
throwing_register_bow ('arbalest_auto', 'Automated arbalest', {x=1, y=1.3, z=0.5}, 50, 1.5, 60, true, {
{'default:steel_ingot', 'farming:string', 'default:mese_crystal'},
{'default:steel_ingot', 'farming:string', 'default:steel_ingot'},
{'default:steel_ingot', 'farming:string', 'default:mese_crystal'},
})
end

140
torch_arrow.lua Executable file
View File

@ -0,0 +1,140 @@
minetest.register_craftitem("throwing:arrow_torch", {
description = "Torch Arrow",
inventory_image = "throwing_arrow_torch.png",
})
minetest.register_node("throwing:arrow_torch_box", {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
-- Shaft
{-6.5/17, -1.5/17, -1.5/17, 6.5/17, 1.5/17, 1.5/17},
--Spitze
{-4.5/17, 2.5/17, 2.5/17, -3.5/17, -2.5/17, -2.5/17},
{-8.5/17, 0.5/17, 0.5/17, -6.5/17, -0.5/17, -0.5/17},
--Federn
{6.5/17, 1.5/17, 1.5/17, 7.5/17, 2.5/17, 2.5/17},
{7.5/17, -2.5/17, 2.5/17, 6.5/17, -1.5/17, 1.5/17},
{7.5/17, 2.5/17, -2.5/17, 6.5/17, 1.5/17, -1.5/17},
{6.5/17, -1.5/17, -1.5/17, 7.5/17, -2.5/17, -2.5/17},
{7.5/17, 2.5/17, 2.5/17, 8.5/17, 3.5/17, 3.5/17},
{8.5/17, -3.5/17, 3.5/17, 7.5/17, -2.5/17, 2.5/17},
{8.5/17, 3.5/17, -3.5/17, 7.5/17, 2.5/17, -2.5/17},
{7.5/17, -2.5/17, -2.5/17, 8.5/17, -3.5/17, -3.5/17},
}
},
tiles = {"throwing_arrow_torch.png", "throwing_arrow_torch.png", "throwing_arrow_torch_back.png", "throwing_arrow_torch_front.png", "throwing_arrow_torch_2.png", "throwing_arrow_torch.png"},
groups = {not_in_creative_inventory=1},
})
local THROWING_ARROW_ENTITY={
physical = false,
visual = "wielditem",
visual_size = {x=0.1, y=0.1},
textures = {"throwing:arrow_torch_box"},
lastpos={},
collisionbox = {0,0,0,0,0,0},
node = "",
player = "",
bow_damage = 0,
}
THROWING_ARROW_ENTITY.on_step = function(self, dtime)
local newpos = self.object:getpos()
if self.lastpos.x~= nil then
for _, pos in pairs(throwing_get_trajectoire(self, newpos)) do
local node = minetest.get_node(pos)
local objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, 0.5)
for k, obj in pairs(objs) do
local objpos = obj:getpos()
if throwing_is_player(self.player, obj) or throwing_is_entity(obj) then
if throwing_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 damage = 0.5
if self.bow_damage and self.bow_damage > 0 then
damage = damage + (self.bow_damage/12)
end
obj:punch(puncher, 1.0, {
full_punch_interval=1.0,
damage_groups={fleshy=damage},
}, nil)
local toughness = 0.9
if math.random() < toughness then
if math.random(0,100) % 2 == 0 then -- 50% of chance to drop //MFF (Mg|07/27/15)
minetest.add_item(pos, 'throwing:arrow_torch')
end
else
minetest.add_item(pos, 'default:stick')
end
self.object:remove()
return
end
end
end
if node.name == 'air' then
minetest.add_node(pos, {name="throwing:torch_trail"})
minetest.get_node_timer(pos):start(0.1)
elseif node.name ~= "air"
and not string.find(node.name, "trail")
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
local player = minetest.get_player_by_name(self.player)
if not player then self.object:remove() return end
if node.name ~= "ignore" and not string.find(node.name, "water_") and not string.find(node.name, "lava")
and not string.find(node.name, "torch") and minetest.get_item_group(node.name, "unbreakable") == 0
and not minetest.is_protected(self.lastpos, self.player) and node.diggable ~= false then
local dir=vector.direction(self.lastpos, pos)
local wall=minetest.dir_to_wallmounted(dir)
minetest.add_node(self.lastpos, {name="default:torch", param2 = wall})
else
local toughness = 0.9
if math.random() < toughness then
minetest.add_item(self.lastpos, 'throwing:arrow_torch')
else
minetest.add_item(self.lastpos, 'default:stick')
end
end
self.object:remove()
return
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
minetest.register_entity("throwing:arrow_torch_entity", THROWING_ARROW_ENTITY)
minetest.register_craft({
output = 'throwing:arrow_torch 4',
recipe = {
{'default:stick', 'default:stick', 'group:coal'},
}
})
minetest.register_craft({
output = 'throwing:arrow_torch 4',
recipe = {
{'group:coal', 'default:stick', 'default:stick'},
}
})
minetest.register_node("throwing:torch_trail", {
drawtype = "airlike",
light_source = default.LIGHT_MAX-1,
walkable = false,
drop = "",
groups = {dig_immediate=3},
on_timer = function(pos, elapsed)
minetest.remove_node(pos)
end,
})