Initial commit

master
Juraj Vajda 2016-01-07 20:22:12 +01:00
commit 74adc847b6
7 changed files with 410 additions and 0 deletions

3
README.md Normal file
View File

@ -0,0 +1,3 @@
*Mob Spawners*
This mod for minetest lets the player configure and craft a Spawners blocks for mobs.

5
depends.txt Normal file
View File

@ -0,0 +1,5 @@
default
mobs?
fake_fire?
xpanes?
creatures?

389
init.lua Normal file
View File

@ -0,0 +1,389 @@
local max_obj_per_mapblock = tonumber(minetest.setting_get("max_objects_per_block"))
-- main table
spawners = {}
-- list of mods
spawners.mob_mods = {"mobs", "testmod"}
-- table holding all mobs info
spawners.mob_tables = {}
-- check if mods exists and build tables
for k, v in ipairs(spawners.mob_mods) do
local modpath = minetest.get_modpath(v)
if (modpath) then
-- list of mobs and their info
table.insert(spawners.mob_tables, {name="sheep_white", mod_prefix_default=v, mod_prefix_custom="", dummy_size={x=0.52,y=0.52}, dummy_offset=0.2, dummy_mesh="mobs_sheep.b3d", dummy_texture={"mobs_sheep_white.png"}, night_only=false})
table.insert(spawners.mob_tables, {name="cow", mod_prefix_default=v, mod_prefix_custom="", dummy_size={x=0.3,y=0.3}, dummy_offset=-0.3, dummy_mesh="mobs_cow.x", dummy_texture={"mobs_cow.png"}, night_only=false})
table.insert(spawners.mob_tables, {name="chicken", mod_prefix_default=v, mod_prefix_custom="", dummy_size={x=0.9,y=0.9}, dummy_offset=0.2, dummy_mesh="mobs_chicken.x", dummy_texture={"mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png"}, night_only=false})
table.insert(spawners.mob_tables, {name="warthog", mod_prefix_default=v, mod_prefix_custom="", dummy_size={x=0.62,y=0.62}, dummy_offset=-0.3, dummy_mesh="mobs_warthog.x", dummy_texture={"mobs_warthog.png"}, night_only=true})
table.insert(spawners.mob_tables, {name="bunny", mod_prefix_default=v, mod_prefix_custom="", dummy_size={x=1,y=1}, dummy_offset=0.2, dummy_mesh="mobs_bunny.b3d", dummy_texture={"mobs_bunny_brown.png"}, night_only=false})
table.insert(spawners.mob_tables, {name="kitten", mod_prefix_default=v, mod_prefix_custom="", dummy_size={x=0.32,y=0.32}, dummy_offset=0, dummy_mesh="mobs_kitten.b3d", dummy_texture={"mobs_kitten_ginger.png"}, night_only=false})
else
print("[Spawners] MOD: "..v.." not found.")
end
end
-- start spawning mobs
function spawners.start_spawning(pos, how_many, mob_name, mod_prefix)
if not pos or not how_many or not mob_name then return end
local sound_name
-- remove 'spawners:' from the string
local mob_name = string.sub(mob_name,10)
-- fix some namings
if mob_name == "sheep_white" then
sound_name = "sheep"
elseif mob_name == "warthog" then
sound_name = "pig"
else
sound_name = mob_name
end
for i=1,how_many do
-- local x = 1/math.random(1,3)
-- local z = 1/math.random(1,3)
-- local p = {x=pos.x+x,y=pos.y,z=pos.z+z}
local obj = minetest.add_entity(pos, mod_prefix..":"..mob_name)
if obj then
if sound_name then
minetest.sound_play(mod_prefix.."_"..sound_name, {
pos = pos,
max_hear_distance = 32,
gain = 10,
})
end
minetest.log("action", "Spawners: spawned "..mob_name.." at ("..pos.x..","..pos.y..","..pos.z..")")
end
end
end
function spawners.check_around_radius(pos)
local player_near = false
local radius = 21
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, radius)) do
if obj:is_player() then
player_near = true
end
end
return player_near
end
function check_node_status(pos, mob, night_only)
local player_near = spawners.check_around_radius(pos)
local random_pos = false
if player_near then
local min_node_light = 10
local tod = minetest.get_timeofday() * 24000
local node_light = minetest.get_node_light(pos)
local spawn_positions = {}
local front = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z})
local right = minetest.get_node({x=pos.x, y=pos.y, z=pos.z+1})
local back = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z})
local left = minetest.get_node({x=pos.x, y=pos.y, z=pos.z-1})
local top = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z})
local bottom = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z})
if not node_light then return end
-- make sure that at least one side of the spawner is open
if front.name == "air" then
table.insert(spawn_positions, {x=pos.x+1.5, y=pos.y, z=pos.z})
end
if right.name == "air" then
table.insert(spawn_positions, {x=pos.x, y=pos.y, z=pos.z+1.5})
end
if back.name == "air" then
table.insert(spawn_positions, {x=pos.x-1.5, y=pos.y, z=pos.z})
end
if left.name == "air" then
table.insert(spawn_positions, {x=pos.x, y=pos.y, z=pos.z-1.5})
end
if top.name == "air" then
table.insert(spawn_positions, {x=pos.x, y=pos.y+1.5, z=pos.z})
end
if bottom.name == "air" then
table.insert(spawn_positions, {x=pos.x, y=pos.y-1.5, z=pos.z})
end
-- spawner is closed from all sides
if not (front or right or back or left or top or bottom) then
minetest.log("action","spawner is closed")
return false
end
local pick_random = math.random(1,#spawn_positions)
-- pick random from the open sides
for k, v in pairs (spawn_positions) do
if k == pick_random then
random_pos = v
end
end
if not random_pos then return end
print("#spawn_positions: "..#spawn_positions)
print("pick_random: "..pick_random)
print("node_light: "..node_light)
-- print("node_pos"..minetest.pos_to_string(pos))
-- print("random_pos"..minetest.pos_to_string(random_pos))
-- check the node above the found air node
local node_above = minetest.get_node({x=random_pos.x, y=random_pos.y+1, z=random_pos.z}).name
local node_below = minetest.get_node({x=random_pos.x, y=random_pos.y-1, z=random_pos.z}).name
print("node_above: "..node_above)
print("node_below: "..node_below)
if not (node_above == "air" or node_below == "air") then
print("node below or above is not air")
return false
end
if not night_only and node_light < min_node_light then
print("not enough light")
return false
end
-- At 0 time of day (tod) the day begins; it is midnight and the moon is exactly at the zenith (1).
-- At 4500 tod, the first sun rays emit from the horizon, it gets brighter (2).
-- At 4750 tod, the sun rises and it gets brighter (3).
-- At 5001 tod, it gets brighter again (4).
-- At 5200 tod, the sun becomes fully visible (4).
-- At 5250 tod, it gets brighter again (5).
-- At 5500 tod, it gets brighter again (6).
-- At 5751 tod, maximum brightness is reached (7).
-- At 12000 tod is midday; the sun is exactly at the zenith (7).
-- At 18250 tod, the day is going to end, it gets a bit darker (6).
-- At 18502 tod, it gets a bit darker again (5).
-- At 18600 tod, the sun begins to set (5).
-- At 18752 tod, it gets a bit darker yet again (4).
-- At 19000 tod, the sky gets even darker (3).
-- At 19252 tod, the sun is almost gone and the sky gets even darker (2).
-- At 19359 tod, the sun square is gone and the last sun rays emit from the horizon (2).
-- At 19500 tod, the sun rays stop from being visible (2).
-- At 19502 tod, the sky has the lowest brightness (1).
-- At 24000 tod, the day ends and the next one starts; it is midnight again (1).
if night_only then
print("tod: "..tod)
if not (19359 > tod and tod > 5200) or node_light < min_node_light then
print("it's night")
if random_pos then
return random_pos
else
return false
end
else
return false
end
end
return random_pos
else
return false
end
end
function spawners.create(mob_name, mod_prefix, size, offset, mesh, texture, night_only)
local dummy_definition = {
hp_max = 1,
physical = true,
collisionbox = {0,0,0,0,0,0},
visual = "mesh",
visual_size = size,
mesh = mesh,
textures = texture,
makes_footstep_sound = false,
timer = 0,
automatic_rotate = math.pi * -3,
m_name = "dummy"
}
dummy_definition.on_activate = function(self)
self.object:setvelocity({x=0, y=0, z=0})
self.object:setacceleration({x=0, y=0, z=0})
self.object:set_armor_groups({immortal=1})
end
-- remove dummy after dug up the spawner
dummy_definition.on_step = function(self, dtime)
self.timer = self.timer + dtime
local n = minetest.get_node_or_nil(self.object:getpos())
if self.timer > 2 then
if n and n.name and n.name ~= "spawners:"..mob_name.."_spawner_active" then
self.object:remove()
end
end
end
minetest.register_entity("spawners:dummy_"..mob_name, dummy_definition)
-- node spawner active
minetest.register_node("spawners:"..mob_name.."_spawner_active", {
description = mob_name.." spawner active",
paramtype = "light",
light_source = 4,
drawtype = "allfaces",
walkable = true,
damage_per_second = 4,
sunlight_propagates = true,
tiles = {
{
name = "spawners_spawner_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 2.0
},
}
},
is_ground_content = true,
groups = {cracky=1,level=2,igniter=1,not_in_creative_inventory=1},
drop = "spawners:"..mob_name.."_spawner",
on_construct = function(pos)
pos.y = pos.y + offset
minetest.add_entity(pos,"spawners:dummy_"..mob_name)
end,
})
-- node spawner inactive
minetest.register_node("spawners:"..mob_name.."_spawner", {
description = mob_name.." spawner",
paramtype = "light",
drawtype = "allfaces",
walkable = true,
sunlight_propagates = true,
tiles = {"spawners_spawner.png"},
is_ground_content = true,
groups = {cracky=1,level=2},
on_construct = function(pos)
local random_pos = check_node_status(pos, mob_name, night_only)
if random_pos then
minetest.set_node(pos, {name="spawners:"..mob_name.."_spawner_active"})
else
minetest.log("action","no random_pos found")
end
end,
})
-- node spawner overheated
minetest.register_node("spawners:"..mob_name.."_spawner_overheat", {
description = mob_name.." spawner overheated",
paramtype = "light",
light_source = 2,
drawtype = "allfaces",
walkable = true,
damage_per_second = 4,
sunlight_propagates = true,
tiles = {"spawners_spawner.png^[colorize:#FF000030"},
is_ground_content = true,
groups = {cracky=1,level=2,igniter=1,not_in_creative_inventory=1},
drop = "spawners:"..mob_name.."_spawner",
on_construct = function(pos)
minetest.get_node_timer(pos):start(60)
end,
on_timer = function(pos, elapsed)
minetest.log("action", "============= timer elapsed: "..elapsed)
minetest.set_node(pos, {name="spawners:"..mob_name.."_spawner"})
end,
})
-- abm
minetest.register_abm({
nodenames = {"spawners:"..mob_name.."_spawner", "spawners:"..mob_name.."_spawner_active", "spawners:"..mob_name.."_spawner_overheat"},
neighbors = {"air"},
interval = 2.0,
chance = 20,
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.log("action", "active_object_count: "..active_object_count)
minetest.log("action", "active_object_count_wider: "..active_object_count_wider)
local random_pos = check_node_status(pos, mob_name, night_only)
if random_pos then
-- random_pos found
-- do not spawn if too many active entities in map block
-- call cooldown
if active_object_count_wider > max_obj_per_mapblock then
minetest.log("action", "************** too many mobs in area")
if node.name ~= "spawners:"..mob_name.."_spawner_overheat" then
minetest.set_node(pos, {name="spawners:"..mob_name.."_spawner_overheat"})
end
-- extend the timeout if still too many entities in map block
if node.name == "spawners:"..mob_name.."_spawner_overheat" then
minetest.log("action", "++++++++++++++ extending timeout")
minetest.get_node_timer(pos):stop()
minetest.get_node_timer(pos):start(60)
end
return
end
if node.name ~= "spawners:"..mob_name.."_spawner_active" then
minetest.set_node(pos, {name="spawners:"..mob_name.."_spawner_active"})
end
spawners.start_spawning(random_pos, 1, "spawners:"..mob_name, mod_prefix)
else
-- no random_pos found
if minetest.get_node_timer(pos):is_started() then
minetest.get_node_timer(pos):stop()
minetest.log("action", "timer stopped")
end
if node.name ~= "spawners:"..mob_name.."_spawner" then
minetest.set_node(pos, {name="spawners:"..mob_name.."_spawner"})
end
end
end
})
end
-- create all spawners and crafting recipes
for i, mob_table in ipairs(spawners.mob_tables) do
if mob_table then
local mod_prefix
if mob_table.mod_prefix_custom == "" then mod_prefix = mob_table.mod_prefix_default end
-- spawners
spawners.create(mob_table.name, mod_prefix, mob_table.dummy_size, mob_table.dummy_offset, mob_table.dummy_mesh, mob_table.dummy_texture, mob_table.night_only)
-- recipes
minetest.register_craft({
output = "spawners:"..mob_table.name.."_spawner",
recipe = {
{"default:diamondblock", "fake_fire:flint_and_steel", "default:diamondblock"},
{"xpanes:bar", "spawners:"..mob_table.name, "xpanes:bar"},
{"default:diamondblock", "xpanes:bar", "default:diamondblock"},
}
})
end
end
print ("[MOD] Spawners loaded")

13
license.txt Normal file
View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B