2020-07-10 11:01:21 +00:00
local S = minetest.get_translator ( " mcl_potions " )
2020-06-18 11:43:50 +00:00
local lingering_image = function ( colorstring , opacity )
if not opacity then
opacity = 127
end
2020-07-05 21:36:18 +00:00
return " mcl_potions_splash_overlay.png^[colorize: " .. colorstring .. " : " .. tostring ( opacity ) .. " ^mcl_potions_lingering_bottle.png "
2020-06-18 11:43:50 +00:00
end
2020-06-27 00:32:03 +00:00
local lingering_effect_at = { }
2020-08-05 16:33:53 +00:00
local function add_lingering_effect ( pos , color , def , is_water )
2020-06-27 00:32:03 +00:00
2020-08-05 16:33:53 +00:00
lingering_effect_at [ pos ] = { color = color , timer = 30 , def = def , is_water = is_water }
2020-06-27 00:32:03 +00:00
2020-06-27 22:50:08 +00:00
end
2020-06-27 00:32:03 +00:00
2020-06-27 22:50:08 +00:00
local lingering_timer = 0
minetest.register_globalstep ( function ( dtime )
2020-06-27 00:32:03 +00:00
2020-06-27 22:50:08 +00:00
lingering_timer = lingering_timer + dtime
if lingering_timer >= 1 then
2020-06-27 00:32:03 +00:00
2020-06-27 22:50:08 +00:00
for pos , vals in pairs ( lingering_effect_at ) do
2020-06-27 00:32:03 +00:00
2020-06-27 22:50:08 +00:00
vals.timer = vals.timer - lingering_timer
local d = 4 * ( vals.timer / 30.0 )
2020-08-05 17:26:51 +00:00
local texture
if vals.is_water then
texture = " mcl_potions_droplet.png "
else
texture = " mcl_potions_sprite.png "
end
2020-06-27 22:50:08 +00:00
minetest.add_particlespawner ( {
2020-08-05 17:26:51 +00:00
amount = 10 * d ^ 2 ,
time = 1 ,
minpos = { x = pos.x - d , y = pos.y + 0.5 , z = pos.z - d } ,
maxpos = { x = pos.x + d , y = pos.y + 1 , z = pos.z + d } ,
minvel = { x =- 0.5 , y = 0 , z =- 0.5 } ,
maxvel = { x = 0.5 , y = 0.5 , z = 0.5 } ,
minacc = { x =- 0.2 , y = 0 , z =- 0.2 } ,
maxacc = { x = 0.2 , y = .05 , z = 0.2 } ,
minexptime = 1 ,
maxexptime = 2 ,
minsize = 2 ,
maxsize = 4 ,
collisiondetection = true ,
vertical = false ,
texture = texture .. " ^[colorize: " .. vals.color .. " :127 " ,
} )
-- Extinguish fire if water bottle
2020-08-05 16:33:53 +00:00
if vals.is_water then
2020-08-05 17:44:19 +00:00
if mcl_potions._extinguish_nearby_fire ( pos , d ) then
2020-08-05 17:53:14 +00:00
vals.timer = vals.timer - 3.25
2020-08-05 16:33:53 +00:00
end
end
-- Affect players and mobs
2020-06-27 22:50:08 +00:00
for _ , obj in pairs ( minetest.get_objects_inside_radius ( pos , d ) ) do
2020-06-27 01:27:17 +00:00
2020-06-27 22:50:08 +00:00
local entity = obj : get_luaentity ( )
if obj : is_player ( ) or entity._cmi_is_mob then
2020-06-27 00:32:03 +00:00
2020-06-27 22:50:08 +00:00
vals.def . potion_fun ( obj )
2020-08-05 17:53:14 +00:00
-- TODO: Apply timer penalty only if the potion effect was acutally applied
vals.timer = vals.timer - 3.25
2020-06-27 00:32:03 +00:00
end
end
2020-08-08 08:00:16 +00:00
if vals.timer <= 0 then
lingering_effect_at [ pos ] = nil
end
2020-06-27 22:50:08 +00:00
end
lingering_timer = 0
end
end )
2020-06-27 00:32:03 +00:00
2020-07-12 11:59:29 +00:00
function mcl_potions . register_lingering ( name , descr , color , def )
2020-06-18 11:43:50 +00:00
2020-08-08 08:00:16 +00:00
local id = " mcl_potions: " .. name .. " _lingering "
local longdesc = def.longdesc
if not def.no_effect then
longdesc = S ( " A throwable potion that will shatter on impact, where it creates a magic cloud that lingers around for a while. Any player or mob inside the cloud will receive the potion's effect, possibly repeatedly. " )
if def.longdesc then
longdesc = longdesc .. " \n " .. def.longdesc
end
end
minetest.register_craftitem ( id , {
description = descr ,
_tt_help = def.tt ,
_doc_items_longdesc = longdesc ,
_doc_items_usagehelp = S ( " Use the “Punch” key to throw it. " ) ,
inventory_image = lingering_image ( color ) ,
groups = { brewitem = 1 , not_in_creative_inventory = 0 } ,
on_use = function ( item , placer , pointed_thing )
local velocity = 10
local dir = placer : get_look_dir ( ) ;
local pos = placer : getpos ( ) ;
local obj = minetest.add_entity ( { x = pos.x + dir.x , y = pos.y + 2 + dir.y , z = pos.z + dir.z } , id .. " _flying " )
obj : setvelocity ( { x = dir.x * velocity , y = dir.y * velocity , z = dir.z * velocity } )
obj : setacceleration ( { x = dir.x *- 3 , y =- 9.8 , z = dir.z *- 3 } )
obj : get_luaentity ( ) . _thrower = placer : get_player_name ( )
if not minetest.is_creative_enabled ( placer : get_player_name ( ) ) then
item : take_item ( )
end
return item
end ,
stack_max = 1 ,
_on_dispense = function ( stack , dispenserpos , droppos , dropnode , dropdir )
local s_pos = vector.add ( dispenserpos , vector.multiply ( dropdir , 0.51 ) )
local obj = minetest.add_entity ( { x = s_pos.x + dropdir.x , y = s_pos.y + dropdir.y , z = s_pos.z + dropdir.z } , id .. " _flying " )
local velocity = 22
obj : set_velocity ( { x = dropdir.x * velocity , y = dropdir.y * velocity , z = dropdir.z * velocity } )
obj : set_acceleration ( { x = dropdir.x *- 3 , y =- 9.8 , z = dropdir.z *- 3 } )
end
} )
local w = 0.7
minetest.register_entity ( id .. " _flying " , {
textures = { lingering_image ( color ) } ,
hp_max = 1 ,
visual_size = { x = w / 2 , y = w / 2 } ,
collisionbox = { - 0.1 , - 0.1 , - 0.1 , 0.1 , 0.1 , 0.1 } ,
pointable = false ,
on_step = function ( self , dtime )
local pos = self.object : get_pos ( )
local node = minetest.get_node ( pos )
local n = node.name
local g = minetest.get_node_group ( n , " liquid " )
local d = 4
if n ~= " air " and n ~= " mcl_portals:portal " and n ~= " mcl_portals:portal_end " and g == 0 or mcl_potions.is_obj_hit ( self , pos ) then
minetest.sound_play ( " mcl_potions_breaking_glass " , { pos = pos , max_hear_distance = 16 , gain = 1 } )
add_lingering_effect ( pos , color , def , name == " water " )
local texture , minacc , maxacc
if name == " water " then
texture = " mcl_potions_droplet.png "
minacc = { x =- 0.2 , y =- 0.05 , z =- 0.2 }
maxacc = { x = 0.2 , y = 0.05 , z = 0.2 }
else
texture = " mcl_potions_sprite.png "
minacc = { x =- 0.2 , y = 0 , z =- 0.2 }
maxacc = { x = 0.2 , y = .05 , z = 0.2 }
2020-06-26 23:08:41 +00:00
end
2020-08-08 08:00:16 +00:00
minetest.add_particlespawner ( {
amount = 40 ,
time = 1 ,
minpos = { x = pos.x - d , y = pos.y + 0.5 , z = pos.z - d } ,
maxpos = { x = pos.x + d , y = pos.y + 1 , z = pos.z + d } ,
minvel = { x =- 0.5 , y = 0 , z =- 0.5 } ,
maxvel = { x = 0.5 , y = 0.5 , z = 0.5 } ,
minacc = minacc ,
maxacc = maxacc ,
minexptime = 1 ,
maxexptime = 2 ,
minsize = 1 ,
maxsize = 2 ,
collisiondetection = true ,
vertical = false ,
texture = texture .. " ^[colorize: " .. color .. " :127 " ,
} )
if name == " water " then
mcl_potions._extinguish_nearby_fire ( pos , d )
end
self.object : remove ( )
2020-07-11 13:07:27 +00:00
end
2020-08-08 08:00:16 +00:00
end ,
} )
2020-06-18 11:43:50 +00:00
end