2022-07-25 17:47:36 +02:00
local S = minetest.get_translator ( minetest.get_current_modname ( ) )
2022-07-22 20:48:36 +02:00
--[[
there are strings in meta , which are being used to see which effect will be given to the player ( s )
Valid strings :
2022-08-01 14:22:33 +02:00
swiftness
leaping
2024-04-27 05:03:54 +02:00
strength
2022-08-01 14:22:33 +02:00
regeneration
2024-04-27 05:03:54 +02:00
haste
resistance
slow_falling
absorption
2022-07-22 20:48:36 +02:00
] ] --
2022-07-25 17:20:51 +02:00
2022-08-01 14:14:06 +02:00
mcl_beacons = {
blocks = { " mcl_core:diamondblock " , " mcl_core:ironblock " , " mcl_core:goldblock " , " mcl_core:emeraldblock " , " mcl_nether:netheriteblock " } ,
fuel = { " mcl_core:diamond " , " mcl_core:emerald " , " mcl_core:iron_ingot " , " mcl_core:gold_ingot " , " mcl_nether:netherite_ingot " }
}
local beacon_blocklist = mcl_beacons.blocks
local beacon_fuellist = mcl_beacons.fuel
local pallete_order = {
2022-08-01 15:48:23 +02:00
glass_cyan = 1 ,
pane_cyan_flat = 1 ,
pane_cyan = 1 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_white = 2 ,
pane_white_flat = 2 ,
pane_white = 2 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_brown = 3 ,
pane_brown_flat = 3 ,
pane_brown = 3 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_blue = 4 ,
pane_blue_flat = 4 ,
pane_blue = 4 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_light_blue = 5 ,
pane_light_blue_flat = 5 ,
pane_light_blue = 5 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_pink = 6 ,
pane_pink_flat = 6 ,
pane_pink = 6 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_purple = 7 ,
pane_purple_flat = 7 ,
pane_purple = 7 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_red = 8 ,
pane_red_flat = 8 ,
pane_red = 8 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_silver = 9 ,
pane_silver_flat = 9 ,
pane_silver = 9 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_gray = 10 ,
pane_gray_flat = 10 ,
pane_gray = 10 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_lime = 11 ,
pane_lime_flat = 11 ,
pane_lime = 11 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_green = 12 ,
pane_green_flat = 12 ,
pane_green = 12 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_orange = 13 ,
pane_orange_flat = 13 ,
pane_orange = 13 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_yellow = 14 ,
pane_yellow_flat = 14 ,
pane_yellow = 14 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_black = 15 ,
pane_black_flat = 15 ,
pane_black = 15 ,
2022-08-01 14:14:06 +02:00
2022-08-01 15:48:23 +02:00
glass_magenta = 16 ,
pane_magenta_flat = 16 ,
pane_magenta = 16
2022-08-01 14:14:06 +02:00
}
2024-05-29 13:26:22 +02:00
local EFFECT_CONVERSIONS = {
strenght = " strength "
}
2022-08-01 14:14:06 +02:00
2022-07-25 21:35:15 +02:00
local function get_beacon_beam ( glass_nodename )
2022-08-01 14:22:33 +02:00
if glass_nodename == " air " then return 0 end
local glass_string = glass_nodename : split ( ' : ' ) [ 2 ]
if not pallete_order [ glass_string ] then return 0 end
return pallete_order [ glass_string ]
2022-07-25 21:35:15 +02:00
end
2022-07-31 13:38:07 +02:00
minetest.register_node ( " mcl_beacons:beacon_beam " , {
2023-05-27 17:27:01 +02:00
tiles = { " blank.png^[noalpha^[colorize:#b8bab9 " } ,
2022-08-01 14:22:33 +02:00
drawtype = " nodebox " ,
node_box = {
type = " fixed " ,
fixed = {
{ - 0.1250 , - 0.5000 , - 0.1250 , 0.1250 , 0.5000 , 0.1250 }
}
} ,
pointable = false ,
2022-08-07 04:38:15 +02:00
light_source = 14 ,
2022-08-01 14:22:33 +02:00
walkable = false ,
groups = { not_in_creative_inventory = 1 } ,
_mcl_blast_resistance = 1200 ,
paramtype2 = " color " ,
palette = " beacon_beam_palette.png " ,
palette_index = 0 ,
buildable_to = true ,
2022-07-31 13:38:07 +02:00
} )
2022-07-25 21:35:15 +02:00
2022-07-31 13:38:07 +02:00
mesecon.register_mvps_stopper ( " mcl_beacons:beacon_beam " )
2022-07-22 20:48:36 +02:00
local formspec_string =
2022-08-01 14:22:33 +02:00
" size[11,14] " ..
2022-07-22 20:48:36 +02:00
2022-08-01 14:22:33 +02:00
" label[4.5,0.5; " .. minetest.formspec_escape ( S ( " Beacon: " ) ) .. " ] " ..
" label[0.5,1; " .. minetest.formspec_escape ( S ( " Primary Power: " ) ) .. " ] " ..
" label[0.5,8.25; " .. minetest.formspec_escape ( S ( " Inventory: " ) ) .. " ] " ..
2022-07-22 20:48:36 +02:00
2022-08-01 14:22:33 +02:00
" image[1,1.5;1,1;custom_beacom_symbol_4.png] " ..
" image[1,3;1,1;custom_beacom_symbol_3.png] " ..
" image[1,4.5;1,1;custom_beacom_symbol_2.png] " ..
" image[1,6;1,1;custom_beacom_symbol_1.png] " ..
2022-07-22 20:48:36 +02:00
2024-04-27 05:03:54 +02:00
" image_button[5.2,1.5;1,1;mcl_potions_effect_swiftness.png;swiftness;] " ..
" image_button[8.5,1.5;1,1;mcl_potions_effect_haste.png;haste;] " ..
2022-08-01 14:22:33 +02:00
" image_button[5.2,3;1,1;mcl_potions_effect_leaping.png;leaping;] " ..
2024-04-27 05:03:54 +02:00
" image_button[8.5,3;1,1;mcl_potions_effect_resistance.png;resistance;] " ..
" image_button[5.2,4.5;1,1;mcl_potions_effect_strength.png;strength;] " ..
" image_button[8.5,4.5;1,1;mcl_potions_effect_absorption.png;absorption;] " ..
" image_button[5.2,6;1,1;mcl_potions_effect_regeneration.png;regeneration;] " ..
" image_button[8.5,6;1,1;mcl_potions_effect_slow_falling.png;slow_falling;] " ..
2022-07-22 20:48:36 +02:00
2022-08-01 14:22:33 +02:00
" item_image[1,7;1,1;mcl_core:diamond] " ..
" item_image[2.2,7;1,1;mcl_core:emerald] " ..
" item_image[3.4,7;1,1;mcl_core:iron_ingot] " ..
" item_image[4.6,7;1,1;mcl_core:gold_ingot] " ..
" item_image[5.8,7;1,1;mcl_nether:netherite_ingot] " ..
2022-07-22 20:48:36 +02:00
2022-08-01 14:22:33 +02:00
mcl_formspec.get_itemslot_bg ( 7.2 , 7 , 1 , 1 ) ..
2022-07-24 13:00:58 +02:00
" list[context;input;7.2,7;1,1;] " ..
2022-07-22 20:48:36 +02:00
mcl_formspec.get_itemslot_bg ( 1 , 9 , 9 , 3 ) ..
2022-08-01 14:22:33 +02:00
" list[current_player;main;1,9;9,3;9] " ..
2022-07-22 20:48:36 +02:00
mcl_formspec.get_itemslot_bg ( 1 , 12.5 , 9 , 1 ) ..
2022-08-01 14:22:33 +02:00
" list[current_player;main;1,12.5;9,1;] "
2022-07-22 20:48:36 +02:00
2022-07-25 17:23:28 +02:00
local function remove_beacon_beam ( pos )
2022-08-01 14:22:33 +02:00
for y = pos.y , pos.y + 301 do
local node = minetest.get_node ( { x = pos.x , y = y , z = pos.z } )
if node.name ~= " air " and node.name ~= " mcl_core:bedrock " and node.name ~= " mcl_core:void " then
if node.name == " ignore " then
minetest.get_voxel_manip ( ) : read_from_map ( { x = pos.x , y = y , z = pos.z } , { x = pos.x , y = y , z = pos.z } )
node = minetest.get_node ( { x = pos.x , y = y , z = pos.z } )
end
2024-05-29 03:19:51 +02:00
2022-08-01 14:22:33 +02:00
if node.name == " mcl_beacons:beacon_beam " then
minetest.remove_node ( { x = pos.x , y = y , z = pos.z } )
end
end
end
2022-07-25 17:20:51 +02:00
end
2022-07-22 20:48:36 +02:00
local function beacon_blockcheck ( pos )
2022-08-01 14:22:33 +02:00
for y_offset = 1 , 4 do
local block_y = pos.y - y_offset
for block_x = ( pos.x - y_offset ) , ( pos.x + y_offset ) do
for block_z = ( pos.z - y_offset ) , ( pos.z + y_offset ) do
local valid_block = false --boolean which stores if block is valid or not
for _ , beacon_block in pairs ( beacon_blocklist ) do
if beacon_block == minetest.get_node ( { x = block_x , y = block_y , z = block_z } ) . name and not valid_block then --is the block in the pyramid a valid beacon block
valid_block = true
end
end
if not valid_block then
return y_offset - 1 --the last layer is complete, this one is missing or incomplete
end
end
end
if y_offset == 4 then --all checks are done, beacon is maxed
return y_offset
end
end
2022-07-22 20:48:36 +02:00
end
2022-07-23 12:46:02 +02:00
2023-04-27 20:04:36 +02:00
local function clear_obstructed_beam ( pos )
2023-04-04 21:57:28 +02:00
for y = pos.y + 1 , pos.y + 100 do
local nodename = minetest.get_node ( { x = pos.x , y = y , z = pos.z } ) . name
if nodename ~= " mcl_core:bedrock " and nodename ~= " air " and nodename ~= " mcl_core:void " and nodename ~= " ignore " then --ignore means not loaded, let's just assume that's air
if nodename ~= " mcl_beacons:beacon_beam " then
if minetest.get_item_group ( nodename , " glass " ) == 0 and minetest.get_item_group ( nodename , " material_glass " ) == 0 then
remove_beacon_beam ( pos )
return true
end
end
end
end
return false
end
2022-07-24 12:32:20 +02:00
local function effect_player ( effect , pos , power_level , effect_level , player )
2022-08-01 14:22:33 +02:00
local distance = vector.distance ( player : get_pos ( ) , pos )
if distance > ( power_level + 1 ) * 10 then return end
2024-04-27 05:03:54 +02:00
mcl_potions.give_effect_by_level ( effect , player , effect_level , 16 )
2022-07-23 12:46:02 +02:00
end
2023-04-27 20:04:36 +02:00
local function apply_effects_to_all_players ( pos )
2024-05-29 03:19:51 +02:00
local meta = minetest.get_meta ( pos )
2023-04-04 21:57:28 +02:00
local effect_string = meta : get_string ( " effect " )
2024-05-29 03:19:51 +02:00
local effect_level = meta : get_int ( " effect_level " )
local power_level = beacon_blockcheck ( pos )
2023-04-04 21:57:28 +02:00
2024-05-29 13:26:22 +02:00
local new_effect_string = EFFECT_CONVERSION [ effect_string ]
if new_effect_string then
effect_string = new_effect_string
2024-05-29 03:19:51 +02:00
meta : set_string ( " effect " , effect_string )
end
2023-04-27 20:04:36 +02:00
2024-05-29 03:19:51 +02:00
if effect_string == " " or ( effect_level == 2 and power_level < 4 ) then --no need to run loops when beacon is in an invalid setup :P
2023-04-04 21:57:28 +02:00
return
end
2024-05-29 03:19:51 +02:00
local beacon_distance = ( power_level + 1 ) * 10
2023-04-27 20:04:36 +02:00
for _ , player in pairs ( minetest.get_connected_players ( ) ) do
2024-05-29 03:19:51 +02:00
if vector.distance ( pos , player : get_pos ( ) ) <= beacon_distance then
if not clear_obstructed_beam ( pos ) then
effect_player ( effect_string , pos , power_level , effect_level , player )
end
end
2023-04-04 21:57:28 +02:00
end
end
2022-07-22 20:48:36 +02:00
minetest.register_node ( " mcl_beacons:beacon " , {
2022-08-01 14:22:33 +02:00
description = S " Beacon " ,
drawtype = " mesh " ,
collisionbox = { - 0.5 , - 0.5 , - 0.5 , 0.5 , 0.5 , 0.5 } ,
mesh = " mcl_beacon.b3d " ,
tiles = { " beacon_UV.png " } ,
2022-08-07 04:38:15 +02:00
use_texture_alpha = " clip " ,
2022-08-01 14:22:33 +02:00
on_construct = function ( pos )
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
inv : set_size ( " input " , 1 )
local form = formspec_string
2022-07-22 20:48:36 +02:00
meta : set_string ( " formspec " , form )
2022-08-01 14:22:33 +02:00
end ,
on_destruct = function ( pos )
local meta = minetest.get_meta ( pos )
local input = meta : get_inventory ( ) : get_stack ( " input " , 1 )
if not input : is_empty ( ) then
local p = { x = pos.x + math.random ( 0 , 10 ) / 10 - 0.5 , y = pos.y , z = pos.z + math.random ( 0 , 10 ) / 10 - 0.5 } --from mcl_anvils
minetest.add_item ( p , input )
end
remove_beacon_beam ( pos )
end ,
on_receive_fields = function ( pos , formname , fields , sender )
2024-04-27 05:03:54 +02:00
if fields.swiftness or fields.regeneration or fields.leaping or fields.strenght
or fields.haste or fields.resistance or fields.absorption or fields.slow_falling then
2022-08-01 14:22:33 +02:00
local sender_name = sender : get_player_name ( )
local power_level = beacon_blockcheck ( pos )
if minetest.is_protected ( pos , sender_name ) then
minetest.record_protection_violation ( pos , sender_name )
return
elseif power_level == 0 then
return
end
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
local input = inv : get_stack ( " input " , 1 )
2024-05-29 03:19:51 +02:00
2022-08-01 14:22:33 +02:00
if input : is_empty ( ) then
return
end
local valid_item = false
for _ , item in ipairs ( beacon_fuellist ) do
if input : get_name ( ) == item then
valid_item = true
end
end
if not valid_item then
return
end
local successful = false
if fields.swiftness then
if power_level == 4 then
minetest.get_meta ( pos ) : set_int ( " effect_level " , 2 )
else
minetest.get_meta ( pos ) : set_int ( " effect_level " , 1 )
end
minetest.get_meta ( pos ) : set_string ( " effect " , " swiftness " )
successful = true
2024-04-27 05:03:54 +02:00
elseif fields.haste then
if power_level == 4 then
minetest.get_meta ( pos ) : set_int ( " effect_level " , 2 )
else
minetest.get_meta ( pos ) : set_int ( " effect_level " , 1 )
end
minetest.get_meta ( pos ) : set_string ( " effect " , " haste " )
successful = true
2022-08-01 14:22:33 +02:00
elseif fields.leaping and power_level >= 2 then
if power_level == 4 then
minetest.get_meta ( pos ) : set_int ( " effect_level " , 2 )
else
minetest.get_meta ( pos ) : set_int ( " effect_level " , 1 )
end
minetest.get_meta ( pos ) : set_string ( " effect " , " leaping " )
successful = true
2024-04-27 05:03:54 +02:00
elseif fields.resistance and power_level >= 2 then
if power_level == 4 then
minetest.get_meta ( pos ) : set_int ( " effect_level " , 2 )
else
minetest.get_meta ( pos ) : set_int ( " effect_level " , 1 )
end
minetest.get_meta ( pos ) : set_string ( " effect " , " resistance " )
successful = true
2022-08-01 14:22:33 +02:00
elseif fields.strenght and power_level >= 3 then
if power_level == 4 then
minetest.get_meta ( pos ) : set_int ( " effect_level " , 2 )
else
minetest.get_meta ( pos ) : set_int ( " effect_level " , 1 )
end
2024-04-27 05:03:54 +02:00
minetest.get_meta ( pos ) : set_string ( " effect " , " strength " )
successful = true
elseif fields.absorption and power_level >= 3 then
if power_level == 4 then
minetest.get_meta ( pos ) : set_int ( " effect_level " , 2 )
else
minetest.get_meta ( pos ) : set_int ( " effect_level " , 1 )
end
minetest.get_meta ( pos ) : set_string ( " effect " , " absorption " )
2022-08-01 14:22:33 +02:00
successful = true
elseif fields.regeneration and power_level == 4 then
minetest.get_meta ( pos ) : set_int ( " effect_level " , 2 )
minetest.get_meta ( pos ) : set_string ( " effect " , " regeneration " )
successful = true
2024-04-27 05:03:54 +02:00
elseif fields.slow_falling and power_level == 4 then
minetest.get_meta ( pos ) : set_int ( " effect_level " , 2 )
minetest.get_meta ( pos ) : set_string ( " effect " , " slow_falling " )
successful = true
2022-08-01 14:22:33 +02:00
end
if successful then
if power_level == 4 then
awards.unlock ( sender : get_player_name ( ) , " mcl:maxed_beacon " )
end
awards.unlock ( sender : get_player_name ( ) , " mcl:beacon " )
input : take_item ( )
inv : set_stack ( " input " , 1 , input )
2024-05-29 03:19:51 +02:00
2022-08-01 14:22:33 +02:00
local beam_palette_index = 0
remove_beacon_beam ( pos )
for y = pos.y + 1 , pos.y + 201 do
local node = minetest.get_node ( { x = pos.x , y = y , z = pos.z } )
if node.name == ignore then
minetest.get_voxel_manip ( ) : read_from_map ( { x = pos.x , y = y , z = pos.z } , { x = pos.x , y = y , z = pos.z } )
node = minetest.get_node ( { x = pos.x , y = y , z = pos.z } )
end
if minetest.get_item_group ( node.name , " glass " ) ~= 0 or minetest.get_item_group ( node.name , " material_glass " ) ~= 0 then
beam_palette_index = get_beacon_beam ( node.name )
end
if node.name == " air " then
minetest.set_node ( { x = pos.x , y = y , z = pos.z } , { name = " mcl_beacons:beacon_beam " , param2 = beam_palette_index } )
end
end
2023-04-27 20:04:36 +02:00
apply_effects_to_all_players ( pos ) --call it once outside the globalstep so the player gets the effect right after selecting it
2023-04-04 22:03:29 +02:00
end
2022-08-01 14:22:33 +02:00
end
end ,
2022-08-07 04:38:15 +02:00
light_source = 14 ,
2022-08-01 14:22:33 +02:00
groups = { handy = 1 } ,
drop = " mcl_beacons:beacon " ,
sounds = mcl_sounds.node_sound_glass_defaults ( ) ,
_mcl_hardness = 3 ,
2022-07-22 20:48:36 +02:00
} )
mesecon.register_mvps_stopper ( " mcl_beacons:beacon " )
mcl_wip.register_wip_item ( " mcl_beacons:beacon " )
function register_beaconblock ( itemstring ) --API function for other mods
2022-08-01 14:22:33 +02:00
table.insert ( beacon_blocklist , itemstring )
2022-07-22 20:48:36 +02:00
end
function register_beaconfuel ( itemstring )
2022-08-01 14:22:33 +02:00
table.insert ( beacon_fuellist , itemstring )
2022-07-22 20:48:36 +02:00
end
2022-07-31 13:38:07 +02:00
minetest.register_abm {
2022-08-01 14:22:33 +02:00
label = " update beacon beam " ,
nodenames = { " mcl_beacons:beacon_beam " } ,
interval = 1 ,
chance = 1 ,
action = function ( pos )
local node_below = minetest.get_node ( { x = pos.x , y = pos.y - 1 , z = pos.z } )
local node_above = minetest.get_node ( { x = pos.x , y = pos.y + 1 , z = pos.z } )
local node_current = minetest.get_node ( pos )
if node_below.name == " air " then
if minetest.get_node ( { x = pos.x , y = pos.y - 2 , z = pos.z } ) . name == " mcl_beacons:beacon " then
minetest.set_node ( { x = pos.x , y = pos.y - 1 , z = pos.z } , { name = " mcl_beacons:beacon_beam " , param2 = 0 } )
end
remove_beacon_beam ( pos )
2022-08-01 15:48:23 +02:00
elseif node_above.name == " air " or ( node_above.name == " mcl_beacons:beacon_beam " and node_above.param2 ~= node_current.param2 ) then
2022-08-01 14:22:33 +02:00
minetest.set_node ( { x = pos.x , y = pos.y + 1 , z = pos.z } , { name = " mcl_beacons:beacon_beam " , param2 = node_current.param2 } )
elseif minetest.get_item_group ( node_above.name , " glass " ) ~= 0 or minetest.get_item_group ( node_above.name , " material_glass " ) ~= 0 then
minetest.set_node ( { x = pos.x , y = pos.y + 2 , z = pos.z } , { name = " mcl_beacons:beacon_beam " , param2 = get_beacon_beam ( node_above.name ) } )
end
end ,
2022-07-31 13:38:07 +02:00
}
2023-04-04 21:57:28 +02:00
minetest.register_abm {
label = " apply beacon effects to players " ,
nodenames = { " mcl_beacons:beacon " } ,
interval = 3 ,
chance = 1 ,
action = function ( pos )
2023-04-27 20:04:36 +02:00
apply_effects_to_all_players ( pos )
2023-04-04 21:57:28 +02:00
end ,
}
2022-07-24 12:45:30 +02:00
minetest.register_craft ( {
2022-08-01 14:22:33 +02:00
output = " mcl_beacons:beacon " ,
recipe = {
{ " mcl_core:glass " , " mcl_core:glass " , " mcl_core:glass " } ,
{ " mcl_core:glass " , " mcl_mobitems:nether_star " , " mcl_core:glass " } ,
{ " mcl_core:obsidian " , " mcl_core:obsidian " , " mcl_core:obsidian " }
}
2022-08-01 15:48:23 +02:00
} )