Updated bows.

master
Nathan Salapat 2020-10-17 12:07:25 -05:00
parent af65b70ae2
commit 09bcf64dfd
27 changed files with 513 additions and 17 deletions

49
mods/bows/api.txt Normal file
View File

@ -0,0 +1,49 @@
Here is an example of how to register a bow:
bows.register_bow("bow_wood",{
description = "Wooden bow",
texture = "bows_bow.png",
texture_loaded = "bows_bow_loaded.png",
uses = 50, -- How many time you can use a bow to shoot
level = 1, -- Higher levels mean faster arrows
-- Crafting recipe to make bow, can be left nil
craft = {
{"", "group:stick", "farming:string"},
{"group:stick", "", "farming:string"},
{"", "group:stick", "farming:string"}
},
})
Here is an example of how to register an arrow:
bows.register_arrow("arrow_steel",{
description = "Steel arrow",
-- Arrow texture, the ^[colorize section changes the default arrows colour
texture = "bows_arrow_wood.png^[colorize:#FFFFFFcc",
damage = 8, -- How many 1/2 hearts damage it can do
craft_count = 4, -- How many arrows are made from recipe below
craft = {
{"default:steel_ingot", "group:stick", bows.feather}
},
-- Special function when an entity or mob is hit
on_hit_object = function(self, target, hp, user, lastpos)
if target:get_luaentity().name == "mob_horse:horse" then
print ("--- aww da horsey!!! " .. hp .. " damage points!")
end
end,
-- Special function when arrow hits a node
on_hit_node = function(self, pos, user, arrow_pos)
if self.node.name == "default:glass" then
minetest.sound_play("default_break_glass", {
pos = pos, gain = 1.0, max_hear_distance = 10})
minetest.remove_node(pos)
minetest.add_item(pos, "vessels:glass_fragments")
end
end,
})

157
mods/bows/arrow.lua Normal file
View File

@ -0,0 +1,157 @@
-- Localise functions
local floor, min, max = math.floor, math.min, math.max
--Should we use new collisionbox detection
local colbox = false
local radius = colbox and 3.0 or 1.0
--= Functions inspired from Kaeza's Firearms mod
local function minmax(x, y)
return min(x, y), max(x, y)
end
local function pos_in_box(p, b1, b2)
local xmin, xmax = minmax(b1.x, b2.x)
local ymin, ymax = minmax(b1.y, b2.y)
local zmin, zmax = minmax(b1.z, b2.z)
return p.x >= xmin and p.x <= xmax
and p.y >= ymin and p.y <= ymax
and p.z >= zmin and p.z <= zmax
end
local function get_obj_box(obj)
local box
if obj:is_player() then
box = {-.5, -.5, -.5, .5, 1.5, .5}
else
box = obj:get_luaentity().collisionbox
or {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
end
local p = obj:get_pos()
local x1, y1, z1, x2, y2, z2 = unpack(box)
return {x = x1 + p.x, y = y1 + p.y, z = z1 + p.z},
{x = x2 + p.x, y = y2 + p.y, z = z2 + p.z}
end
--= END (Thanks Kaeza :)
local on_hit_remove = function(self)
minetest.sound_play(
bows.registered_arrows[self.name].on_hit_sound, {
pos = self.object:get_pos(),
gain = 1.0,
max_hear_distance = 7
})
-- chance of dropping arrow
local chance = bows.registered_arrows[self.name].drop_chance
if math.random(0, chance) == 1 then
minetest.add_item(self.object:get_pos(), self.name)
end
self.object:remove()
return self
end
local on_hit_object = function(self, target, hp, user, lastpos)
target:punch(user, 0.1, {
full_punch_interval = 0.1,
damage_groups = {fleshy = hp},
}, nil)
if bows.registered_arrows[self.name].on_hit_object then
bows.registered_arrows[self.name].on_hit_object(
self, target, hp, user, lastpos)
end
on_hit_remove(self)
return self
end
minetest.register_entity("bows:arrow",{
hp_max = 10,
visual = "wielditem",
visual_size = {x = .20, y = .20},
collisionbox = {-0.1,-0.1,-0.1,0.1,0.1,0.1},
physical = true,
textures = {"air"},
_is_arrow = true,
timer = 20,
oldvel = {x = 0, y = 0, z = 0},
on_activate = function(self, staticdata)
if not self then
self.object:remove()
return
end
if bows.tmp and bows.tmp.arrow ~= nil then
self.arrow = bows.tmp.arrow
self.user = bows.tmp.user
self.name = bows.tmp.name
self.dmg = bows.registered_arrows[self.name].damage
self.text = bows.registered_arrows[self.name].disp_entity
bows.tmp = nil
self.object:set_properties({textures = {self.text}})
else
self.object:remove()
end
end,
on_step = function(self, dtime, ...)
self.timer = self.timer - dtime
if self.timer < 0 then
self.object:remove()
return
end
local what_is, what_obj, ent
for i, ob in pairs(minetest.get_objects_inside_radius(
self.object:get_pos(), radius)) do
what_obj = nil
what_is = ""
-- player
if ob
and bows.pvp
and ob:is_player()
and ob:get_player_name() ~= self.user:get_player_name() then
what_obj = ob
what_is = "player"
end
-- entity/mob
if ob and not what_obj then
ent = ob:get_luaentity()
if ent
and ent.physical
and not ent._is_arrow
and ent.name ~= "__builtin:item" then
what_obj = ob
what_is = "entity"
end
end
if what_obj then
if colbox then
-- Object specific collision detection
local p1, p2 = get_obj_box(what_obj)
if pos_in_box(self.object:get_pos(), p1, p2) then
on_hit_object(self, what_obj, self.dmg, self.user,
self.object:get_pos())
return self
end
else
on_hit_object(self, what_obj, self.dmg, self.user,
self.object:get_pos())
return self
end
end
end
local vel = self.object:get_velocity()
if vel.x == 0 or vel.y == 0 or vel.z == 0 then
if bows.registered_arrows[self.name].on_hit_node then
local pos = self.object:get_pos()
local lastpos = {x = pos.x, y = pos.y, z = pos.z}
pos.x = pos.x + (self.oldvel.x / 100)
pos.y = pos.y + (self.oldvel.y / 100)
pos.z = pos.z + (self.oldvel.z / 100)
self.node = minetest.get_node(pos)
bows.registered_arrows[self.name].on_hit_node(
self, pos, self.user, lastpos)
end
on_hit_remove(self)
return self
end
self.oldvel = vel
end,
})

54
mods/bows/bows.lua Normal file
View File

@ -0,0 +1,54 @@
--BOWS------------------------------------------------------------------------------------
bows.register_bow('bow_wood',{
description = 'Wooden bow',
texture = 'bows_bow.png',
texture_loaded = 'bows_bow_loaded.png',
uses = 100,
level = 15,
craft = {
{'', 'group:stick', 'farming:string'},
{'group:stick', '', 'farming:string'},
{'', 'group:stick', 'farming:string'}
},
})
--ARROWS----------------------------------------------------------------------------------
minetest.register_craftitem('bows:arrow_ent', {
inventory_image = 'bows_arrow_ent.png',
groups = {not_in_creative_inventory=1}
})
bows.register_arrow('arrow_1',{
description = 'Weak Arrow',
texture = 'bows_arrow_1.png',
displayed_entity = 'bows:arrow_ent',
damage = 4,
drop_chance = 3,
craft = {
{'group:stick', 'mobs:chicken_feather'}
},
})
bows.register_arrow('arrow_2',{
description = 'Fair Arrow',
texture = 'bows_arrow_2.png',
displayed_entity = 'bows:arrow_ent',
speed = 2,
damage = 6,
drop_chance = 2,
craft = {
{'default:flint', 'group:stick', 'mobs:chicken_feather'}
},
})
bows.register_arrow('arrow_3',{
description = 'Good Arrow',
texture = 'bows_arrow_3.png',
displayed_entity = 'bows:arrow_ent',
speed = 4,
damage = 10,
drop_chance = 1,
craft = {
{'epic:arrow_tip', 'group:stick', 'mobs:chicken_feather'}
},
})

77
mods/bows/crossbows.lua Normal file
View File

@ -0,0 +1,77 @@
--CROSSBOWS-------------------------------------------------------------------------------
bows.register_bow('crossbow',{
description = 'Crossbow',
texture = 'bows_crossbow_inv.png',
texture_loaded = 'bows_crossbow_loaded.png',
ammo = 'bolt',
uses = 300,
level = 25,
craft = {
{'default:steel_ingot', 'default:stick', 'default:steel_ingot'},
{'farming:string', 'farming:string', 'farming:string'},
{'', 'default:stick', ''},
},
})
--CROSSBOW BOLTS--------------------------------------------------------------------------
minetest.register_craftitem('bows:bolt_ent', {
inventory_image = 'bows_bolt_ent.png',
groups = {not_in_creative_inventory=1}
})
bows.register_arrow('bolt_1',{
description = 'Weak Crossbow Bolt',
texture = 'bows_bolt_1.png',
displayed_entity = 'bows:bolt_ent',
type = 'bolt',
damage = 6,
drop_chance = 3,
craft = {
{'default:stick'}
},
})
bows.register_arrow('bolt_2',{
description = 'Fair Crossbow Bolt',
texture = 'bows_bolt_2.png',
displayed_entity = 'bows:bolt_ent',
type = 'bolt',
speed = 2,
damage = 8,
drop_chance = 2,
craft = {
{'default:flint', 'default:stick'}
},
})
bows.register_arrow('bolt_3',{
description = 'Good Crossbow Bolt',
texture = 'bows_bolt_3.png',
displayed_entity = 'bows:bolt_ent',
type = 'bolt',
speed = 4,
damage = 12,
drop_chance = 1,
craft = {
{'epic:arrow_tip', 'default:stick'}
},
})
bows.register_arrow('bolt_exploding',{
description = 'Exploding Crossbow Bolt',
texture = 'bows_bolt_exp.png',
displayed_entity = 'bows:bolt_ent',
type = 'bolt',
speed = 2,
damage = 5,
drop_chance = 0,
craft = {
{'bows:bolt_3', 'tnt:gunpowder_stick'}
},
on_hit_node = function(self, pos, user, arrow_pos)
if self.node.name ~= '' and not minetest.is_protected(pos, user:get_player_name()) then
print (self.node.name)
tnt.boom(vector.round(pos), {radius = 2, damage_radius = 4})
end
end,
})

148
mods/bows/init.lua Normal file
View File

@ -0,0 +1,148 @@
-- Bows Mod by UjEdwin
bows = {
pvp = minetest.settings:get_bool('enable_pvp'),
registered_arrows = {},
registered_bows = {},
}
local creative_mode_cache = minetest.settings:get_bool('creative_mode')
function bows.is_creative(name)
return creative_mode_cache or minetest.check_player_privs(name, {creative = true})
end
bows.register_arrow = function(name, def)
if name == nil
or name == '' then
return false
end
def.damage = def.damage or 0
def.name = 'bows:' .. name
def.level = def.level or 1
def.disp_entity = def.displayed_entity or def.name
def.on_hit_object = def.on_hit_object
def.on_hit_node = def.on_hit_node
def.speed = def.speed or 0
def.on_hit_sound = def.on_hit_sound or 'default_dig_dig_immediate'
bows.registered_arrows[def.name] = def
if def.type == 'bolt' then
minetest.register_craftitem(':bows:' .. name, {
description = def.description or name,
inventory_image = def.texture or 'bows_arrow_wooden.png',
groups = {bolt = 1},
drop_chance = def.drop_chance
})
else
minetest.register_craftitem(':bows:' .. name, {
description = def.description or name,
inventory_image = def.texture or 'bows_arrow_wooden.png',
groups = {arrow = 1},
drop_chance = def.drop_chance
})
end
if def.craft then
minetest.register_craft({
output = def.name ..' ' .. (def.craft_count or 1),
recipe = def.craft
})
end
end
bows.register_bow = function(name, def)
if name == nil
or name == '' then
return false
end
def.replace = 'bows:' .. name .. '_loaded'
def.name = 'bows:' .. name
def.uses = def.uses - 1 or 49
def.ammo = def.ammo or 'arrow'
bows.registered_bows[def.replace] = def
bows.registered_bows[def.name] = def
minetest.register_tool(':' .. def.name, {
description = def.description or name,
inventory_image = def.texture or 'bows_bow.png',
on_use = bows.load,
groups = {bow = 1},
})
minetest.register_tool(':' .. def.replace, {
description = def.description or name,
inventory_image = def.texture_loaded or 'bows_bow_loaded.png',
on_use = bows.shoot,
groups = {bow = 1, not_in_creative_inventory = 1},
})
if def.craft then
minetest.register_craft({output = def.name,recipe = def.craft})
end
end
bows.load = function(itemstack, user, pointed_thing)
local name = itemstack:get_name()
local ammo = bows.registered_bows[name].ammo
local inv = user:get_inventory()
local index = user:get_wield_index() - 1
local arrow = inv:get_stack('main', index)
if minetest.get_item_group(arrow:get_name(), ammo) == 0 then
return itemstack
end
local item = itemstack:to_table()
local meta = minetest.deserialize(item.metadata)
meta = {arrow = arrow:get_name()}
item.metadata = minetest.serialize(meta)
item.name = item.name .. '_loaded'
itemstack:replace(item)
if not bows.is_creative(user:get_player_name()) then
inv:set_stack('main', index,
ItemStack(arrow:get_name() .. ' ' .. (arrow:get_count() - 1)))
end
return itemstack
end
bows.shoot = function(itemstack, user, pointed_thing)
local item = itemstack:to_table()
local meta = minetest.deserialize(item.metadata)
if (not (meta and meta.arrow))
or (not bows.registered_arrows[meta.arrow]) then
return itemstack
end
local name = itemstack:get_name()
local replace = bows.registered_bows[name].name
local ar = bows.registered_bows[name].uses
local wear = bows.registered_bows[name].uses
local arrow_speed = bows.registered_arrows[meta.arrow].speed
print ('arrow speed is '..arrow_speed)
local level = bows.registered_bows[name].level + arrow_speed
bows.tmp = {}
bows.tmp.arrow = meta.arrow
bows.tmp.user = user
bows.tmp.name = meta.arrow
item.arrow = ''
item.metadata = minetest.serialize(meta)
item.name = replace
itemstack:replace(item)
local pos = user:get_pos()
local dir = user:get_look_dir()
local e = minetest.add_entity({
x = pos.x,
y = pos.y + 1.5,
z = pos.z
}, 'bows:arrow')
e:set_velocity({x = dir.x * level, y = dir.y * level, z = dir.z * level})
e:set_acceleration({x = dir.x * -3, y = -4, z = dir.z * -3})
e:set_yaw(user:get_look_horizontal() - math.pi/2)
if not bows.is_creative(user:get_player_name()) then
itemstack:add_wear(65535 / wear)
end
minetest.sound_play('bows_shoot', {pos = pos})
return itemstack
end
local path = minetest.get_modpath('bows')
dofile(path .. '/arrow.lua')
dofile(path .. '/bows.lua')
dofile(path .. '/crossbows.lua')
minetest.register_alias('castle_weapons:crossbow', 'bows:crossbow')
minetest.register_alias('castle_weapons:crossbow_bolt', 'bows:bolt_3')

4
mods/bows/mod.conf Normal file
View File

@ -0,0 +1,4 @@
name = bows
depends = default, tnt
optional_dependency = mobs, castle_weapons
description = Adds a selection of bows and arrows for players to use in-game.

9
mods/bows/readme.MD Normal file
View File

@ -0,0 +1,9 @@
# Bows Mod for Minetest
### Originally by AiTechEye
### Forked and tweaked by TenPlus1
This mod allows the player to craft bows and arrows to be used in game that can hurt players and mobs as well as affect nodes hit when using special functions included in the arrow definition.
License: CC0

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

View File

@ -10,14 +10,14 @@ Licence Models: Stuart Jones - CC-BY-SA 3.0
License Sounds: freesound.org
--]]
minetest.register_alias('crossbow', 'castle_weapons:crossbow')
minetest.register_alias('bolt', 'castle_weapons:crossbow_bolt')
minetest.register_alias('castle:crossbow', 'castle_weapons:crossbow')
minetest.register_alias('castle:bolt', 'castle_weapons:crossbow_bolt')
minetest.register_alias('castle:crossbow_bolt', 'castle_weapons:crossbow_bolt')
minetest.register_alias('castle:crossbow_loaded', 'castle_weapons:crossbow_loaded')
--]]
-- internationalization boilerplate
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP..'/intllib.lua')
@ -462,13 +462,13 @@ minetest.register_tool('castle_weapons:crossbow', {
inventory_image = 'castle_crossbow_inv.png',
on_use = function(itemstack, user, pointed_thing)
local inv = user:get_inventory()
if inv:contains_item('main', 'castle_weapons:crossbow_bolt') then
minetest.sound_play('castle_crossbow_reload', {object=user})
if not minetest.settings:get_bool('creative_mode') then
inv:remove_item('main', 'castle_weapons:crossbow_bolt 1')
end
return 'castle_weapons:crossbow_loaded 1 '..itemstack:get_wear()
if inv:contains_item('main', 'castle_weapons:crossbow_bolt') then
minetest.sound_play('castle_crossbow_reload', {object=user})
if not minetest.settings:get_bool('creative_mode') then
inv:remove_item('main', 'castle_weapons:crossbow_bolt 1')
end
return 'castle_weapons:crossbow_loaded 1 '..itemstack:get_wear()
end
minetest.sound_play('castle_crossbow_click', {object=user})
end,
})

View File

@ -1,7 +1,4 @@
local MP = minetest.get_modpath(minetest.get_current_modname())
dofile(MP.."/crossbow.lua")
--dofile(MP.."/crossbow.lua")
dofile(MP.."/battleaxe.lua")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,4 +1,7 @@
local news = {
'10/17/20',
'Added a second bow, tiered arrows, and exploding crossbow bolts.',
'',
'10/13/20',
'Added stone carving station, and stone pkarcs.',
'',

View File

@ -22,7 +22,7 @@ for i in ipairs (tool_repair) do
local tool = tool_repair[i][1]
local matrl = tool_repair[i][2]
simplecrafting_lib.register('crystal_w', {
stations.dual_register_recipe('crystal_w', {
input = {
[tool] = 1,
[matrl] = 1,

View File

@ -29,7 +29,7 @@ local tool_repair ={
{'shields:shield_steel', 'default:steel_ingot'},
{'shields:shield_gold', 'default:gold_ingot'},
{'castle_weapons:battleaxe', 'default:steel_ingot'},
{'castle_weapons:crossbow', 'default:steel_ingot'},
{'bows:crossbow', 'default:steel_ingot'},
{'stations:hammer', 'default:steel_ingot'},
{'epic:pick_titanium', 'epic:titanium_ingot'},
{'epic:shovel_titanium', 'epic:titanium_ingot'},
@ -50,9 +50,7 @@ for i in ipairs (tool_repair) do
local tool = tool_repair[i][1]
local material = tool_repair[i][2]
-- no stations.dual_register_recipe() to ignore registering repair recipes...
--
simplecrafting_lib.register('anvil', {
stations.dual_register_recipe('anvil', {
input = {
[tool] = 1,
[material] = 1,