2017-07-05 03:15:46 +02:00
--MCmobs v0.2
--maikerumine
--made for MC like Survival game
--License for code WTFPL and otherwise stated in readmes
2022-02-13 21:40:12 +01:00
local S = minetest.get_translator ( " mobs_mc " )
2017-07-05 03:15:46 +02:00
--###################
--################### SHULKER
--###################
2022-09-11 19:40:16 +02:00
local adjacents = {
vector.new ( 1 , 0 , 0 ) ,
vector.new ( - 1 , 0 , 0 ) ,
vector.new ( 0 , 1 , 0 ) ,
vector.new ( 0 , - 1 , 0 ) ,
vector.new ( 0 , 0 , 1 ) ,
vector.new ( 0 , 0 , - 1 ) ,
}
local function check_spot ( pos )
2022-09-11 23:44:33 +02:00
pos = vector.offset ( pos , 0 , 0.5 , 0 )
2022-09-11 19:40:16 +02:00
local n = minetest.get_node ( pos )
2022-09-11 23:44:33 +02:00
if n.name ~= " air " then return false end
2022-09-11 19:40:16 +02:00
for _ , a in pairs ( adjacents ) do
local p = vector.add ( pos , a )
local pn = minetest.get_node ( p )
if minetest.get_item_group ( pn.name , " solid " ) > 0 then return true end
end
return false
end
local pr = PseudoRandom ( os.time ( ) * ( - 334 ) )
2017-07-05 03:15:46 +02:00
-- animation 45-80 is transition between passive and attack stance
2022-11-09 04:09:58 +01:00
mcl_mobs.register_mob ( " mobs_mc:shulker " , {
2021-04-25 17:30:15 +02:00
description = S ( " Shulker " ) ,
2017-07-05 03:15:46 +02:00
type = " monster " ,
2020-04-11 02:46:03 +02:00
spawn_class = " hostile " ,
2022-02-13 21:40:12 +01:00
attack_type = " shoot " ,
2023-12-11 09:36:03 +01:00
shoot_interval = 6 ,
2017-07-05 03:15:46 +02:00
arrow = " mobs_mc:shulkerbullet " ,
shoot_offset = 0.5 ,
passive = false ,
hp_min = 30 ,
hp_max = 30 ,
2020-12-06 15:46:42 +01:00
xp_min = 5 ,
xp_max = 5 ,
2023-11-16 18:27:54 +01:00
armor = 20 ,
2017-07-05 03:15:46 +02:00
collisionbox = { - 0.5 , - 0.01 , - 0.5 , 0.5 , 0.99 , 0.5 } ,
visual = " mesh " ,
mesh = " mobs_mc_shulker.b3d " ,
textures = { " mobs_mc_endergolem.png " , } ,
2018-09-14 16:27:58 +02:00
-- TODO: sounds
2017-07-05 03:15:46 +02:00
-- TODO: Make shulker dye-able
visual_size = { x = 3 , y = 3 } ,
2023-11-13 16:13:52 +01:00
walk_chance = 10 ,
2022-06-07 09:55:19 +02:00
knock_back = false ,
2017-07-05 03:15:46 +02:00
jump = false ,
2022-09-11 19:40:16 +02:00
can_despawn = false ,
fall_speed = 0 ,
2017-07-05 03:15:46 +02:00
drops = {
2022-05-25 23:25:15 +02:00
{ name = " mcl_mobitems:shulker_shell " ,
2020-12-23 17:41:42 +01:00
chance = 2 ,
min = 1 ,
max = 1 ,
looting = " rare " ,
looting_factor = 0.0625 } ,
2017-07-05 03:15:46 +02:00
} ,
animation = {
2023-11-13 16:13:52 +01:00
stand_speed = 25 , walk_speed = 25 , run_speed = 50 , punch_speed = 25 ,
2017-07-05 03:15:46 +02:00
speed_normal = 25 , speed_run = 50 ,
2022-09-11 19:17:55 +02:00
stand_start = 0 , stand_end = 25 ,
2023-11-14 14:57:56 +01:00
walk_start = 45 , walk_end = 65 ,
walk_loop = false ,
2023-11-13 16:13:52 +01:00
run_start = 65 , run_end = 85 ,
2023-11-14 15:47:24 +01:00
run_loop = false ,
2017-07-05 03:15:46 +02:00
punch_start = 80 , punch_end = 100 ,
} ,
view_range = 16 ,
2022-09-11 19:17:55 +02:00
fear_height = 0 ,
2023-11-13 16:13:52 +01:00
walk_velocity = 0 ,
2023-11-16 18:27:54 +01:00
run_velocity = 0 ,
2022-09-11 19:17:55 +02:00
noyaw = true ,
do_custom = function ( self , dtime )
2022-09-11 19:40:16 +02:00
local pos = self.object : get_pos ( )
2022-09-11 19:17:55 +02:00
if math.floor ( self.object : get_yaw ( ) ) ~= 0 then
self.object : set_yaw ( 0 )
mcl_mobs : yaw ( self , 0 , 0 , dtime )
end
if self.state == " attack " then
2023-11-14 14:57:56 +01:00
self : set_animation ( " run " )
2023-11-25 02:55:06 +01:00
self.armor = 0
elseif self.state == " stand " then
2023-11-16 18:27:54 +01:00
self.armor = 20
2023-11-25 02:55:06 +01:00
elseif self.state == " walk " or self.state == " run " then
2023-11-16 18:27:54 +01:00
self.armor = 0
2022-09-11 19:17:55 +02:00
end
self.path . way = false
self.look_at_players = false
2022-09-11 19:40:16 +02:00
if not check_spot ( pos ) then
self : teleport ( nil )
end
end ,
do_punch = function ( self , puncher , time_from_last_punch , tool_capabilities , dir , damage )
self : teleport ( puncher )
end ,
do_teleport = function ( self , target )
if target ~= nil then
local target_pos = target : get_pos ( )
-- Find all solid nodes below air in a 10× 10× 10 cuboid centered on the target
local nodes = minetest.find_nodes_in_area_under_air ( vector.subtract ( target_pos , 5 ) , vector.add ( target_pos , 5 ) , { " group:solid " , " group:cracky " , " group:crumbly " } )
local telepos
if nodes ~= nil then
if # nodes > 0 then
-- Up to 64 attempts to teleport
for n = 1 , math.min ( 64 , # nodes ) do
local r = pr : next ( 1 , # nodes )
local nodepos = nodes [ r ]
2024-08-31 23:51:58 +02:00
local tg = vector.offset ( nodepos , 0 , 0.5 , 0 )
2022-09-11 19:40:16 +02:00
if check_spot ( tg ) then
telepos = tg
end
end
if telepos then
self.object : set_pos ( telepos )
end
end
end
else
local pos = self.object : get_pos ( )
-- Up to 8 top-level attempts to teleport
for n = 1 , 8 do
local node_ok = false
-- We need to add (or subtract) different random numbers to each vector component, so it couldn't be done with a nice single vector.add() or .subtract():
local randomCube = vector.new ( pos.x + 8 * ( pr : next ( 0 , 16 ) - 8 ) , pos.y + 8 * ( pr : next ( 0 , 16 ) - 8 ) , pos.z + 8 * ( pr : next ( 0 , 16 ) - 8 ) )
local nodes = minetest.find_nodes_in_area_under_air ( vector.subtract ( randomCube , 4 ) , vector.add ( randomCube , 4 ) , { " group:solid " , " group:cracky " , " group:crumbly " } )
if nodes ~= nil then
if # nodes > 0 then
-- Up to 8 low-level (in total up to 8*8 = 64) attempts to teleport
for n = 1 , math.min ( 8 , # nodes ) do
local r = pr : next ( 1 , # nodes )
local nodepos = nodes [ r ]
2022-11-09 06:06:59 +01:00
local tg = vector.offset ( nodepos , 0 , 0.5 , 0 )
2022-09-11 19:40:16 +02:00
if check_spot ( tg ) then
self.object : set_pos ( tg )
node_ok = true
break
end
end
end
end
if node_ok then
break
end
end
end
2022-09-11 19:17:55 +02:00
end ,
2023-12-11 09:36:03 +01:00
on_attack = function ( self , dtime )
self.shoot_interval = math.random ( 1 , 6 )
end ,
2017-07-05 03:15:46 +02:00
} )
-- bullet arrow (weapon)
2022-11-09 04:09:58 +01:00
mcl_mobs.register_arrow ( " mobs_mc:shulkerbullet " , {
2017-07-05 03:15:46 +02:00
visual = " sprite " ,
visual_size = { x = 0.25 , y = 0.25 } ,
textures = { " mobs_mc_shulkerbullet.png " } ,
2023-11-16 11:21:25 +01:00
velocity = 5 ,
2023-11-15 19:00:01 +01:00
homing = true ,
2023-10-26 21:35:13 +02:00
hit_player = mcl_mobs.get_arrow_damage_func ( 4 ) ,
hit_mob = mcl_mobs.get_arrow_damage_func ( 4 ) ,
2017-07-05 03:15:46 +02:00
} )
2022-11-09 04:09:58 +01:00
mcl_mobs.register_egg ( " mobs_mc:shulker " , S ( " Shulker " ) , " #946694 " , " #4d3852 " , 0 )
2023-02-10 03:46:23 +01:00
mcl_mobs : non_spawn_specific ( " mobs_mc:shulker " , " overworld " , 0 , minetest.LIGHT_MAX + 1 )
2022-09-11 19:55:13 +02:00
--[[
2022-05-25 14:44:49 +02:00
mcl_mobs : spawn_specific (
2021-04-25 17:30:15 +02:00
" mobs_mc:shulker " ,
" end " ,
2021-04-08 13:39:18 +02:00
" ground " ,
{
" End "
} ,
2021-04-25 17:30:15 +02:00
0 ,
minetest.LIGHT_MAX + 1 ,
30 ,
5000 ,
2 ,
2022-05-25 23:25:15 +02:00
mcl_vars.mg_end_min ,
mcl_vars.mg_end_max )
2022-09-11 19:55:13 +02:00
--]]