3 dofile(minetest
.get_modpath("mcl_throwing").."/arrow.lua")
4 dofile(minetest
.get_modpath("mcl_throwing").."/throwable.lua")
7 ["mcl_throwing:arrow"] = "mcl_throwing:arrow_entity",
11 local BOW_DURABILITY
= 385
12 local CHARGE_SPEED
= 1
16 mcl_throwing
.shoot_arrow
= function(arrow_item
, pos
, dir
, yaw
, shooter
, power
, damage
)
17 local obj
= minetest
.add_entity({x
=pos
.x
,y
=pos
.y
,z
=pos
.z
}, arrows
[arrow_item
])
24 obj
:setvelocity({x
=dir
.x
*power
, y
=dir
.y
*power
, z
=dir
.z
*power
})
25 obj
:setacceleration({x
=dir
.x
*-3, y
=-GRAVITY
, z
=dir
.z
*-3})
26 obj
:setyaw(yaw
-math
.pi
/2)
27 local le
= obj
:get_luaentity()
31 minetest
.sound_play("mcl_throwing_bow_shoot", {pos
=pos
})
32 if shooter
~= nil then
33 if obj
:get_luaentity().player
== "" then
34 obj
:get_luaentity().player
= shooter
36 obj
:get_luaentity().node
= shooter
:get_inventory():get_stack("main", 1):get_name()
41 local get_arrow
= function(player
)
42 local inv
= player
:get_inventory()
43 local arrow_stack
, arrow_stack_id
44 for i
=1, inv
:get_size("main") do
45 local it
= inv
:get_stack("main", i
)
46 if not it
:is_empty() and minetest
.get_item_group(it
:get_name(), "ammo_bow") ~= 0 then
52 return arrow_stack
, arrow_stack_id
55 local player_shoot_arrow
= function(itemstack
, player
, power
, damage
)
56 local arrow_stack
, arrow_stack_id
= get_arrow(player
)
57 local arrow_itemstring
58 if not minetest
.settings
:get_bool("creative_mode") then
59 if not arrow_stack
then
62 arrow_itemstring
= arrow_stack
:get_name()
63 arrow_stack
:take_item()
64 local inv
= player
:get_inventory()
65 inv
:set_stack("main", arrow_stack_id
, arrow_stack
)
67 local playerpos
= player
:getpos()
68 local dir
= player
:get_look_dir()
69 local yaw
= player
:get_look_horizontal()
71 if not arrow_itemstring
then
72 arrow_itemstring
= "mcl_throwing:arrow"
74 mcl_throwing
.shoot_arrow(arrow_itemstring
, {x
=playerpos
.x
,y
=playerpos
.y
+1.5,z
=playerpos
.z
}, dir
, yaw
, player
, power
, damage
)
78 local powerup_function
= function(nextbow
)
79 return function(itemstack
, placer
, pointed_thing
)
80 -- Use pointed node's on_rightclick function first, if present
81 if pointed_thing
.type == "node" then
82 local node
= minetest
.get_node(pointed_thing
.under
)
83 if placer
and not placer
:get_player_control().sneak
then
84 if minetest
.registered_nodes
[node
.name
] and minetest
.registered_nodes
[node
.name
].on_rightclick
then
85 return minetest
.registered_nodes
[node
.name
].on_rightclick(pointed_thing
.under
, node
, placer
, itemstack
) or itemstack
90 -- Check for arrow or Creative Mode
91 if minetest
.settings
:get_bool("creative_mode") or get_arrow(placer
) ~= nil then
92 local wear
= itemstack
:get_wear()
93 itemstack
:replace(nextbow
)
94 itemstack
:set_wear(wear
)
100 minetest
.register_tool("mcl_throwing:bow", {
102 _doc_items_longdesc
= "Bows are ranged weapons to shoot arrows at your foes.",
103 _doc_items_usagehelp
= [[To use the bow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to shoot.
105 The arrow speed and damage increase with the charge level:
106 • Low charge: 1 damage
107 • Medium charge: 2 damage
108 • High charge: 4-5 damage (20% chance for 5 damage)]],
109 _doc_items_durability
= BOW_DURABILITY
,
110 inventory_image
= "mcl_throwing_bow.png",
112 -- Trick to disable melee damage to entities.
113 -- Range not set to 0 (unlike the others) so it can be placed into item frames
115 -- Trick to disable digging as well
116 on_use
= function() end,
117 groups
= {weapon
=1,weapon_ranged
=1},
120 minetest
.register_tool("mcl_throwing:bow_0", {
122 _doc_items_create_entry
= false,
123 inventory_image
= "mcl_throwing_bow_0.png",
125 range
= 0, -- Pointing range to 0 to prevent punching with bow :D
126 groups
= {not_in_creative_inventory
=1, not_in_craft_guide
=1},
129 minetest
.register_tool("mcl_throwing:bow_1", {
131 _doc_items_create_entry
= false,
132 inventory_image
= "mcl_throwing_bow_1.png",
135 groups
= {not_in_creative_inventory
=1, not_in_craft_guide
=1},
138 minetest
.register_tool("mcl_throwing:bow_2", {
140 _doc_items_create_entry
= false,
141 inventory_image
= "mcl_throwing_bow_2.png",
144 groups
= {not_in_creative_inventory
=1, not_in_craft_guide
=1},
147 controls
.register_on_release(function(player
, key
, time
)
148 if key
~="RMB" then return end
149 local inv
= minetest
.get_inventory({type="player", name
=player
:get_player_name()})
150 local wielditem
= player
:get_wielded_item()
151 if (wielditem
:get_name()=="mcl_throwing:bow_0" or wielditem
:get_name()=="mcl_throwing:bow_1" or wielditem
:get_name()=="mcl_throwing:bow_2") then
153 if wielditem
:get_name()=="mcl_throwing:bow_0" then
154 shot
= player_shoot_arrow(wielditem
, player
, 4, 1)
155 elseif wielditem
:get_name()=="mcl_throwing:bow_1" then
156 shot
= player_shoot_arrow(wielditem
, player
, 16, 2)
157 elseif wielditem
:get_name()=="mcl_throwing:bow_2" then
158 local r
= math
.random(1,5)
160 -- Damage and range have been nerfed because the arrow charges very quickly
161 -- TODO: Use Minecraft damage and range (9-10 @ ca. 53 m/s)
163 -- 20% chance for critical hit
168 shot
= player_shoot_arrow(wielditem
, player
, 26, damage
)
170 wielditem
:set_name("mcl_throwing:bow")
171 if shot
and minetest
.settings
:get_bool("creative_mode") == false then
172 wielditem
:add_wear(65535/BOW_DURABILITY
)
174 player
:set_wielded_item(wielditem
)
175 bow_load
[player
:get_player_name()] = false
179 controls
.register_on_hold(function(player
, key
, time
)
183 local name
= player
:get_player_name()
184 local inv
= minetest
.get_inventory({type="player", name
=name
})
185 local wielditem
= player
:get_wielded_item()
186 if wielditem
:get_name()=="mcl_throwing:bow" and (minetest
.settings
:get_bool("creative_mode") or inv
:contains_item("main", "mcl_throwing:arrow")) then
187 wielditem
:set_name("mcl_throwing:bow_0")
188 bow_load
[name
] = os
.time()
190 if type(bow_load
[name
]) == "number" then
191 if wielditem
:get_name() == "mcl_throwing:bow_0" and os
.time() - bow_load
[name
] > CHARGE_SPEED
then
192 wielditem
:set_name("mcl_throwing:bow_1")
193 elseif wielditem
:get_name() == "mcl_throwing:bow_1" and os
.time() - bow_load
[name
] > CHARGE_SPEED
*2 then
194 wielditem
:set_name("mcl_throwing:bow_2")
197 wielditem
:set_name("mcl_throwing:bow")
200 player
:set_wielded_item(wielditem
)
203 minetest
.register_globalstep(function(dtime
)
204 for _
, player
in pairs(minetest
.get_connected_players()) do
205 local wielditem
= player
:get_wielded_item()
206 --if wielditem:get_name()=="bow:bow_dropped" then
207 -- wielditem:set_name("bow:bow")
208 -- player:set_wielded_item(wielditem)
210 local controls
= player
:get_player_control()
211 local inv
= minetest
.get_inventory({type="player", name
= player
:get_player_name()})
212 if bow_load
[player
:get_player_name()] and (wielditem
:get_name()~="mcl_throwing:bow_0" and wielditem
:get_name()~="mcl_throwing:bow_1" and wielditem
:get_name()~="mcl_throwing:bow_2") then
213 local list
= inv
:get_list("main")
214 for place
, stack
in pairs(list
) do
215 if stack
:get_name()=="mcl_throwing:bow_0" or stack
:get_name()=="mcl_throwing:bow_1" or stack
:get_name()=="mcl_throwing:bow_2" then
216 stack
:set_name("mcl_throwing:bow")
221 inv
:set_list("main", list
)
222 bow_load
[player
:get_player_name()] = false
227 if minetest
.get_modpath("mcl_core") and minetest
.get_modpath("mcl_mobitems") then
228 minetest
.register_craft({
229 output
= 'mcl_throwing:bow',
231 {'', 'mcl_core:stick', 'mcl_mobitems:string'},
232 {'mcl_core:stick', '', 'mcl_mobitems:string'},
233 {'', 'mcl_core:stick', 'mcl_mobitems:string'},
236 minetest
.register_craft({
237 output
= 'mcl_throwing:bow',
239 {'mcl_mobitems:string', 'mcl_core:stick', ''},
240 {'mcl_mobitems:string', '', 'mcl_core:stick'},
241 {'mcl_mobitems:string', 'mcl_core:stick', ''},
246 minetest
.register_craft({
248 recipe
= "mcl_throwing:bow",
252 -- Add entry aliases for the Help
253 if minetest
.get_modpath("doc") then
254 doc
.add_entry_alias("tools", "mcl_throwing:bow", "tools", "mcl_throwing:bow_0")
255 doc
.add_entry_alias("tools", "mcl_throwing:bow", "tools", "mcl_throwing:bow_1")
256 doc
.add_entry_alias("tools", "mcl_throwing:bow", "tools", "mcl_throwing:bow_2")