Move bow/arrow logic into new mod mcl_bows

This commit is contained in:
Wuzzy 2018-05-07 23:10:49 +02:00
parent e55a1a6211
commit 4be5f89829
27 changed files with 391 additions and 388 deletions

View file

@ -34,7 +34,7 @@ minetest.register_node("mobs_mc:arrow_box", {
{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, 8.5/17, -3.5/17, -3.5/17},
} }
}, },
tiles = {"mcl_throwing_arrow.png^[transformFX", "mcl_throwing_arrow.png^[transformFX", "mcl_throwing_arrow_back.png", "mcl_throwing_arrow_front.png", "mcl_throwing_arrow.png", "mcl_throwing_arrow.png^[transformFX"}, tiles = {"mcl_bows_arrow.png^[transformFX", "mcl_bows_arrow.png^[transformFX", "mcl_bows_arrow_back.png", "mcl_bows_arrow_front.png", "mcl_bows_arrow.png", "mcl_bows_arrow.png^[transformFX"},
groups = {not_in_creative_inventory=1}, groups = {not_in_creative_inventory=1},
}) })
@ -135,7 +135,7 @@ if c("arrow") then
description = S("Arrow"), description = S("Arrow"),
_doc_items_longdesc = S("Arrows are ammunition for bows."), _doc_items_longdesc = S("Arrows are ammunition for bows."),
_doc_items_usagehelp = S("To use arrows as ammunition for a bow, put them in the inventory slot following the bow. Slots are counted left to right, top to bottom."), _doc_items_usagehelp = S("To use arrows as ammunition for a bow, put them in the inventory slot following the bow. Slots are counted left to right, top to bottom."),
inventory_image = "mcl_throwing_arrow_inv.png", inventory_image = "mcl_bows_arrow_inv.png",
}) })
end end
@ -155,7 +155,7 @@ if c("bow") then
description = S("Bow"), description = S("Bow"),
_doc_items_longdesc = S("Bows are ranged weapons to shoot arrows at your foes."), _doc_items_longdesc = S("Bows are ranged weapons to shoot arrows at your foes."),
_doc_items_usagehelp = S("To use the bow, you first need to have at least one arrow in slot following the bow. Leftclick to shoot. Each hit deals 3 damage."), _doc_items_usagehelp = S("To use the bow, you first need to have at least one arrow in slot following the bow. Leftclick to shoot. Each hit deals 3 damage."),
inventory_image = "mcl_throwing_bow.png", inventory_image = "mcl_bows_bow.png",
on_use = function(itemstack, user, pointed_thing) on_use = function(itemstack, user, pointed_thing)
if throwing_shoot_arrow(itemstack, user, pointed_thing) then if throwing_shoot_arrow(itemstack, user, pointed_thing) then
if not minetest.settings:get_bool("creative_mode") then if not minetest.settings:get_bool("creative_mode") then

View file

@ -1,8 +1,8 @@
default? default?
mobs mobs
tnt? tnt?
mcl_bows?
mcl_throwing? mcl_throwing?
throwing?
fishing? fishing?
bones? bones?
mesecons_materials? mesecons_materials?

View file

@ -21,7 +21,7 @@ mobs:register_mob("mobs_mc:illusioner", {
textures = { { textures = { {
"mobs_mc_illusionist.png", "mobs_mc_illusionist.png",
"mobs_mc_illusionist.png", --hat "mobs_mc_illusionist.png", --hat
"mcl_throwing_bow.png", "mcl_bows_bow.png",
}, }, }, },
visual_size = {x=3, y=3}, visual_size = {x=3, y=3},
walk_velocity = 0.6, walk_velocity = 0.6,

View file

@ -33,8 +33,8 @@ mobs_mc.override.items = {
snowball = "mcl_throwing:snowball", snowball = "mcl_throwing:snowball",
top_snow = "mcl_core:snow", top_snow = "mcl_core:snow",
snow_block = "mcl_core:snowblock", snow_block = "mcl_core:snowblock",
arrow = "mcl_throwing:arrow", arrow = "mcl_bows:arrow",
bow = "mcl_throwing:bow", bow = "mcl_bows:bow",
head_zombie = "mcl_heads:zombie", head_zombie = "mcl_heads:zombie",
head_creeper = "mcl_heads:creeper", head_creeper = "mcl_heads:creeper",
head_skeleton = "mcl_heads:skeleton", head_skeleton = "mcl_heads:skeleton",

View file

@ -152,13 +152,13 @@ awards.register_achievement("mcl:onARail", {
icon = "default_rail.png", icon = "default_rail.png",
}) })
-- Triggered in mcl_throwing -- Triggered in mcl_bows
awards.register_achievement("mcl:snipeSkeleton", { awards.register_achievement("mcl:snipeSkeleton", {
title = S("Sniper Duel"), title = S("Sniper Duel"),
-- TODO: This achievement should be for killing, not hitting -- TODO: This achievement should be for killing, not hitting
-- TODO: The range should be 50, not 20. Nerfed because of reduced bow range -- TODO: The range should be 50, not 20. Nerfed because of reduced bow range
description = S("Hit a skeleton, wither skeleton or stray by bow and arrow from a distance of at least 20 meters."), description = S("Hit a skeleton, wither skeleton or stray by bow and arrow from a distance of at least 20 meters."),
icon = "mcl_throwing_bow.png", icon = "mcl_bows_bow.png",
}) })
-- Triggered in mcl_portals -- Triggered in mcl_portals

View file

@ -217,7 +217,7 @@ minetest.register_on_punchplayer(function(player, hitter)
hittertype = "mob" hittertype = "mob"
hittersubtype = hitter:get_luaentity().name hittersubtype = hitter:get_luaentity().name
-- Arrow -- Arrow
elseif hitter:get_luaentity().name == "mcl_throwing:arrow_entity" or hitter:get_luaentity().name == "mobs_mc:arrow_entity" then elseif hitter:get_luaentity().name == "mcl_bows:arrow_entity" or hitter:get_luaentity().name == "mobs_mc:arrow_entity" then
hittertype = "arrow" hittertype = "arrow"
if hitter:get_luaentity()._shooter then if hitter:get_luaentity()._shooter then
shooter = hitter:get_luaentity()._shooter shooter = hitter:get_luaentity()._shooter

View file

@ -320,7 +320,7 @@ minetest.register_craft({
output = 'mcl_dispensers:dispenser', output = 'mcl_dispensers:dispenser',
recipe = { recipe = {
{"mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble",}, {"mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble",},
{"mcl_core:cobble", "mcl_throwing:bow", "mcl_core:cobble",}, {"mcl_core:cobble", "mcl_bows:bow", "mcl_core:cobble",},
{"mcl_core:cobble", "mesecons:redstone", "mcl_core:cobble",}, {"mcl_core:cobble", "mesecons:redstone", "mcl_core:cobble",},
} }
}) })
@ -331,7 +331,7 @@ local check_craft = function(itemstack, player, old_craft_grid, craft_inv)
local bow, id local bow, id
for i=1, craft_inv:get_size("craft") do for i=1, craft_inv:get_size("craft") do
local item = craft_inv:get_stack("craft", i) local item = craft_inv:get_stack("craft", i)
if item:get_name() == "mcl_throwing:bow" then if item:get_name() == "mcl_bows:bow" then
bow = item bow = item
id = i id = i
break break

View file

@ -1,4 +1,4 @@
This mod adds bows, arrows and throwable items for MineClone 2. This mod adds bows and arrows for MineClone 2.
License: License:
* Source code: LGPL 3.0 * Source code: LGPL 3.0
@ -7,7 +7,7 @@ License:
* Textures: See MineClone 2 license notes. * Textures: See MineClone 2 license notes.
* Sounds: * Sounds:
* mcl_throwing_bow_shoot.ogg: MIT License * mcl_bows_bow_shoot.ogg: MIT License
* mcl_throwing_hit_player.ogg: CC BY 3.0 by Freesound.org user tim.kahn. * mcl_bows_hit_player.ogg: CC BY 3.0 by Freesound.org user tim.kahn.
https://freesound.org/people/tim.kahn/sounds/38495/ https://freesound.org/people/tim.kahn/sounds/38495/
http://creativecommons.org/licenses/by/3.0/ http://creativecommons.org/licenses/by/3.0/

View file

@ -1,22 +1,22 @@
local mod_mcl_hunger = minetest.get_modpath("mcl_hunger") local mod_mcl_hunger = minetest.get_modpath("mcl_hunger")
local mod_awards = minetest.get_modpath("awards") and minetest.get_modpath("mcl_achievements") local mod_awards = minetest.get_modpath("awards") and minetest.get_modpath("mcl_achievements")
minetest.register_craftitem("mcl_throwing:arrow", { minetest.register_craftitem("mcl_bows:arrow", {
description = "Arrow", description = "Arrow",
_doc_items_longdesc = [[Arrows are ammunition for bows and dispensers. _doc_items_longdesc = [[Arrows are ammunition for bows and dispensers.
An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 20% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.]], An arrow fired from a bow has a regular damage of 1-9. At full charge, there's a 20% chance of a critical hit dealing 10 damage instead. An arrow fired from a dispenser always deals 3 damage.]],
_doc_items_usagehelp = "To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory.", _doc_items_usagehelp = "To use arrows as ammunition for a bow, just put them anywhere in your inventory, they will be used up automatically. To use arrows as ammunition for a dispenser, place them in the dispenser's inventory.",
inventory_image = "mcl_throwing_arrow_inv.png", inventory_image = "mcl_bows_arrow_inv.png",
groups = { ammo=1, ammo_bow=1 }, groups = { ammo=1, ammo_bow=1 },
_on_dispense = function(itemstack, dispenserpos, droppos, dropnode, dropdir) _on_dispense = function(itemstack, dispenserpos, droppos, dropnode, dropdir)
-- Shoot arrow -- Shoot arrow
local shootpos = vector.add(dispenserpos, vector.multiply(dropdir, 0.51)) local shootpos = vector.add(dispenserpos, vector.multiply(dropdir, 0.51))
local yaw = math.atan2(dropdir.z, dropdir.x) - math.pi/2 local yaw = math.atan2(dropdir.z, dropdir.x) - math.pi/2
mcl_throwing.shoot_arrow(itemstack:get_name(), shootpos, dropdir, yaw, nil, 19, 3) mcl_bows.shoot_arrow(itemstack:get_name(), shootpos, dropdir, yaw, nil, 19, 3)
end, end,
}) })
minetest.register_node("mcl_throwing:arrow_box", { minetest.register_node("mcl_bows:arrow_box", {
drawtype = "nodebox", drawtype = "nodebox",
is_ground_content = false, is_ground_content = false,
node_box = { node_box = {
@ -39,7 +39,7 @@ minetest.register_node("mcl_throwing:arrow_box", {
{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, 8.5/17, -3.5/17, -3.5/17},
} }
}, },
tiles = {"mcl_throwing_arrow.png^[transformFX", "mcl_throwing_arrow.png^[transformFX", "mcl_throwing_arrow_back.png", "mcl_throwing_arrow_front.png", "mcl_throwing_arrow.png", "mcl_throwing_arrow.png^[transformFX"}, tiles = {"mcl_bows_arrow.png^[transformFX", "mcl_bows_arrow.png^[transformFX", "mcl_bows_arrow_back.png", "mcl_bows_arrow_front.png", "mcl_bows_arrow.png", "mcl_bows_arrow.png^[transformFX"},
groups = {not_in_creative_inventory=1}, groups = {not_in_creative_inventory=1},
}) })
@ -47,7 +47,7 @@ local THROWING_ARROW_ENTITY={
physical = false, physical = false,
visual = "wielditem", visual = "wielditem",
visual_size = {x=0.4, y=0.4}, visual_size = {x=0.4, y=0.4},
textures = {"mcl_throwing:arrow_box"}, textures = {"mcl_bows:arrow_box"},
collisionbox = {0,0,0,0,0,0}, collisionbox = {0,0,0,0,0,0},
_lastpos={}, _lastpos={},
@ -104,7 +104,7 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
if is_player then if is_player then
if self._shooter and self._shooter:is_player() then if self._shooter and self._shooter:is_player() then
-- “Ding” sound for hitting another player -- “Ding” sound for hitting another player
minetest.sound_play({name="mcl_throwing_hit_player", gain=0.1}, {to_player=self._shooter}) minetest.sound_play({name="mcl_bows_hit_player", gain=0.1}, {to_player=self._shooter})
end end
if mod_mcl_hunger then if mod_mcl_hunger then
mcl_hunger.exhaust(obj:get_player_name(), mcl_hunger.EXHAUST_DAMAGE) mcl_hunger.exhaust(obj:get_player_name(), mcl_hunger.EXHAUST_DAMAGE)
@ -132,7 +132,7 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
local def = minetest.registered_nodes[node.name] local def = minetest.registered_nodes[node.name]
if (def and def.walkable) or not def then if (def and def.walkable) or not def then
if not minetest.settings:get_bool("creative_mode") then if not minetest.settings:get_bool("creative_mode") then
minetest.add_item(self._lastpos, 'mcl_throwing:arrow') minetest.add_item(self._lastpos, 'mcl_bows:arrow')
end end
self.object:remove() self.object:remove()
end end
@ -142,11 +142,11 @@ THROWING_ARROW_ENTITY.on_step = function(self, dtime)
self._lastpos={x=pos.x, y=pos.y, z=pos.z} self._lastpos={x=pos.x, y=pos.y, z=pos.z}
end end
minetest.register_entity("mcl_throwing:arrow_entity", THROWING_ARROW_ENTITY) minetest.register_entity("mcl_bows:arrow_entity", THROWING_ARROW_ENTITY)
if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then
minetest.register_craft({ minetest.register_craft({
output = 'mcl_throwing:arrow 4', output = 'mcl_bows:arrow 4',
recipe = { recipe = {
{'mcl_core:flint'}, {'mcl_core:flint'},
{'mcl_core:stick'}, {'mcl_core:stick'},

View file

@ -1,7 +1,7 @@
mcl_throwing = {} mcl_bows = {}
local arrows = { local arrows = {
["mcl_throwing:arrow"] = "mcl_throwing:arrow_entity", ["mcl_bows:arrow"] = "mcl_bows:arrow_entity",
} }
local GRAVITY = 9.81 local GRAVITY = 9.81
@ -31,7 +31,7 @@ local bow_load = {}
-- Another player table, this one stores the wield index of the bow being charged -- Another player table, this one stores the wield index of the bow being charged
local bow_index = {} local bow_index = {}
mcl_throwing.shoot_arrow = function(arrow_item, pos, dir, yaw, shooter, power, damage) mcl_bows.shoot_arrow = function(arrow_item, pos, dir, yaw, shooter, power, damage)
local obj = minetest.add_entity({x=pos.x,y=pos.y,z=pos.z}, arrows[arrow_item]) local obj = minetest.add_entity({x=pos.x,y=pos.y,z=pos.z}, arrows[arrow_item])
if power == nil then if power == nil then
power = 19 power = 19
@ -46,7 +46,7 @@ mcl_throwing.shoot_arrow = function(arrow_item, pos, dir, yaw, shooter, power, d
le._shooter = shooter le._shooter = shooter
le._damage = damage le._damage = damage
le._startpos = pos le._startpos = pos
minetest.sound_play("mcl_throwing_bow_shoot", {pos=pos}) minetest.sound_play("mcl_bows_bow_shoot", {pos=pos})
if shooter ~= nil then if shooter ~= nil then
if obj:get_luaentity().player == "" then if obj:get_luaentity().player == "" then
obj:get_luaentity().player = shooter obj:get_luaentity().player = shooter
@ -87,20 +87,20 @@ local player_shoot_arrow = function(itemstack, player, power, damage)
local yaw = player:get_look_horizontal() local yaw = player:get_look_horizontal()
if not arrow_itemstring then if not arrow_itemstring then
arrow_itemstring = "mcl_throwing:arrow" arrow_itemstring = "mcl_bows:arrow"
end end
mcl_throwing.shoot_arrow(arrow_itemstring, {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, dir, yaw, player, power, damage) mcl_bows.shoot_arrow(arrow_itemstring, {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, dir, yaw, player, power, damage)
return true return true
end end
-- Bow item, uncharged state -- Bow item, uncharged state
minetest.register_tool("mcl_throwing:bow", { minetest.register_tool("mcl_bows:bow", {
description = "Bow", description = "Bow",
_doc_items_longdesc = [[Bows are ranged weapons to shoot arrows at your foes. _doc_items_longdesc = [[Bows are ranged weapons to shoot arrows at your foes.
The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead.]], The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead.]],
_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.]], _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.]],
_doc_items_durability = BOW_DURABILITY, _doc_items_durability = BOW_DURABILITY,
inventory_image = "mcl_throwing_bow.png", inventory_image = "mcl_bows_bow.png",
stack_max = 1, stack_max = 1,
-- Trick to disable melee damage to entities. -- Trick to disable melee damage to entities.
-- Range not set to 0 (unlike the others) so it can be placed into item frames -- Range not set to 0 (unlike the others) so it can be placed into item frames
@ -115,8 +115,8 @@ local reset_bows = function(player)
local inv = player:get_inventory() local inv = player:get_inventory()
local list = inv:get_list("main") local list = inv:get_list("main")
for place, stack in pairs(list) do for place, stack in pairs(list) do
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 if stack:get_name()=="mcl_bows:bow_0" or stack:get_name()=="mcl_bows:bow_1" or stack:get_name()=="mcl_bows:bow_2" then
stack:set_name("mcl_throwing:bow") stack:set_name("mcl_bows:bow")
list[place] = stack list[place] = stack
end end
end end
@ -137,16 +137,16 @@ end
-- Bow in charging state -- Bow in charging state
for level=0, 2 do for level=0, 2 do
minetest.register_tool("mcl_throwing:bow_"..level, { minetest.register_tool("mcl_bows:bow_"..level, {
description = "Bow", description = "Bow",
_doc_items_create_entry = false, _doc_items_create_entry = false,
inventory_image = "mcl_throwing_bow_"..level..".png", inventory_image = "mcl_bows_bow_"..level..".png",
stack_max = 1, stack_max = 1,
range = 0, -- Pointing range to 0 to prevent punching with bow :D range = 0, -- Pointing range to 0 to prevent punching with bow :D
groups = {not_in_creative_inventory=1, not_in_craft_guide=1}, groups = {not_in_creative_inventory=1, not_in_craft_guide=1},
on_drop = function(itemstack, dropper, pos) on_drop = function(itemstack, dropper, pos)
reset_bow_state(player) reset_bow_state(player)
itemstack:set_name("mcl_throwing:bow") itemstack:set_name("mcl_bows:bow")
minetest.item_drop(itemstack, dropper, pos) minetest.item_drop(itemstack, dropper, pos)
itemstack:take_item() itemstack:take_item()
return itemstack return itemstack
@ -159,7 +159,7 @@ controls.register_on_release(function(player, key, time)
if key~="RMB" then return end if key~="RMB" then return end
local inv = minetest.get_inventory({type="player", name=player:get_player_name()}) local inv = minetest.get_inventory({type="player", name=player:get_player_name()})
local wielditem = player:get_wielded_item() local wielditem = player:get_wielded_item()
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 if (wielditem:get_name()=="mcl_bows:bow_0" or wielditem:get_name()=="mcl_bows:bow_1" or wielditem:get_name()=="mcl_bows:bow_2") then
local has_shot = false local has_shot = false
local speed, damage local speed, damage
@ -172,7 +172,7 @@ controls.register_on_release(function(player, key, time)
-- In case something goes wrong ... -- In case something goes wrong ...
-- Just assume minimum charge. -- Just assume minimum charge.
charge = 0 charge = 0
minetest.log("warning", "[mcl_throwing] Player "..player:get_player_name().." fires arrow with non-numeric bow_load!") minetest.log("warning", "[mcl_bows] Player "..player:get_player_name().." fires arrow with non-numeric bow_load!")
end end
charge = math.max(math.min(charge, BOW_CHARGE_TIME_FULL), 0) charge = math.max(math.min(charge, BOW_CHARGE_TIME_FULL), 0)
@ -199,7 +199,7 @@ controls.register_on_release(function(player, key, time)
has_shot = player_shoot_arrow(wielditem, player, speed, damage) has_shot = player_shoot_arrow(wielditem, player, speed, damage)
wielditem:set_name("mcl_throwing:bow") wielditem:set_name("mcl_bows:bow")
if has_shot and minetest.settings:get_bool("creative_mode") == false then if has_shot and minetest.settings:get_bool("creative_mode") == false then
wielditem:add_wear(65535/BOW_DURABILITY) wielditem:add_wear(65535/BOW_DURABILITY)
end end
@ -215,8 +215,8 @@ controls.register_on_hold(function(player, key, time)
local name = player:get_player_name() local name = player:get_player_name()
local inv = minetest.get_inventory({type="player", name=name}) local inv = minetest.get_inventory({type="player", name=name})
local wielditem = player:get_wielded_item() local wielditem = player:get_wielded_item()
if bow_load[name] == nil and wielditem:get_name()=="mcl_throwing:bow" and (minetest.settings:get_bool("creative_mode") or inv:contains_item("main", "mcl_throwing:arrow")) then if bow_load[name] == nil and wielditem:get_name()=="mcl_bows:bow" and (minetest.settings:get_bool("creative_mode") or inv:contains_item("main", "mcl_bows:arrow")) then
wielditem:set_name("mcl_throwing:bow_0") wielditem:set_name("mcl_bows:bow_0")
player:set_wielded_item(wielditem) player:set_wielded_item(wielditem)
if minetest.get_modpath("mcl_playerphysics") then if minetest.get_modpath("mcl_playerphysics") then
-- Slow player down when using bow -- Slow player down when using bow
@ -227,14 +227,14 @@ controls.register_on_hold(function(player, key, time)
else else
if player:get_wield_index() == bow_index[name] then if player:get_wield_index() == bow_index[name] then
if type(bow_load[name]) == "number" then if type(bow_load[name]) == "number" then
if wielditem:get_name() == "mcl_throwing:bow_0" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_HALF then if wielditem:get_name() == "mcl_bows:bow_0" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_HALF then
wielditem:set_name("mcl_throwing:bow_1") wielditem:set_name("mcl_bows:bow_1")
elseif wielditem:get_name() == "mcl_throwing:bow_1" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_FULL then elseif wielditem:get_name() == "mcl_bows:bow_1" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_FULL then
wielditem:set_name("mcl_throwing:bow_2") wielditem:set_name("mcl_bows:bow_2")
end end
else else
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 if wielditem:get_name() == "mcl_bows:bow_0" or wielditem:get_name() == "mcl_bows:bow_1" or wielditem:get_name() == "mcl_bows:bow_2" then
wielditem:set_name("mcl_throwing:bow") wielditem:set_name("mcl_bows:bow")
end end
end end
player:set_wielded_item(wielditem) player:set_wielded_item(wielditem)
@ -250,7 +250,7 @@ minetest.register_globalstep(function(dtime)
local wielditem = player:get_wielded_item() local wielditem = player:get_wielded_item()
local wieldindex = player:get_wield_index() local wieldindex = player:get_wield_index()
local controls = player:get_player_control() local controls = player:get_player_control()
if type(bow_load[name]) == "number" and ((wielditem:get_name()~="mcl_throwing:bow_0" and wielditem:get_name()~="mcl_throwing:bow_1" and wielditem:get_name()~="mcl_throwing:bow_2") or wieldindex ~= bow_index[name]) then if type(bow_load[name]) == "number" and ((wielditem:get_name()~="mcl_bows:bow_0" and wielditem:get_name()~="mcl_bows:bow_1" and wielditem:get_name()~="mcl_bows:bow_2") or wieldindex ~= bow_index[name]) then
reset_bow_state(player, true) reset_bow_state(player, true)
end end
end end
@ -266,7 +266,7 @@ end)
if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then
minetest.register_craft({ minetest.register_craft({
output = 'mcl_throwing:bow', output = 'mcl_bows:bow',
recipe = { recipe = {
{'', 'mcl_core:stick', 'mcl_mobitems:string'}, {'', 'mcl_core:stick', 'mcl_mobitems:string'},
{'mcl_core:stick', '', 'mcl_mobitems:string'}, {'mcl_core:stick', '', 'mcl_mobitems:string'},
@ -274,7 +274,7 @@ if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") the
} }
}) })
minetest.register_craft({ minetest.register_craft({
output = 'mcl_throwing:bow', output = 'mcl_bows:bow',
recipe = { recipe = {
{'mcl_mobitems:string', 'mcl_core:stick', ''}, {'mcl_mobitems:string', 'mcl_core:stick', ''},
{'mcl_mobitems:string', '', 'mcl_core:stick'}, {'mcl_mobitems:string', '', 'mcl_core:stick'},
@ -285,15 +285,15 @@ end
minetest.register_craft({ minetest.register_craft({
type = "fuel", type = "fuel",
recipe = "mcl_throwing:bow", recipe = "mcl_bows:bow",
burntime = 15, burntime = 15,
}) })
-- Add entry aliases for the Help -- Add entry aliases for the Help
if minetest.get_modpath("doc") then if minetest.get_modpath("doc") then
doc.add_entry_alias("tools", "mcl_throwing:bow", "tools", "mcl_throwing:bow_0") doc.add_entry_alias("tools", "mcl_bows:bow", "tools", "mcl_bows:bow_0")
doc.add_entry_alias("tools", "mcl_throwing:bow", "tools", "mcl_throwing:bow_1") doc.add_entry_alias("tools", "mcl_bows:bow", "tools", "mcl_bows:bow_1")
doc.add_entry_alias("tools", "mcl_throwing:bow", "tools", "mcl_throwing:bow_2") doc.add_entry_alias("tools", "mcl_bows:bow", "tools", "mcl_bows:bow_2")
end end

View file

@ -0,0 +1,8 @@
controls
awards?
mcl_achievements?
mcl_hunger?
mcl_core?
mcl_mobitems?
mcl_playerphysics?
doc?

View file

@ -0,0 +1,5 @@
dofile(minetest.get_modpath("mcl_bows") .. "/arrow.lua")
dofile(minetest.get_modpath("mcl_bows") .. "/bow.lua")
minetest.register_alias("mcl_throwing:bow", "mcl_bows:bow")
minetest.register_alias("mcl_throwing:arrow", "mcl_bows:arrow")

View file

Before

Width:  |  Height:  |  Size: 184 B

After

Width:  |  Height:  |  Size: 184 B

View file

Before

Width:  |  Height:  |  Size: 124 B

After

Width:  |  Height:  |  Size: 124 B

View file

Before

Width:  |  Height:  |  Size: 113 B

After

Width:  |  Height:  |  Size: 113 B

View file

Before

Width:  |  Height:  |  Size: 245 B

After

Width:  |  Height:  |  Size: 245 B

View file

Before

Width:  |  Height:  |  Size: 206 B

After

Width:  |  Height:  |  Size: 206 B

View file

Before

Width:  |  Height:  |  Size: 231 B

After

Width:  |  Height:  |  Size: 231 B

View file

Before

Width:  |  Height:  |  Size: 227 B

After

Width:  |  Height:  |  Size: 227 B

View file

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 225 B

View file

@ -1,5 +1,4 @@
mcl_sounds mcl_sounds
mcl_throwing
mcl_util mcl_util
doc_items doc_items
mcl_worlds mcl_worlds

View file

@ -47,7 +47,7 @@ local go_fishing = function(itemstack, user, pointed_thing)
items = mcl_loot.get_loot({ items = mcl_loot.get_loot({
items = { items = {
-- TODO: Enchanted Bow -- TODO: Enchanted Bow
{ itemstring = "mcl_throwing:bow", wear_min = 49144, wear_max = 65535 }, -- 75%-100% damage { itemstring = "mcl_bows:bow", wear_min = 49144, wear_max = 65535 }, -- 75%-100% damage
-- TODO: Enchanted Book -- TODO: Enchanted Book
{ itemstring = "mcl_books:book" }, { itemstring = "mcl_books:book" },
-- TODO: Enchanted Fishing Rod -- TODO: Enchanted Fishing Rod

View file

@ -1,8 +1,3 @@
controls
awards?
mcl_achievements?
mcl_hunger?
mcl_core? mcl_core?
mcl_mobitems? mcl_mobitems?
mcl_playerphysics?
doc? doc?

View file

@ -1,6 +1,324 @@
mcl_throwing = {} mcl_throwing = {}
dofile(minetest.get_modpath("mcl_throwing").."/arrow.lua") --
dofile(minetest.get_modpath("mcl_throwing").."/bow.lua") -- Snowballs and other throwable items
dofile(minetest.get_modpath("mcl_throwing").."/throwable.lua") --
local GRAVITY = tonumber(minetest.settings:get("movement_gravity"))
local entity_mapping = {
["mcl_throwing:snowball"] = "mcl_throwing:snowball_entity",
["mcl_throwing:egg"] = "mcl_throwing:egg_entity",
["mcl_throwing:ender_pearl"] = "mcl_throwing:ender_pearl_entity",
}
local velocities = {
["mcl_throwing:snowball_entity"] = 22,
["mcl_throwing:egg_entity"] = 22,
["mcl_throwing:ender_pearl_entity"] = 22,
}
mcl_throwing.throw = function(throw_item, pos, dir, velocity)
if velocity == nil then
velocity = velocities[throw_item]
end
if velocity == nil then
velocity = 22
end
local itemstring = ItemStack(throw_item):get_name()
local obj = minetest.add_entity(pos, entity_mapping[itemstring])
obj:setvelocity({x=dir.x*velocity, y=dir.y*velocity, z=dir.z*velocity})
obj:setacceleration({x=dir.x*-3, y=-GRAVITY, z=dir.z*-3})
return obj
end
-- Throw item
local throw_function = function(entity_name, velocity)
local func = function(item, player, pointed_thing)
local playerpos = player:get_pos()
local dir = player:get_look_dir()
local obj = mcl_throwing.throw(item, {x=playerpos.x, y=playerpos.y+1.5, z=playerpos.z}, dir, velocity)
obj:get_luaentity()._thrower = player:get_player_name()
if not minetest.settings:get_bool("creative_mode") then
item:take_item()
end
return item
end
return func
end
local dispense_function = function(stack, dispenserpos, droppos, dropnode, dropdir)
-- Launch throwable item
local shootpos = vector.add(dispenserpos, vector.multiply(dropdir, 0.51))
mcl_throwing.throw(stack:get_name(), shootpos, dropdir)
end
-- Staticdata handling because objects may want to be reloaded
local get_staticdata = function(self)
local data = {
_lastpos = self._lastpos,
_thrower = self._thrower,
}
return minetest.serialize(data)
end
local on_activate = function(self, staticdata, dtime_s)
local data = minetest.deserialize(staticdata)
if data then
self._lastpos = data._lastpos
self._thrower = data._thrower
end
end
-- The snowball entity
local snowball_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_snowball.png"},
visual_size = {x=0.5, y=0.5},
collisionbox = {0,0,0,0,0,0},
get_staticdata = get_staticdata,
on_activate = on_activate,
_lastpos={},
}
local egg_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_egg.png"},
visual_size = {x=0.45, y=0.45},
collisionbox = {0,0,0,0,0,0},
get_staticdata = get_staticdata,
on_activate = on_activate,
_lastpos={},
}
-- Ender pearl entity
local pearl_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_ender_pearl.png"},
visual_size = {x=0.9, y=0.9},
collisionbox = {0,0,0,0,0,0},
get_staticdata = get_staticdata,
on_activate = on_activate,
_lastpos={},
_thrower = nil, -- Player ObjectRef of the player who threw the ender pearl
}
-- Snowball on_step()--> called when snowball is moving.
local snowball_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:getpos()
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
if (def and def.walkable) or not def then
self.object:remove()
return
end
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set _lastpos-->Node will be added at last pos outside the node
end
-- Movement function of egg
local egg_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:getpos()
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
if (def and def.walkable) or not def then
-- 1/8 chance to spawn a chick
-- FIXME: Chicks have a quite good chance to spawn in walls
local r = math.random(1,8)
-- Turn given object into a child
local make_child= function(object)
local ent = object:get_luaentity()
object:set_properties({
visual_size = { x = ent.base_size.x/2, y = ent.base_size.y/2 },
collisionbox = {
ent.base_colbox[1]/2,
ent.base_colbox[2]/2,
ent.base_colbox[3]/2,
ent.base_colbox[4]/2,
ent.base_colbox[5]/2,
ent.base_colbox[6]/2,
}
})
ent.child = true
end
if r == 1 then
make_child(minetest.add_entity(self._lastpos, "mobs_mc:chicken"))
-- BONUS ROUND: 1/32 chance to spawn 3 additional chicks
local r = math.random(1,32)
if r == 1 then
local offsets = {
{ x=0.7, y=0, z=0 },
{ x=-0.7, y=0, z=-0.7 },
{ x=-0.7, y=0, z=0.7 },
}
for o=1, 3 do
local pos = vector.add(self._lastpos, offsets[o])
make_child(minetest.add_entity(pos, "mobs_mc:chicken"))
end
end
end
self.object:remove()
return
end
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
end
-- Movement function of ender pearl
local pearl_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:getpos()
pos.y = math.floor(pos.y)
local node = minetest.get_node(pos)
local nn = node.name
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
local walkable = (def and def.walkable)
-- No teleport for hitting ignore for now. Otherwise the player could get stuck.
-- FIXME: This also means the player loses an ender pearl for throwing into unloaded areas
if node.name == "ignore" then
self.object:remove()
-- Activate when hitting a solid node or a plant
elseif walkable or nn == "mcl_core:vine" or nn == "mcl_core:deadbush" or minetest.get_item_group(nn, "flower") ~= 0 or minetest.get_item_group(nn, "sapling") ~= 0 or minetest.get_item_group(nn, "plant") ~= 0 or minetest.get_item_group(nn, "mushroom") ~= 0 or not def then
local player = minetest.get_player_by_name(self._thrower)
if player then
-- Teleport and hurt player
-- First determine good teleport position
local dir = {x=0, y=0, z=0}
local v = self.object:getvelocity()
if walkable then
local vc = table.copy(v) -- vector for calculating
-- Node is walkable, we have to find a place somewhere outside of that node
vc = vector.normalize(vc)
-- Zero-out the two axes with a lower absolute value than
-- the axis with the strongest force
local lv, ld
lv, ld = math.abs(vc.y), "y"
if math.abs(vc.x) > lv then
lv, ld = math.abs(vc.x), "x"
end
if math.abs(vc.z) > lv then
lv, ld = math.abs(vc.z), "z"
end
if ld ~= "x" then vc.x = 0 end
if ld ~= "y" then vc.y = 0 end
if ld ~= "z" then vc.z = 0 end
-- Final tweaks to the teleporting pos, based on direction
-- Impact from the side
dir.x = vc.x * -1
dir.z = vc.z * -1
-- Special case: top or bottom of node
if vc.y > 0 then
-- We need more space when impact is from below
dir.y = -2.3
elseif vc.y < 0 then
-- Standing on top
dir.y = 0.5
end
end
-- If node was not walkable, no modification to pos is made.
-- Final teleportation position
local telepos = vector.add(pos, dir)
local telenode = minetest.get_node(telepos)
--[[ It may be possible that telepos is walkable due to the algorithm.
Especially when the ender pearl is faster horizontally than vertical.
This applies final fixing, just to be sure we're not in a walkable node ]]
if not minetest.registered_nodes[telenode.name] or minetest.registered_nodes[telenode.name].walkable then
if v.y < 0 then
telepos.y = telepos.y + 0.5
else
telepos.y = telepos.y - 2.3
end
end
local oldpos = player:getpos()
-- Teleport and hurt player
player:setpos(telepos)
player:set_hp(player:get_hp() - 5)
-- 5% chance to spawn endermite at the player's origin
local r = math.random(1,20)
if r == 1 then
minetest.add_entity(oldpos, "mobs_mc:endermite")
end
end
self.object:remove()
return
end
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
end
snowball_ENTITY.on_step = snowball_on_step
egg_ENTITY.on_step = egg_on_step
pearl_ENTITY.on_step = pearl_on_step
minetest.register_entity("mcl_throwing:snowball_entity", snowball_ENTITY)
minetest.register_entity("mcl_throwing:egg_entity", egg_ENTITY)
minetest.register_entity("mcl_throwing:ender_pearl_entity", pearl_ENTITY)
local how_to_throw = "Hold it in your and and leftclick to throw."
-- Snowball
minetest.register_craftitem("mcl_throwing:snowball", {
description = "Snowball",
_doc_items_longdesc = "Snowballs can be thrown or launched from a dispenser for fun. Hitting something with a snowball does nothing.",
_doc_items_usagehelp = how_to_throw,
inventory_image = "mcl_throwing_snowball.png",
stack_max = 16,
on_use = throw_function("mcl_throwing:snowball_entity"),
_on_dispense = dispense_function,
})
-- Egg
minetest.register_craftitem("mcl_throwing:egg", {
description = "Egg",
_doc_items_longdesc = "Eggs can be thrown or launched from a dispenser and breaks on impact. There is a small chance that 1 or even 4 chickens will pop out of the egg when it hits the ground.",
_doc_items_usagehelp = how_to_throw,
inventory_image = "mcl_throwing_egg.png",
stack_max = 16,
on_use = throw_function("mcl_throwing:egg_entity"),
_on_dispense = dispense_function,
groups = { craftitem = 1 },
})
-- Ender Pearl
minetest.register_craftitem("mcl_throwing:ender_pearl", {
description = "Ender Pearl",
_doc_items_longdesc = "An ender pearl is an item which can be used for teleportation at the cost of health. It can be thrown and teleport the thrower to its impact location when it hits a solid block, a plant or vines. Each teleportation hurts the user by 5 hit points.",
_doc_items_usagehelp = how_to_throw,
wield_image = "mcl_throwing_ender_pearl.png",
inventory_image = "mcl_throwing_ender_pearl.png",
stack_max = 16,
on_use = throw_function("mcl_throwing:ender_pearl_entity"),
})

View file

@ -1,322 +0,0 @@
--
-- Snowballs and other throwable items
--
local GRAVITY = tonumber(minetest.settings:get("movement_gravity"))
local entity_mapping = {
["mcl_throwing:snowball"] = "mcl_throwing:snowball_entity",
["mcl_throwing:egg"] = "mcl_throwing:egg_entity",
["mcl_throwing:ender_pearl"] = "mcl_throwing:ender_pearl_entity",
}
local velocities = {
["mcl_throwing:snowball_entity"] = 22,
["mcl_throwing:egg_entity"] = 22,
["mcl_throwing:ender_pearl_entity"] = 22,
}
mcl_throwing.throw = function(throw_item, pos, dir, velocity)
if velocity == nil then
velocity = velocities[throw_item]
end
if velocity == nil then
velocity = 22
end
local itemstring = ItemStack(throw_item):get_name()
local obj = minetest.add_entity(pos, entity_mapping[itemstring])
obj:setvelocity({x=dir.x*velocity, y=dir.y*velocity, z=dir.z*velocity})
obj:setacceleration({x=dir.x*-3, y=-GRAVITY, z=dir.z*-3})
return obj
end
-- Throw item
local throw_function = function(entity_name, velocity)
local func = function(item, player, pointed_thing)
local playerpos = player:get_pos()
local dir = player:get_look_dir()
local obj = mcl_throwing.throw(item, {x=playerpos.x, y=playerpos.y+1.5, z=playerpos.z}, dir, velocity)
obj:get_luaentity()._thrower = player:get_player_name()
if not minetest.settings:get_bool("creative_mode") then
item:take_item()
end
return item
end
return func
end
local dispense_function = function(stack, dispenserpos, droppos, dropnode, dropdir)
-- Launch throwable item
local shootpos = vector.add(dispenserpos, vector.multiply(dropdir, 0.51))
mcl_throwing.throw(stack:get_name(), shootpos, dropdir)
end
-- Staticdata handling because objects may want to be reloaded
local get_staticdata = function(self)
local data = {
_lastpos = self._lastpos,
_thrower = self._thrower,
}
return minetest.serialize(data)
end
local on_activate = function(self, staticdata, dtime_s)
local data = minetest.deserialize(staticdata)
if data then
self._lastpos = data._lastpos
self._thrower = data._thrower
end
end
-- The snowball entity
local snowball_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_snowball.png"},
visual_size = {x=0.5, y=0.5},
collisionbox = {0,0,0,0,0,0},
get_staticdata = get_staticdata,
on_activate = on_activate,
_lastpos={},
}
local egg_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_egg.png"},
visual_size = {x=0.45, y=0.45},
collisionbox = {0,0,0,0,0,0},
get_staticdata = get_staticdata,
on_activate = on_activate,
_lastpos={},
}
-- Ender pearl entity
local pearl_ENTITY={
physical = false,
timer=0,
textures = {"mcl_throwing_ender_pearl.png"},
visual_size = {x=0.9, y=0.9},
collisionbox = {0,0,0,0,0,0},
get_staticdata = get_staticdata,
on_activate = on_activate,
_lastpos={},
_thrower = nil, -- Player ObjectRef of the player who threw the ender pearl
}
-- Snowball on_step()--> called when snowball is moving.
local snowball_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:getpos()
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
if (def and def.walkable) or not def then
self.object:remove()
return
end
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set _lastpos-->Node will be added at last pos outside the node
end
-- Movement function of egg
local egg_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:getpos()
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
if (def and def.walkable) or not def then
-- 1/8 chance to spawn a chick
-- FIXME: Chicks have a quite good chance to spawn in walls
local r = math.random(1,8)
-- Turn given object into a child
local make_child= function(object)
local ent = object:get_luaentity()
object:set_properties({
visual_size = { x = ent.base_size.x/2, y = ent.base_size.y/2 },
collisionbox = {
ent.base_colbox[1]/2,
ent.base_colbox[2]/2,
ent.base_colbox[3]/2,
ent.base_colbox[4]/2,
ent.base_colbox[5]/2,
ent.base_colbox[6]/2,
}
})
ent.child = true
end
if r == 1 then
make_child(minetest.add_entity(self._lastpos, "mobs_mc:chicken"))
-- BONUS ROUND: 1/32 chance to spawn 3 additional chicks
local r = math.random(1,32)
if r == 1 then
local offsets = {
{ x=0.7, y=0, z=0 },
{ x=-0.7, y=0, z=-0.7 },
{ x=-0.7, y=0, z=0.7 },
}
for o=1, 3 do
local pos = vector.add(self._lastpos, offsets[o])
make_child(minetest.add_entity(pos, "mobs_mc:chicken"))
end
end
end
self.object:remove()
return
end
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
end
-- Movement function of ender pearl
local pearl_on_step = function(self, dtime)
self.timer=self.timer+dtime
local pos = self.object:getpos()
pos.y = math.floor(pos.y)
local node = minetest.get_node(pos)
local nn = node.name
local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node
if self._lastpos.x~=nil then
local walkable = (def and def.walkable)
-- No teleport for hitting ignore for now. Otherwise the player could get stuck.
-- FIXME: This also means the player loses an ender pearl for throwing into unloaded areas
if node.name == "ignore" then
self.object:remove()
-- Activate when hitting a solid node or a plant
elseif walkable or nn == "mcl_core:vine" or nn == "mcl_core:deadbush" or minetest.get_item_group(nn, "flower") ~= 0 or minetest.get_item_group(nn, "sapling") ~= 0 or minetest.get_item_group(nn, "plant") ~= 0 or minetest.get_item_group(nn, "mushroom") ~= 0 or not def then
local player = minetest.get_player_by_name(self._thrower)
if player then
-- Teleport and hurt player
-- First determine good teleport position
local dir = {x=0, y=0, z=0}
local v = self.object:getvelocity()
if walkable then
local vc = table.copy(v) -- vector for calculating
-- Node is walkable, we have to find a place somewhere outside of that node
vc = vector.normalize(vc)
-- Zero-out the two axes with a lower absolute value than
-- the axis with the strongest force
local lv, ld
lv, ld = math.abs(vc.y), "y"
if math.abs(vc.x) > lv then
lv, ld = math.abs(vc.x), "x"
end
if math.abs(vc.z) > lv then
lv, ld = math.abs(vc.z), "z"
end
if ld ~= "x" then vc.x = 0 end
if ld ~= "y" then vc.y = 0 end
if ld ~= "z" then vc.z = 0 end
-- Final tweaks to the teleporting pos, based on direction
-- Impact from the side
dir.x = vc.x * -1
dir.z = vc.z * -1
-- Special case: top or bottom of node
if vc.y > 0 then
-- We need more space when impact is from below
dir.y = -2.3
elseif vc.y < 0 then
-- Standing on top
dir.y = 0.5
end
end
-- If node was not walkable, no modification to pos is made.
-- Final teleportation position
local telepos = vector.add(pos, dir)
local telenode = minetest.get_node(telepos)
--[[ It may be possible that telepos is walkable due to the algorithm.
Especially when the ender pearl is faster horizontally than vertical.
This applies final fixing, just to be sure we're not in a walkable node ]]
if not minetest.registered_nodes[telenode.name] or minetest.registered_nodes[telenode.name].walkable then
if v.y < 0 then
telepos.y = telepos.y + 0.5
else
telepos.y = telepos.y - 2.3
end
end
local oldpos = player:getpos()
-- Teleport and hurt player
player:setpos(telepos)
player:set_hp(player:get_hp() - 5)
-- 5% chance to spawn endermite at the player's origin
local r = math.random(1,20)
if r == 1 then
minetest.add_entity(oldpos, "mobs_mc:endermite")
end
end
self.object:remove()
return
end
end
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
end
snowball_ENTITY.on_step = snowball_on_step
egg_ENTITY.on_step = egg_on_step
pearl_ENTITY.on_step = pearl_on_step
minetest.register_entity("mcl_throwing:snowball_entity", snowball_ENTITY)
minetest.register_entity("mcl_throwing:egg_entity", egg_ENTITY)
minetest.register_entity("mcl_throwing:ender_pearl_entity", pearl_ENTITY)
local how_to_throw = "Hold it in your and and leftclick to throw."
-- Snowball
minetest.register_craftitem("mcl_throwing:snowball", {
description = "Snowball",
_doc_items_longdesc = "Snowballs can be thrown or launched from a dispenser for fun. Hitting something with a snowball does nothing.",
_doc_items_usagehelp = how_to_throw,
inventory_image = "mcl_throwing_snowball.png",
stack_max = 16,
on_use = throw_function("mcl_throwing:snowball_entity"),
_on_dispense = dispense_function,
})
-- Egg
minetest.register_craftitem("mcl_throwing:egg", {
description = "Egg",
_doc_items_longdesc = "Eggs can be thrown or launched from a dispenser and breaks on impact. There is a small chance that 1 or even 4 chickens will pop out of the egg when it hits the ground.",
_doc_items_usagehelp = how_to_throw,
inventory_image = "mcl_throwing_egg.png",
stack_max = 16,
on_use = throw_function("mcl_throwing:egg_entity"),
_on_dispense = dispense_function,
groups = { craftitem = 1 },
})
-- Ender Pearl
minetest.register_craftitem("mcl_throwing:ender_pearl", {
description = "Ender Pearl",
_doc_items_longdesc = "An ender pearl is an item which can be used for teleportation at the cost of health. It can be thrown and teleport the thrower to its impact location when it hits a solid block, a plant or vines. Each teleportation hurts the user by 5 hit points.",
_doc_items_usagehelp = how_to_throw,
wield_image = "mcl_throwing_ender_pearl.png",
inventory_image = "mcl_throwing_ender_pearl.png",
stack_max = 16,
on_use = throw_function("mcl_throwing:ender_pearl_entity"),
})