2021-10-15 21:00:37 +02:00
local S = minetest.get_translator ( minetest.get_current_modname ( ) )
local math = math
local vector = vector
-- Time in seconds after which a stuck arrow is deleted
2024-08-31 13:41:42 +02:00
local ROCKET_TIMEOUT = 1
2021-10-15 21:00:37 +02:00
local YAW_OFFSET = - math.pi / 2
2024-12-30 19:13:00 +01:00
local particle_explosion = vl_fireworks.generic_particle_explosion
2024-12-22 04:37:18 +01:00
2024-09-28 01:49:25 +02:00
local function damage_explosion ( self , damagemulitplier , pos )
2022-11-18 07:26:44 +01:00
if self._harmless then return end
2024-08-31 13:41:42 +02:00
2024-09-28 01:49:25 +02:00
local p = pos or self.object : get_pos ( )
2022-09-13 02:39:11 +02:00
if not p then return end
2022-06-04 16:33:18 +02:00
mcl_explosions.explode ( p , 3 , { } )
2024-12-05 15:47:52 +01:00
local objects = core.get_objects_inside_radius ( p , 8 )
2021-10-15 21:00:37 +02:00
for _ , obj in pairs ( objects ) do
if obj : is_player ( ) then
2022-06-04 16:33:18 +02:00
mcl_util.deal_damage ( obj , damagemulitplier - vector.distance ( p , obj : get_pos ( ) ) , { type = " explosion " } )
2024-02-04 18:42:13 +01:00
elseif obj : get_luaentity ( ) and obj : get_luaentity ( ) . is_mob then
2021-10-15 21:00:37 +02:00
obj : punch ( self.object , 1.0 , {
full_punch_interval = 1.0 ,
2022-06-04 16:33:18 +02:00
damage_groups = { fleshy = damagemulitplier - vector.distance ( p , obj : get_pos ( ) ) } ,
2024-02-04 18:42:13 +01:00
} , self.object : get_velocity ( ) ) -- TODO possibly change the punch dir to be outwards instead of rocket velocity
2021-10-15 21:00:37 +02:00
end
end
end
2024-12-05 15:47:52 +01:00
core.register_craftitem ( " mcl_bows:rocket " , {
2021-10-15 21:00:37 +02:00
description = S ( " Arrow " ) ,
_tt_help = S ( " Ammunition " ) .. " \n " .. S ( " Damage from bow: 1-10 " ) .. " \n " .. S ( " Damage from dispenser: 3 " ) ,
_doc_items_longdesc = S ( " Arrows are ammunition for bows and dispensers. " ) .. " \n " ..
2024-08-31 13:41:42 +02:00
S ( " 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. " ) .. " \n " ..
S ( " Arrows might get stuck on solid blocks and can be retrieved again. They are also capable of pushing wooden buttons. " ) ,
2021-10-15 21:00:37 +02:00
_doc_items_usagehelp = S ( " 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. To retrieve an arrow that sticks in a block, simply walk close to it. " ) ,
inventory_image = " mcl_bows_rocket.png " ,
2024-12-05 15:57:31 +01:00
groups = { ammo = 1 , ammo_crossbow = 1 , ammo_bow_regular = 1 } ,
2021-10-15 21:00:37 +02:00
_on_dispense = function ( itemstack , dispenserpos , droppos , dropnode , dropdir )
-- Shoot arrow
local shootpos = vector.add ( dispenserpos , vector.multiply ( dropdir , 0.51 ) )
local yaw = math.atan2 ( dropdir.z , dropdir.x ) + YAW_OFFSET
mcl_bows.shoot_arrow ( itemstack : get_name ( ) , shootpos , dropdir , yaw , nil , 19 , 3 )
end ,
2024-09-29 13:38:41 +02:00
_on_collide_with_entity = function ( self , _ , obj )
2024-08-31 13:41:42 +02:00
if self._in_player == false then
2024-09-28 01:49:25 +02:00
pos = self.object : get_pos ( )
2024-08-31 13:41:42 +02:00
obj : punch ( self.object , 1.0 , {
full_punch_interval = 1.0 ,
damage_groups = { fleshy = self._damage } ,
} , self.object : get_velocity ( ) )
2021-10-15 21:00:37 +02:00
2024-12-30 19:13:00 +01:00
if particle_explosion then
local eploded_particle = particle_explosion ( pos )
damage_explosion ( self , eploded_particle * 17 , pos )
end
2024-09-28 01:49:25 +02:00
mcl_burning.extinguish ( self.object )
2024-11-16 01:19:41 +01:00
mcl_util.remove_entity ( self )
2024-08-31 13:41:42 +02:00
end
end ,
} )
2021-10-15 21:00:37 +02:00
2024-08-31 13:41:42 +02:00
local arrow_entity = mcl_bows.arrow_entity
local rocket_entity = table.copy ( arrow_entity )
table.update ( rocket_entity , {
mesh = " mcl_bows_rocket.obj " ,
textures = { " mcl_bows_rocket.png " } ,
visual_size = { x = 2.5 , y = 2.5 } ,
save_fields = {
" stuck " , " fuse " , " stuckin " , " lastpos " , " startpos " , " damage " , " is_critical " , " shootername " ,
} ,
_fuse = nil , -- Amount of time (in seconds) the arrow has been stuck so far
_fuserechecktimer = nil , -- An additional timer for periodically re-checking the stuck status of an arrow
} )
rocket_entity.on_step = function ( self , dtime )
self._fuse = ( self._fuse or 0 ) + dtime
2021-10-15 21:00:37 +02:00
2024-08-31 13:41:42 +02:00
if self._fuse > ROCKET_TIMEOUT then
2021-10-15 21:00:37 +02:00
self._stuck = true
end
2024-08-31 13:41:42 +02:00
if self._stuck and self._fuse > ROCKET_TIMEOUT then
2024-12-30 19:13:00 +01:00
if particle_explosion then
local eploded_particle = particle_explosion ( self )
damage_explosion ( self , eploded_particle * 17 )
end
2024-08-31 13:41:42 +02:00
mcl_burning.extinguish ( self.object )
2024-11-16 01:19:41 +01:00
mcl_util.remove_entity ( self )
2024-08-31 13:41:42 +02:00
return
2021-10-15 21:00:37 +02:00
end
2024-11-14 03:59:07 +01:00
-- Perform normal projectile behaviors
vl_projectile.update_projectile ( self , dtime )
2021-10-15 21:00:37 +02:00
end
2024-08-31 13:41:42 +02:00
vl_projectile.register ( " mcl_bows:rocket_entity " , rocket_entity )
2021-10-15 21:00:37 +02:00
2024-12-30 19:13:00 +01:00
if core.get_modpath ( " mcl_core " ) and core.get_modpath ( " mcl_mobitems " ) and core.get_modpath ( " vl_fireworks " ) then
2024-12-05 15:47:52 +01:00
core.register_craft ( {
2021-10-15 21:00:37 +02:00
output = " mcl_bows:rocket 1 " ,
recipe = {
{ " mcl_core:paper " } ,
2024-12-24 22:53:31 +01:00
{ " vl_fireworks:rocket_2 " } ,
2021-10-15 21:00:37 +02:00
{ " mcl_bows:arrow " } ,
}
} )
end
if minetest.get_modpath ( " doc_identifier " ) then
doc.sub . identifier.register_object ( " mcl_bows:rocket_entity " , " craftitems " , " mcl_bows:rocket " )
end