Compare commits
5 Commits
4bdd5a33e7
...
dfd100bd54
Author | SHA1 | Date |
---|---|---|
Hector Franqui | dfd100bd54 | |
Hector Franqui | e46e1d80c8 | |
Hector Franqui | 936f897a81 | |
Hector Franqui | 0f2157f5f5 | |
Hector Franqui | eddaeda1f5 |
|
@ -0,0 +1,483 @@
|
|||
|
||||
local spawners = {}
|
||||
spawner_count = 0
|
||||
|
||||
natspawner.on_mob_die = function(self, pos)
|
||||
if self.spawn and self.spawn.pos then
|
||||
local meta = minetest.get_meta(self.spawn.pos)
|
||||
meta:set_int("entity_killed_count", meta:get_int("entity_killed_count") + 1)
|
||||
if self.variation then
|
||||
meta:set_int("spawned_variation_count", meta:get_int("spawned_variation_count") - 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function spawn(pos, force)
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local spawner_name = meta:get_string("spawner_name")
|
||||
|
||||
if spawner_name then
|
||||
local spawner = spawners[spawner_name]
|
||||
local replacement_node_name = meta:get_string("replaced_node_name")
|
||||
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
local interval = math.random(spawner.min_spawn_interval, spawner.max_spawn_interval)
|
||||
|
||||
if replacement_node_name and replacement_node_name ~= "" then
|
||||
|
||||
-- Check if variations are forced
|
||||
local force_variation = false
|
||||
--minetest.log("Spawner data: "..dump(spawners[spawner_name].replacement_nodes[replacement_node_name]))
|
||||
if spawners[spawner_name].replacement_nodes[replacement_node_name].variations_only == true then
|
||||
force_variation = true
|
||||
end
|
||||
|
||||
-- Entity names for which we are going to search
|
||||
local search_names = {}
|
||||
local variation_names = {}
|
||||
local raw_var_names = spawners[spawner_name].replacement_nodes[replacement_node_name].variations
|
||||
if raw_var_names then
|
||||
for name,_ in pairs(raw_var_names) do
|
||||
variation_names[#variation_names + 1] = name
|
||||
end
|
||||
end
|
||||
-- If variations are forced, only take the variation names
|
||||
if force_variation == true then
|
||||
search_names = variation_names
|
||||
else
|
||||
search_names = spawners[spawner_name].entities.all_entity_names
|
||||
end
|
||||
|
||||
-- Search for nearby players and entities
|
||||
local objects = minetest.get_objects_inside_radius(pos, 10)
|
||||
local entity_count = 0
|
||||
for _,object in pairs(objects) do
|
||||
if object then
|
||||
if object:is_player() and not force then
|
||||
minetest.log("Player too close")
|
||||
-- Re-schedule
|
||||
timer:start(interval)
|
||||
minetest.log("Next spawning scheduled in "..interval.." seconds")
|
||||
return
|
||||
elseif object:get_luaentity()
|
||||
and object:get_luaentity().entity_name then
|
||||
|
||||
-- Check if the found entity has the name of one the entities
|
||||
-- that this spawner cares about
|
||||
for i = 1, #search_names do
|
||||
if object:get_luaentity().entity_name == search_names[i] then
|
||||
entity_count = entity_count + 1
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Create a list of names we are to spawn
|
||||
local spawn_names = {}
|
||||
if force_variation then
|
||||
spawn_names = variation_names
|
||||
elseif #variation_names > 0 then
|
||||
spawn_names[#spawn_names + 1] = spawners[spawner_name].entities.default
|
||||
for i = 1, #variation_names do
|
||||
spawn_names[#spawn_names + 1] = variation_names[i]
|
||||
end
|
||||
else
|
||||
spawn_names[#spawn_names + 1] = spawners[spawner_name].entities.default
|
||||
end
|
||||
|
||||
-- Choose an entity name.
|
||||
local is_variation = false
|
||||
|
||||
if force_variation == true then
|
||||
entity_name = spawn_names[math.random(1, #spawn_names)]
|
||||
--minetest.log("New entity name: "..dump(entity_name))
|
||||
is_variation = true
|
||||
minetest.log("Spawning variation "..entity_name.." (forced)")
|
||||
else
|
||||
local variation_chance = math.random(1, 10)
|
||||
if variation_chance > 7 then
|
||||
entity_name = spawn_names[math.random(1, #spawn_names)]
|
||||
-- Increase variation count
|
||||
meta:set_int("spawned_variation_count", meta:get_int("spawned_variation_count") + 1)
|
||||
is_variation = true
|
||||
minetest.log("Spawned variation count: "..meta:get_int("spawned_variation_count"))
|
||||
minetest.log("Spawning variation "..entity_name.." (not forced)")
|
||||
else
|
||||
entity_name = spawners[spawner_name].entities.default
|
||||
end
|
||||
end
|
||||
|
||||
-- Validation: enforce entity max spawn count
|
||||
local max_mob_count = spawner.max_mob_count
|
||||
|
||||
if force_variation then
|
||||
--minetest.log("Entity name: "..dump(entity_name))
|
||||
--minetest.log("Mob data: "..dump(spawners[spawner_name]
|
||||
-- .replacement_nodes[replacement_node_name]
|
||||
-- .variations[entity_name]))
|
||||
max_mob_count = spawners[spawner_name]
|
||||
.replacement_nodes[replacement_node_name]
|
||||
.variations[entity_name]
|
||||
.max_count or spawner.max_mob_count
|
||||
entity_count = meta:get_int("spawned_variation_count")
|
||||
end
|
||||
|
||||
minetest.log("Entity count: "..dump(entity_count))
|
||||
minetest.log("Max mob count: "..dump(max_mob_count))
|
||||
|
||||
if force or (entity_count <= max_mob_count) then
|
||||
|
||||
-- Spawn
|
||||
local spawn_pos = {
|
||||
x=pos.x + math.random(0, spawner.spawn_radius),
|
||||
y=pos.y+3,
|
||||
z=pos.z + math.random(0, spawner.spawn_radius)
|
||||
}
|
||||
-- Check spawn position - if not air, then spawn just above the spawner
|
||||
local spawn_node = minetest.get_node_or_nil(spawn_pos)
|
||||
if spawn_node and spawn_node.name ~= "air" then
|
||||
spawn_pos = pos
|
||||
end
|
||||
|
||||
minetest.log("Spawning "..entity_name.." at pos "..minetest.pos_to_string(spawn_pos))
|
||||
local entity = minetest.add_entity(spawn_pos, entity_name)
|
||||
if entity then
|
||||
entity:get_luaentity().entity_name = entity_name
|
||||
entity:get_luaentity().spawn = {
|
||||
pos = pos
|
||||
}
|
||||
|
||||
if is_variation == true then
|
||||
entity:get_luaentity().variation = true
|
||||
end
|
||||
end
|
||||
minetest.log("Next spawning scheduled in "..interval.." seconds")
|
||||
else
|
||||
minetest.log("Max spawn limit reached")
|
||||
-- Re-calulate interval using deactivation times
|
||||
interval = math.random(spawner.min_deactivation_time, spawner.max_deactivation_time)
|
||||
minetest.log("Deactivating spawner for "..interval.." seconds")
|
||||
end
|
||||
end
|
||||
|
||||
-- Re-schedule
|
||||
timer:start(interval)
|
||||
end
|
||||
end
|
||||
|
||||
natspawner.register_spawner = function(spawner_name, def)
|
||||
|
||||
spawners[spawner_name] = {
|
||||
entities = def.entities,
|
||||
replacement_nodes = def.node_replacement_map,
|
||||
min_player_distance = def.min_player_distance or 10,
|
||||
max_spawn_interval = def.max_spawn_interval or 300, --300
|
||||
min_spawn_interval = def.min_spawn_interval or 120, --120
|
||||
spawn_radius = def.spawn_radius or 15,
|
||||
min_kill_count = def.min_kill_count or 20,
|
||||
max_kill_count = def.max_kill_count or 35,
|
||||
min_deactivation_time = def.min_deactivation_time or 60,
|
||||
max_deactivation_time = def.max_deactivation_time or 120,
|
||||
max_mob_count = def.max_mob_count or 15,
|
||||
spawn_on_dig = def.spawn_on_dig
|
||||
}
|
||||
|
||||
-- Process all names
|
||||
local all_names = {}
|
||||
all_names[#all_names + 1] = def.entities.default
|
||||
for i = 1, #def.entities.others do
|
||||
all_names[#all_names + 1] = def.entities.others[i]
|
||||
end
|
||||
spawners[spawner_name].entities.all_entity_names = all_names
|
||||
|
||||
spawner_count = spawner_count + 1
|
||||
|
||||
-- Register all spawners
|
||||
for _,val in pairs(def.node_replacement_map) do
|
||||
|
||||
minetest.register_node("natspawner:"..spawner_name..val.name, {
|
||||
description = "Spawner",
|
||||
drop = "natspawner:"..spawner_name.."_"..val.name,
|
||||
tiles = val.tiles,
|
||||
groups = {crumbly=2, soil = 2},
|
||||
sounds = default.node_sound_sand_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("spawner_name", spawner_name)
|
||||
meta:set_int("entity_spawn_count", 0)
|
||||
meta:set_int("entity_killed_count", 0)
|
||||
meta:set_int("spawned_variation_count", 0)
|
||||
meta:set_int("max_variation_count",
|
||||
math.random(def.min_variation_count or 0, def.max_variation_count or 0))
|
||||
meta:set_int("next_deactivation_count",
|
||||
math.random(def.min_kill_count, def.max_kill_count))
|
||||
meta:set_int("next_deactivation_time",
|
||||
math.random(def.min_deactivation_time, def.max_deactivation_time))
|
||||
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
timer:start(def.min_spawn_interval)
|
||||
end,
|
||||
on_timer = function(pos)
|
||||
spawn(pos)
|
||||
end,
|
||||
on_dig = function(pos, node, digger)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local entity_killed_count = meta:get_int("entity_killed_count")
|
||||
local next_deactivation_count = meta:get_int("next_deactivation_count")
|
||||
if (entity_killed_count < next_deactivation_count) then
|
||||
if def.spawn_on_dig then
|
||||
spawn(pos, true)
|
||||
end
|
||||
minetest.chat_send_player(digger:get_player_name(), "You have killed "..entity_killed_count.." enemies!")
|
||||
return false
|
||||
else
|
||||
minetest.node_dig(pos, node, digger)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
natspawner.register_spawner("zombie", {
|
||||
entities = {
|
||||
default = "natspawner:zombie",
|
||||
others = {
|
||||
"natspawner:giant_zombie",
|
||||
"natspawner:ice_zombie",
|
||||
"natspawner:sand_zombie",
|
||||
"natspawner:sand_zombie_small"
|
||||
},
|
||||
},
|
||||
node_replacement_map = {
|
||||
["default:stone"] = {
|
||||
name = "stone_spawner",
|
||||
tiles = {"default_stone.png^[cracko:1:2", "default_stone.png", {name = "default_stone.png"}}
|
||||
},
|
||||
["default:sand"] = {
|
||||
name = "sand_spawner",
|
||||
tiles = {"default_sand.png^[cracko:1:2", "default_sand.png", {name = "default_sand.png"}},
|
||||
variations = {
|
||||
["natspawner:sand_zombie"] = {},
|
||||
["natspawner:sand_zombie_small"] = {
|
||||
max_count = 5
|
||||
}
|
||||
},
|
||||
variations_only = true
|
||||
},
|
||||
["default:desert_sand"] = {
|
||||
name = "desert_sand_spawner",
|
||||
tiles = {"default_desert_sand.png^[cracko:1:2", "default_desert_sand.png", {name = "default_desert_sand.png"}},
|
||||
variations = {
|
||||
["natspawner:sand_zombie"] = {},
|
||||
["natspawner:sand_zombie_small"] = {
|
||||
max_count = 5
|
||||
}
|
||||
},
|
||||
variations_only = true
|
||||
},
|
||||
["default:silver_sand"] = {
|
||||
name = "silver_sand_spawner",
|
||||
tiles = {"default_silver_sand.png^[cracko:1:2", "default_silver_sand.png", {name = "default_silver_sand.png"}},
|
||||
variations = {
|
||||
["natspawner:sand_zombie"] = {},
|
||||
["natspawner:sand_zombie_small"] = {
|
||||
max_count = 5
|
||||
}
|
||||
},
|
||||
variations_only = true
|
||||
},
|
||||
["default:ice"] = {
|
||||
name = "ice_spawner",
|
||||
tiles = {"default_ice.png^[cracko:1:2", "default_ice.png", {name = "default_ice.png"}},
|
||||
variations = {
|
||||
["natspawner:ice_zombie"] = {
|
||||
max_count = 15,
|
||||
min_count = 10
|
||||
}
|
||||
},
|
||||
variations_only = true
|
||||
},
|
||||
["default:snowblock"] = {
|
||||
name = "snowblock_spawner",
|
||||
tiles = {"default_snow.png^[cracko:1:2", "default_snow.png", {name = "default_snow.png"}},
|
||||
variations = {
|
||||
["natspawner:ice_zombie"] = {
|
||||
max_count = 15,
|
||||
min_count = 10
|
||||
}
|
||||
},
|
||||
variations_only = true
|
||||
},
|
||||
["default:dirt_with_grass"] = {
|
||||
name = "dirt_with_grass_spawner",
|
||||
tiles = {"default_grass.png^[cracko:1:2", "default_dirt.png", {name = "default_dirt.png^default_grass_side.png"}},
|
||||
variations = {
|
||||
["natspawner:giant_zombie"] = {
|
||||
max_count = 1
|
||||
}
|
||||
}
|
||||
},
|
||||
["default:dirt_with_dry_grass"] = {
|
||||
name = "dirt_with_dry_grass_spawner",
|
||||
tiles = {"default_dry_grass.png^[cracko:1:2", "default_dirt.png", {name = "default_dirt.png^default_dry_grass_side.png"}}
|
||||
},
|
||||
["default:dirt_with_snow"] = {
|
||||
name = "dirt_with_snow_spawner",
|
||||
tiles = {"default_snow.png^[cracko:1:2", "default_dirt.png", {name = "default_dirt.png^default_snow_side.png"}},
|
||||
variations = {
|
||||
["natspawner:ice_zombie"] = {
|
||||
max_count = 15,
|
||||
min_count = 10
|
||||
}
|
||||
},
|
||||
variations_only = true
|
||||
},
|
||||
["default:dirt_with_rainforest_litter"] = {
|
||||
name = "dirt_with_rainforest_litter_spawner",
|
||||
tiles = {"default_rainforest_litter.png^[cracko:1:2", "default_dirt.png", {name = "default_dirt.png^default_rainforest_litter_side.png"}},
|
||||
variations = {
|
||||
["natspawner:giant_zombie"] = {
|
||||
max_count = 1
|
||||
}
|
||||
}
|
||||
},
|
||||
["default:dirt_with_coniferous_litter"] = {
|
||||
name = "dirt_with_coniferous_litter_spawner",
|
||||
tiles = {"default_coniferous_litter.png^[cracko:1:2", "default_dirt.png", {name = "default_dirt.png^default_coniferous_litter_side.png"}}
|
||||
},
|
||||
["default:permafrost"] = {
|
||||
name = "permafrost_spawner",
|
||||
tiles = {"default_permafrost.png^[cracko:1:2", "default_permafrost.png", {name = "default_permafrost.png"}},
|
||||
variations = {
|
||||
["natspawner:ice_zombie"] = {}
|
||||
}
|
||||
},
|
||||
["default:permafrost_with_stones"] = {
|
||||
name = "permafrost_with_stones_spawner",
|
||||
tiles = {"default_permafrost.png^default_stones.png^[cracko:1:2", "default_permafrost.png", {name = "default_permafrost.png"}},
|
||||
variations = {
|
||||
["natspawner:ice_zombie"] = {}
|
||||
}
|
||||
},
|
||||
["default:permafrost_with_moss"] = {
|
||||
name = "permafrost_with_moss_spawner",
|
||||
tiles = {"default_moss.png^[cracko:1:2", "default_permafrost.png", {name = "default_permafrost.png^default_moss_side.png"}},
|
||||
variations = {
|
||||
["natspawner:ice_zombie"] = {}
|
||||
}
|
||||
}
|
||||
},
|
||||
min_player_distance = 5, --20
|
||||
max_mob_count = 5, --15
|
||||
max_spawn_interval = 10, --300
|
||||
min_spawn_interval = 5, --120
|
||||
spawn_radius = 5,
|
||||
min_kill_count = 5,
|
||||
max_kill_count = 10,
|
||||
min_deactivation_time = 5,
|
||||
max_deactivation_time = 5,
|
||||
spawn_on_dig = true
|
||||
})
|
||||
|
||||
local perl1 = {SEED1 = 9130, OCTA1 = 3, PERS1 = 0.5, SCAL1 = 250} -- Values should match minetest mapgen V6 desert noise.
|
||||
|
||||
local function hlp_fnct(pos, name)
|
||||
local n = minetest.get_node_or_nil(pos)
|
||||
if n and n.name and n.name == name then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
local function ground(pos, old)
|
||||
local p2 = pos
|
||||
while hlp_fnct(p2, "air") do
|
||||
p2.y = p2.y -1
|
||||
end
|
||||
if p2.y < old.y then
|
||||
return p2
|
||||
else
|
||||
return old
|
||||
end
|
||||
end
|
||||
|
||||
local function is_air_or_buildable(node)
|
||||
return node
|
||||
and node.name
|
||||
and (node.name == "air"
|
||||
or minetest.registered_nodes[node.name].buildable_to == true)
|
||||
end
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
|
||||
if spawner_count == 0 then return end
|
||||
|
||||
--minetest.log("Max pos: "..minetest.pos_to_string(maxp))
|
||||
--minetest.log("Min pos: "..minetest.pos_to_string(minp))
|
||||
|
||||
local middle_pos = { x=(maxp.x + minp.x)/2, y=(maxp.y + minp.y)/2 , z=(maxp.z + minp.z)/2 }
|
||||
|
||||
--minetest.log("Mid pos: "..minetest.pos_to_string(middle_pos))
|
||||
|
||||
local spawn_pos = nil
|
||||
spawn_pos = minetest.find_node_near(middle_pos, 40, {
|
||||
"default:dirt_with_grass",
|
||||
"default:dirt_with_snow",
|
||||
"default:dirt_with_coniferous_litter",
|
||||
"default:dirt_with_rainforest_litter",
|
||||
"default:permafrost",
|
||||
"default:permafrost_with_moss",
|
||||
"default:permafrost_with_stones",
|
||||
"default:sand",
|
||||
"default:desert_sand",
|
||||
"default:silver_sand"
|
||||
})
|
||||
|
||||
if (spawn_pos ~= nil) then
|
||||
minetest.log("Candidate pos: "..minetest.pos_to_string(spawn_pos))
|
||||
-- Check pos above
|
||||
local node_above = minetest.get_node_or_nil({x=spawn_pos.x, y=spawn_pos.y+1, z=spawn_pos.z})
|
||||
if node_above and node_above.name then
|
||||
if (is_air_or_buildable(node_above)) then
|
||||
minetest.log("Found a good pos at: "..minetest.pos_to_string(spawn_pos))
|
||||
|
||||
-- Choose a spawner
|
||||
for i = 1, spawner_count do
|
||||
local spawner_name = next(spawners)
|
||||
local chance = math.random(1, spawner_count)
|
||||
|
||||
if chance == i then
|
||||
-- Create spawner
|
||||
minetest.after(0.8, function(spawner_name, pos)
|
||||
local node_map = spawners[spawner_name].replacement_nodes
|
||||
local node_to_replace = minetest.get_node(pos)
|
||||
if node_map[node_to_replace.name] then
|
||||
minetest.log("Replacing "..node_to_replace.name.." with "..spawner_name)
|
||||
minetest.log("Creating advanced spawner at "..minetest.pos_to_string(pos))
|
||||
minetest.set_node(pos, {name="natspawner:"..spawner_name..node_map[node_to_replace.name].name})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("replaced_node_name", node_to_replace.name)
|
||||
else
|
||||
minetest.log("Unable to find replacement for node '"..dump(node_to_replace.name).."'")
|
||||
end
|
||||
end, spawner_name, spawn_pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
--mobs:register_egg("natspawner:zombie", "Zombie", "zombie_head.png", 0)
|
||||
|
||||
minetest.register_craftitem("natspawner:rotten_flesh", {
|
||||
description = "Rotten Flesh",
|
||||
inventory_image = "mobs_rotten_flesh.png",
|
||||
on_use = minetest.item_eat(-5),
|
||||
})
|
405
init.lua
405
init.lua
|
@ -1,406 +1,7 @@
|
|||
|
||||
natspawner = {}
|
||||
|
||||
local spawners = {}
|
||||
spawner_count = 0
|
||||
local path = minetest.get_modpath("natspawner")
|
||||
|
||||
mobs:register_mob("natspawner:zombie", {
|
||||
type = "monster",
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
damage = 4,
|
||||
reach = 2,
|
||||
hp_min = 12,
|
||||
hp_max = 35,
|
||||
armor = 150,
|
||||
collisionbox = {-0.25, -1, -0.3, 0.25, 0.75, 0.3},
|
||||
visual = "mesh",
|
||||
mesh = "creatures_mob.x",
|
||||
textures = {
|
||||
{"mobs_zombie.png"},
|
||||
},
|
||||
visual_size = {x=1, y=1},
|
||||
makes_footstep_sound = true,
|
||||
sounds = {
|
||||
random = "mobs_zombie.1",
|
||||
damage = "mobs_zombie_hit",
|
||||
attack = "mobs_zombie.3",
|
||||
death = "mobs_zombie_death",
|
||||
},
|
||||
walk_velocity = 0.5,
|
||||
run_velocity = 1.75,
|
||||
jump = true,
|
||||
floats = 0,
|
||||
view_range = 12,
|
||||
drops = {
|
||||
{name = "zombie:rotten_flesh",
|
||||
chance = 2, min = 3, max = 5,},
|
||||
},
|
||||
water_damage = 0,
|
||||
lava_damage = 1,
|
||||
light_damage = 0,
|
||||
animation = {
|
||||
speed_normal = 10, speed_run = 15,
|
||||
stand_start = 0, stand_end = 79,
|
||||
walk_start = 168, walk_end = 188,
|
||||
run_start = 168, run_end = 188,
|
||||
-- punch_start = 168, punch_end = 188,
|
||||
},
|
||||
on_rightclick = function(self, clicker)
|
||||
minetest.log(dump(self))
|
||||
end,
|
||||
on_die = function(self, pos)
|
||||
if self.spawn and self.spawn.pos then
|
||||
local meta = minetest.get_meta(self.spawn.pos)
|
||||
meta:set_int("entity_killed_count", meta:get_int("entity_killed_count") + 1)
|
||||
if self.variation then meta:set_int("spawned_variation_count", 0) end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
local function spawn(pos, force)
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local spawner_name = meta:get_string("spawner_name")
|
||||
|
||||
if spawner_name then
|
||||
local spawner = spawners[spawner_name]
|
||||
local replacement_node_name = meta:get_string("replaced_node_name")
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
local interval = math.random(spawner.min_spawn_interval, spawner.max_spawn_interval)
|
||||
|
||||
-- Check for players nearby
|
||||
local objects = minetest.get_objects_inside_radius(pos, spawner.min_player_distance)
|
||||
|
||||
--local entity_spawn_count = meta:get_int("entity_spawn_count")
|
||||
|
||||
local entity_count = 0
|
||||
for _,object in pairs(objects) do
|
||||
if object then
|
||||
if object:is_player() and not force then
|
||||
minetest.log("Player too close")
|
||||
-- Re-schedule
|
||||
timer:start(interval)
|
||||
minetest.log("Next spawning scheduled in "..interval.." seconds")
|
||||
return
|
||||
elseif object:get_luaentity()
|
||||
and object:get_luaentity().entity_name
|
||||
and object:get_luaentity().entity_name == spawner.entity_name then
|
||||
entity_count = entity_count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check for amount nearby
|
||||
if force or (entity_count <= spawner.max_mob_count) then
|
||||
-- Spawn
|
||||
local spawn_pos = {x=pos.x + math.random(0, spawner.spawn_radius), y=pos.y+3, z=pos.z + math.random(0, spawner.spawn_radius)}
|
||||
-- Check spawn position - if not air, then spawn just above the spawner
|
||||
local spawn_node = minetest.get_node_or_nil(spawn_pos)
|
||||
if spawn_node and spawn_node.name ~= "air" then
|
||||
spawn_pos = pos
|
||||
end
|
||||
minetest.log("Spawning "..spawner.entity_name.." at pos "..minetest.pos_to_string(spawn_pos))
|
||||
local entity = minetest.add_entity(spawn_pos, spawner.entity_name)
|
||||
if entity then
|
||||
entity:get_luaentity().entity_name = spawner.entity_name
|
||||
entity:get_luaentity().spawn = {
|
||||
pos = pos
|
||||
}
|
||||
|
||||
-- Set textures if requested
|
||||
minetest.log(replacement_node_name)
|
||||
if replacement_node_name and replacement_node_name ~= "" then
|
||||
if spawners[spawner_name].replacement_nodes[replacement_node_name].textures then
|
||||
entity:set_properties({
|
||||
textures = spawners[spawner_name].replacement_nodes[replacement_node_name].textures
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Spawn a variation with 30% chance
|
||||
local variation_chance = math.random(1, 10)
|
||||
if variation_chance > 7
|
||||
and meta:get_int("spawned_variation_count") == 0
|
||||
and spawners[spawner_name].variations then
|
||||
|
||||
-- Choose a variation
|
||||
local variations = spawners[spawner_name].variations
|
||||
local index = math.random(1, #variations)
|
||||
|
||||
entity:get_luaentity().variation = true
|
||||
-- Velocity
|
||||
entity:get_luaentity().walk_velocity = variations[index].walk_velocity
|
||||
entity:get_luaentity().run_velocity = variations[index].run_velocity
|
||||
-- View range
|
||||
entity:get_luaentity().view_range = variations[index].view_range
|
||||
-- HP
|
||||
local hp = math.random(variations[index].hp_min, variations[index].hp_max)
|
||||
entity:get_luaentity().hp_max = hp
|
||||
entity:get_luaentity().health = hp
|
||||
entity:get_luaentity().old_health = hp
|
||||
-- Damage
|
||||
entity:get_luaentity().damage = variations[index].damage
|
||||
entity:get_luaentity().reach = variations[index].reach
|
||||
-- Armor
|
||||
entity:set_armor_groups({immortal = 1, fleshy = variations[index].armor})
|
||||
entity:get_luaentity().knock_back = variations[index].knock_back
|
||||
-- Other properties
|
||||
entity:set_properties({
|
||||
visual_size = variations[index].visual_size,
|
||||
collisionbox = variations[index].collisionbox,
|
||||
stepheight = variations[index].stepheight
|
||||
})
|
||||
-- Increase variation count
|
||||
meta:set_int("spawned_variation_count", meta:get_int("spawned_variation_count") + 1)
|
||||
|
||||
end
|
||||
minetest.log("Next spawning scheduled in "..interval.." seconds")
|
||||
end
|
||||
else
|
||||
minetest.log("Max spawn limit reached")
|
||||
-- Re-calulate interval using deactivation times
|
||||
interval = math.random(spawner.min_deactivation_time, spawner.max_deactivation_time)
|
||||
minetest.log("Deactivating spawner for "..interval.." seconds")
|
||||
end
|
||||
|
||||
-- Re-schedule
|
||||
timer:start(interval)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
natspawner.register_spawner = function(spawner_name, def)
|
||||
|
||||
spawners[spawner_name] = {
|
||||
entity_name = def.entity_name,
|
||||
variations = def.entity_variations,
|
||||
replacement_nodes = def.node_replacement_map,
|
||||
min_player_distance = def.min_player_distance or 10,
|
||||
max_spawn_interval = def.max_spawn_interval or 300, --300
|
||||
min_spawn_interval = def.min_spawn_interval or 120, --120
|
||||
spawn_radius = def.spawn_radius or 15,
|
||||
min_kill_count = def.min_kill_count or 20,
|
||||
max_kill_count = def.max_kill_count or 35,
|
||||
min_deactivation_time = def.min_deactivation_time or 60,
|
||||
max_deactivation_time = def.max_deactivation_time or 120,
|
||||
max_mob_count = def.max_mob_count or 40,
|
||||
spawn_on_dig = def.spawn_on_dig
|
||||
}
|
||||
spawner_count = spawner_count + 1
|
||||
|
||||
-- Register all spawners
|
||||
for _,val in pairs(def.node_replacement_map) do
|
||||
|
||||
minetest.register_node("natspawner:"..spawner_name..val.name, {
|
||||
description = "Spawner",
|
||||
drop = "natspawner:"..spawner_name.."_"..val.name,
|
||||
tiles = val.tiles,
|
||||
groups = {crumbly=2, soil = 2},
|
||||
sounds = default.node_sound_sand_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("spawner_name", spawner_name)
|
||||
meta:set_int("entity_spawn_count", 0)
|
||||
meta:set_int("entity_killed_count", 0)
|
||||
meta:set_int("spawned_variation_count", 0)
|
||||
meta:set_int("next_deactivation_count", math.random(def.min_kill_count, def.max_kill_count))
|
||||
meta:set_int("next_deactivation_time", math.random(def.min_deactivation_time, def.max_deactivation_time))
|
||||
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
timer:start(def.min_spawn_interval)
|
||||
end,
|
||||
on_timer = function(pos)
|
||||
spawn(pos)
|
||||
end,
|
||||
on_dig = function(pos, node, digger)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local entity_killed_count = meta:get_int("entity_killed_count")
|
||||
local next_deactivation_count = meta:get_int("next_deactivation_count")
|
||||
if (entity_killed_count < next_deactivation_count) then
|
||||
if spawn_on_dig then
|
||||
spawn(pos, true)
|
||||
end
|
||||
minetest.chat_send_player(digger:get_player_name(), "You have killed "..entity_killed_count.." enemies!")
|
||||
return false
|
||||
else
|
||||
minetest.node_dig(pos, node, digger)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
natspawner.register_spawner("zombie", {
|
||||
entity_name = "natspawner:zombie",
|
||||
entity_variations = {
|
||||
-- Giant zombie
|
||||
{
|
||||
visual_size = {x=2.75, y=2.5, z=2.75},
|
||||
collisionbox = {-0.63, -2.5, -0.75, 0.63, 1.88, 0.75},
|
||||
stepheight = 2,
|
||||
walk_velocity = 1.5,
|
||||
run_velocity = 3,
|
||||
view_range = 20,
|
||||
hp_min = 215,
|
||||
hp_max = 315,
|
||||
damage = 12,
|
||||
reach = 4,
|
||||
armor = 325,
|
||||
knock_back = false,
|
||||
}
|
||||
},
|
||||
node_replacement_map = {
|
||||
["default:stone"] = {name = "stone_spawner", tiles = {"default_stone.png^[cracko:1:2", "default_stone.png", {name = "default_stone.png"}}},
|
||||
["default:sand"] = {name = "sand_spawner", tiles = {"default_sand.png^[cracko:1:2", "default_sand.png", {name = "default_sand.png"}}},
|
||||
["default:desert_sand"] = {name = "desert_sand_spawner", tiles = {"default_desert_sand.png^[cracko:1:2", "default_desert_sand.png", {name = "default_desert_sand.png"}}},
|
||||
["default:ice"] = {name = "ice_spawner", tiles = {"default_ice.png^[cracko:1:2", "default_ice.png", {name = "default_ice.png"}}},
|
||||
["default:snowblock"] = {name = "snowblock_spawner", tiles = {"default_snow.png^[cracko:1:2", "default_snow.png", {name = "default_snow.png"}}},
|
||||
["default:dirt_with_grass"] = {name = "dirt_with_grass_spawner", tiles = {"default_grass.png^[cracko:1:2", "default_dirt.png", {name = "default_dirt.png^default_grass_side.png"}}},
|
||||
["default:dirt_with_dry_grass"] = {name = "dirt_with_dry_grass_spawner", tiles = {"default_dry_grass.png^[cracko:1:2", "default_dirt.png", {name = "default_dirt.png^default_dry_grass_side.png"}}},
|
||||
["default:dirt_with_snow"] = {name = "dirt_with_snow_spawner", tiles = {"default_snow.png^[cracko:1:2", "default_dirt.png", {name = "default_dirt.png^default_snow_side.png"}}, textures = {"mobs_zombie_ice.png"}},
|
||||
["default:dirt_with_rainforest_litter"] = {name = "dirt_with_rainforest_litter_spawner", tiles = {"default_rainforest_litter.png^[cracko:1:2", "default_dirt.png", {name = "default_dirt.png^default_rainforest_litter_side.png"}}},
|
||||
["default:dirt_with_coniferous_litter"] = {name = "dirt_with_coniferous_litter_spawner", tiles = {"default_coniferous_litter.png^[cracko:1:2", "default_dirt.png", {name = "default_dirt.png^default_coniferous_litter_side.png"}}},
|
||||
["default:permafrost"] = {name = "permafrost_spawner", tiles = {"default_permafrost.png^[cracko:1:2", "default_permafrost.png", {name = "default_permafrost.png"}}},
|
||||
["default:permafrost_with_stones"] = {name = "permafrost_with_stones_spawner", tiles = {"default_permafrost.png^default_stones.png^[cracko:1:2", "default_permafrost.png", {name = "default_permafrost.png"}}},
|
||||
["default:permafrost_with_moss"] = {name = "permafrost_with_moss_spawner", tiles = {"default_moss.png^[cracko:1:2", "default_permafrost.png", {name = "default_permafrost.png^default_moss_side.png"}}}
|
||||
},
|
||||
min_player_distance = 5, --20
|
||||
max_mob_count = 5, --15
|
||||
max_spawn_interval = 10, --300
|
||||
min_spawn_interval = 5, --120
|
||||
spawn_radius = 5,
|
||||
min_kill_count = 5,
|
||||
max_kill_count = 10,
|
||||
min_deactivation_time = 5,
|
||||
max_deactivation_time = 5,
|
||||
spawn_on_dig = true
|
||||
})
|
||||
|
||||
local perl1 = {SEED1 = 9130, OCTA1 = 3, PERS1 = 0.5, SCAL1 = 250} -- Values should match minetest mapgen V6 desert noise.
|
||||
|
||||
local function hlp_fnct(pos, name)
|
||||
local n = minetest.get_node_or_nil(pos)
|
||||
if n and n.name and n.name == name then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
local function ground(pos, old)
|
||||
local p2 = pos
|
||||
while hlp_fnct(p2, "air") do
|
||||
p2.y = p2.y -1
|
||||
end
|
||||
if p2.y < old.y then
|
||||
return p2
|
||||
else
|
||||
return old
|
||||
end
|
||||
end
|
||||
|
||||
local function is_air_or_buildable(node)
|
||||
return node
|
||||
and node.name
|
||||
and (node.name == "air"
|
||||
or minetest.registered_nodes[node.name].buildable_to == true)
|
||||
end
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
|
||||
-- No spawners registered
|
||||
if spawner_count == 0 then return end
|
||||
|
||||
if maxp.y < 0 then return end
|
||||
math.randomseed(seed)
|
||||
local cnt = 0
|
||||
|
||||
local perlin1 = minetest.env:get_perlin(perl1.SEED1, perl1.OCTA1, perl1.PERS1, perl1.SCAL1)
|
||||
local noise1 = perlin1:get2d({x=minp.x,y=minp.y})--,z=minp.z})
|
||||
|
||||
if noise1 > 0.25 or noise1 < -0.26 then
|
||||
local mpos = {x=math.random(minp.x,maxp.x), y=math.random(minp.y,maxp.y), z=math.random(minp.z,maxp.z)}
|
||||
|
||||
local p2 = minetest.find_node_near(mpos, 25, {
|
||||
"default:dirt_with_grass",
|
||||
"default:dirt_with_snow",
|
||||
"default:dirt_with_coniferous_litter"
|
||||
})
|
||||
while p2 == nil and cnt < 10 do
|
||||
cnt = cnt+1
|
||||
mpos = {x=math.random(minp.x,maxp.x), y=math.random(minp.y,maxp.y), z=math.random(minp.z,maxp.z)}
|
||||
p2 = minetest.find_node_near(mpos, 25, {
|
||||
"default:dirt_with_grass",
|
||||
"default:dirt_with_snow",
|
||||
"default:dirt_with_coniferous_litter"
|
||||
})
|
||||
end
|
||||
if p2 == nil then return end
|
||||
if p2.y < 0 then return end
|
||||
|
||||
local off = 0
|
||||
|
||||
-- Simpler finding routine - check if node immediately above is air,
|
||||
-- and if node 16 blocks above is air
|
||||
minetest.log("Checking pos to spawn: "..minetest.pos_to_string(p2))
|
||||
local next_node_above = minetest.get_node_or_nil({x=p2.x, y=p2.y+1, z=p2.z})
|
||||
minetest.log("Found next node above: "..dump(next_node_above))
|
||||
local next_mapblock_above = minetest.get_node_or_nil({x=p2.x, y=p2.y+16, z=p2.z})
|
||||
minetest.log("Found next node above mapblock: "..dump(next_mapblock_above))
|
||||
|
||||
if is_air_or_buildable(next_node_above) and is_air_or_buildable(next_mapblock_above) then
|
||||
|
||||
-- Choose a spawner
|
||||
for i = 1, spawner_count do
|
||||
local spawner_name = next(spawners)
|
||||
local chance = math.random(1, spawner_count)
|
||||
|
||||
if chance == i then
|
||||
-- Create spawner
|
||||
minetest.after(0.8, function(spawner_name, pos)
|
||||
local node_map = spawners[spawner_name].replacement_nodes
|
||||
minetest.log("Creating advanced spawner at "..minetest.pos_to_string(pos))
|
||||
local node_to_replace = minetest.get_node(pos)
|
||||
minetest.log("Replacing "..node_to_replace.name.." with "..spawner_name)
|
||||
minetest.set_node(pos, {name="natspawner:"..spawner_name..node_map[node_to_replace.name].name})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("replaced_node_name", node_to_replace.name)
|
||||
end, spawner_name, p2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- local opos1 = {x=p2.x+22,y=p2.y-1,z=p2.z+22}
|
||||
-- local opos2 = {x=p2.x+22,y=p2.y-1,z=p2.z}
|
||||
-- local opos3 = {x=p2.x,y=p2.y-1,z=p2.z+22}
|
||||
-- local opos1_n = minetest.get_node_or_nil(opos1)
|
||||
-- local opos2_n = minetest.get_node_or_nil(opos2)
|
||||
-- local opos3_n = minetest.get_node_or_nil(opos3)
|
||||
-- if opos1_n and opos1_n.name and opos1_n.name == "air" then
|
||||
-- p2 = ground(opos1, p2)
|
||||
-- end
|
||||
-- if opos2_n and opos2_n.name and opos2_n.name == "air" then
|
||||
-- p2 = ground(opos2, p2)
|
||||
-- end
|
||||
-- if opos3_n and opos3_n.name and opos3_n.name == "air" then
|
||||
-- p2 = ground(opos3, p2)
|
||||
-- end
|
||||
-- p2.y = p2.y - 3
|
||||
-- if p2.y < 0 then p2.y = 0 end
|
||||
--if minetest.find_node_near(p2, 25, {"default:water_source"}) ~= nil or minetest.find_node_near(p2, 22, {"default:dirt_with_grass"}) ~= nil or minetest.find_node_near(p2, 52, {"default:sandstonebrick"}) ~= nil then return end
|
||||
|
||||
--minetest.after(0.8,make,p2)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
mobs:register_egg("natspawner:zombie", "Zombie", "zombie_head.png", 0)
|
||||
|
||||
minetest.register_craftitem("natspawner:rotten_flesh", {
|
||||
description = "Rotten Flesh",
|
||||
inventory_image = "mobs_rotten_flesh.png",
|
||||
on_use = minetest.item_eat(-5),
|
||||
})
|
||||
dofile(path .. "/api.lua")
|
||||
dofile(path .. "/mobs.lua")
|
||||
|
|
|
@ -0,0 +1,417 @@
|
|||
-- Entity registrations
|
||||
|
||||
local function ice_breaking_effect(pos)
|
||||
minetest.add_particlespawner({
|
||||
amount = math.random(15, 25),
|
||||
|
||||
time = 0.5,
|
||||
-- Lifespan of spawner in seconds.
|
||||
-- If time is 0 spawner has infinite lifespan and spawns the `amount` on
|
||||
-- a per-second basis.
|
||||
minpos = {x=pos.x-1, y=pos.y+1, z=pos.z-1},
|
||||
maxpos = {x=pos.x+1, y=pos.y+1, z=pos.z+1},
|
||||
minvel = {x = -2.5, y = -2.5, z = -2.5},
|
||||
maxvel = {x = 2.5, y = 2.5, z = 2.5},
|
||||
|
||||
|
||||
-- minpos = {x=pos.x-1, y=pos.x-1, z=pos.x-1},
|
||||
-- maxpos = {x=pos.x+1, y=pos.x+1, z=pos.x+1},
|
||||
-- minvel = {x=0, y=0, z=0},
|
||||
-- maxvel = {x=0, y=0, z=0},
|
||||
minacc = {x=0, y=-10, z=0},
|
||||
maxacc = {x=0, y=-10, z=0},
|
||||
minexptime = 0.5,
|
||||
maxexptime = 1,
|
||||
minsize = 0.5,
|
||||
maxsize = 1,
|
||||
texture = "frozen_ice.png"
|
||||
})
|
||||
end
|
||||
|
||||
local function normal_attack(self, to_attack)
|
||||
--set_animation(self, "punch")
|
||||
|
||||
-- local p2 = to_attack
|
||||
-- local s2 = self.object:get_pos()
|
||||
|
||||
-- p2.y = p2.y + .5
|
||||
-- s2.y = s2.y + .5
|
||||
|
||||
--local line = minetest.line_of_sight(p2, s2)
|
||||
--minetest.log(dump(line))
|
||||
|
||||
--r, pos = minetest.line_of_sight(p2, s2, stepsize)
|
||||
--if line_of_sight(self, p2, s2) == true then
|
||||
|
||||
-- play attack sound
|
||||
--mob_sound(self, self.sounds.attack)
|
||||
|
||||
-- punch player (or what player is attached to)
|
||||
local attached = self.attack:get_attach()
|
||||
if attached then
|
||||
self.attack = attached
|
||||
end
|
||||
self.attack:punch(self.object, 1.0, {
|
||||
full_punch_interval = 1.0,
|
||||
damage_groups = {fleshy = self.damage}
|
||||
}, nil)
|
||||
--end
|
||||
|
||||
end
|
||||
|
||||
-- Default zombie
|
||||
mobs:register_mob("natspawner:zombie", {
|
||||
type = "monster",
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
damage = 4,
|
||||
reach = 2,
|
||||
hp_min = 12,
|
||||
hp_max = 35,
|
||||
armor = 150,
|
||||
collisionbox = {-0.25, -1, -0.3, 0.25, 0.75, 0.3},
|
||||
visual = "mesh",
|
||||
mesh = "creatures_mob.x",
|
||||
textures = {
|
||||
{"mobs_zombie.png"},
|
||||
},
|
||||
visual_size = {x=1, y=1},
|
||||
makes_footstep_sound = true,
|
||||
sounds = {
|
||||
random = "mobs_zombie.1",
|
||||
damage = "mobs_zombie_hit",
|
||||
attack = "mobs_zombie.3",
|
||||
death = "mobs_zombie_death",
|
||||
},
|
||||
walk_velocity = 0.5,
|
||||
run_velocity = 1.75,
|
||||
jump = true,
|
||||
floats = 0,
|
||||
view_range = 12,
|
||||
drops = {
|
||||
{name = "zombie:rotten_flesh",
|
||||
chance = 2, min = 3, max = 5,},
|
||||
},
|
||||
water_damage = 0,
|
||||
lava_damage = 1,
|
||||
light_damage = 0,
|
||||
animation = {
|
||||
speed_normal = 10, speed_run = 15,
|
||||
stand_start = 0, stand_end = 79,
|
||||
walk_start = 168, walk_end = 188,
|
||||
run_start = 168, run_end = 188,
|
||||
-- punch_start = 168, punch_end = 188,
|
||||
},
|
||||
on_rightclick = function(self, clicker)
|
||||
minetest.log(dump(self))
|
||||
end,
|
||||
on_die = natspawner.on_mob_die
|
||||
})
|
||||
|
||||
mobs:register_mob("natspawner:giant_zombie", {
|
||||
type = "monster",
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
damage = 4,
|
||||
reach = 2,
|
||||
hp_min = 12,
|
||||
hp_max = 35,
|
||||
armor = 150,
|
||||
collisionbox = {-0.625, -2.5, -2.8, 0.625, 1.875, 2.8},
|
||||
visual = "mesh",
|
||||
mesh = "creatures_mob.x",
|
||||
textures = {
|
||||
{"mobs_zombie.png"},
|
||||
},
|
||||
visual_size = {x=2.5, y=2.5, z=2.5},
|
||||
makes_footstep_sound = true,
|
||||
sounds = {
|
||||
random = "mobs_zombie.1",
|
||||
damage = "mobs_zombie_hit",
|
||||
attack = "mobs_zombie.3",
|
||||
death = "mobs_zombie_death",
|
||||
},
|
||||
walk_velocity = 0.5,
|
||||
run_velocity = 1.75,
|
||||
jump = true,
|
||||
floats = 0,
|
||||
view_range = 12,
|
||||
drops = {
|
||||
{name = "zombie:rotten_flesh",
|
||||
chance = 2, min = 3, max = 5,},
|
||||
},
|
||||
water_damage = 0,
|
||||
lava_damage = 1,
|
||||
light_damage = 0,
|
||||
animation = {
|
||||
speed_normal = 10, speed_run = 15,
|
||||
stand_start = 0, stand_end = 79,
|
||||
walk_start = 168, walk_end = 188,
|
||||
run_start = 168, run_end = 188,
|
||||
-- punch_start = 168, punch_end = 188,
|
||||
},
|
||||
on_rightclick = function(self, clicker)
|
||||
minetest.log(dump(self))
|
||||
end,
|
||||
on_die = natspawner.on_mob_die
|
||||
})
|
||||
|
||||
mobs:register_mob("natspawner:ice_zombie", {
|
||||
type = "monster",
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
damage = 4,
|
||||
reach = 2,
|
||||
hp_min = 12,
|
||||
hp_max = 35,
|
||||
armor = 150,
|
||||
collisionbox = {-0.25, -1, -0.3, 0.25, 0.75, 0.3},
|
||||
visual = "mesh",
|
||||
mesh = "creatures_mob.x",
|
||||
textures = {
|
||||
{"mobs_zombie_ice.png"},
|
||||
},
|
||||
visual_size = {x=1, y=1},
|
||||
makes_footstep_sound = true,
|
||||
sounds = {
|
||||
random = "mobs_zombie",
|
||||
damage = "mobs_zombie_ice_hit",
|
||||
attack = "mobs_zombie",
|
||||
death = "mobs_zombie_death",
|
||||
},
|
||||
walk_velocity = 0.5,
|
||||
run_velocity = 1.75,
|
||||
jump = true,
|
||||
floats = 0,
|
||||
view_range = 12,
|
||||
drops = {
|
||||
{name = "zombie:rotten_flesh",
|
||||
chance = 2, min = 3, max = 5,},
|
||||
},
|
||||
water_damage = 0,
|
||||
lava_damage = 1,
|
||||
light_damage = 0,
|
||||
animation = {
|
||||
speed_normal = 10, speed_run = 15,
|
||||
stand_start = 0, stand_end = 79,
|
||||
walk_start = 168, walk_end = 188,
|
||||
run_start = 168, run_end = 188,
|
||||
-- punch_start = 168, punch_end = 188,
|
||||
},
|
||||
blood_amount = 4,
|
||||
blood_texture = "default_ice.png",
|
||||
after_activate = function(self)
|
||||
self.ice_attack_timer = 0
|
||||
end,
|
||||
on_rightclick = function(self, clicker)
|
||||
minetest.log(dump(self))
|
||||
end,
|
||||
on_die = natspawner.on_mob_die,
|
||||
custom_attack = function(self, to_attack)
|
||||
|
||||
self.ice_attack_timer = self.ice_attack_timer + 1
|
||||
|
||||
if self.ice_attack_timer >= 3 then
|
||||
self.ice_attack_timer = 0
|
||||
local chance = math.random(1, 5)
|
||||
if chance > 3 then
|
||||
-- TODO: Add particle effects
|
||||
minetest.log("Ice")
|
||||
minetest.set_node(to_attack, {name="natspawner:freezing_ice"})
|
||||
minetest.set_node({x=to_attack.x, y=to_attack.y+1, z=to_attack.z}, {name="natspawner:freezing_ice"})
|
||||
-- Remove node
|
||||
minetest.after(math.random(1,2), function(pos)
|
||||
local pos_above = {x=pos.x, y=pos.y+1, z=pos.z}
|
||||
minetest.sound_play("default_break_glass")
|
||||
ice_breaking_effect(pos)
|
||||
ice_breaking_effect(pos_above)
|
||||
minetest.set_node(pos, {name="air"})
|
||||
minetest.set_node(pos_above, {name="air"})
|
||||
end, to_attack)
|
||||
end
|
||||
end
|
||||
|
||||
normal_attack(self, to_attack)
|
||||
end
|
||||
})
|
||||
|
||||
mobs:register_mob("natspawner:sand_zombie_small", {
|
||||
type = "monster",
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
damage = 6,
|
||||
reach = 2,
|
||||
hp_min = 12,
|
||||
hp_max = 35,
|
||||
armor = 100,
|
||||
collisionbox = {-0.1625, -0.65, -0.195, 0.1625, 0.4875, 0.195},
|
||||
visual = "mesh",
|
||||
mesh = "creatures_mob.x",
|
||||
textures = {
|
||||
{"mobs_zombie_sand.png"},
|
||||
},
|
||||
visual_size = {x=0.675, y=0.65, z=0.675},
|
||||
makes_footstep_sound = true,
|
||||
sounds = {
|
||||
random = "mobs_zombie",
|
||||
damage = "mobs_zombie_sand_hit",
|
||||
attack = "mobs_zombie",
|
||||
death = "mobs_zombie_death",
|
||||
},
|
||||
walk_velocity = 1.5,
|
||||
run_velocity = 3,
|
||||
jump = true,
|
||||
floats = 0,
|
||||
view_range = 12,
|
||||
drops = {
|
||||
{name = "zombie:rotten_flesh",
|
||||
chance = 2, min = 3, max = 5,},
|
||||
},
|
||||
water_damage = 0,
|
||||
lava_damage = 1,
|
||||
light_damage = 0,
|
||||
animation = {
|
||||
speed_normal = 10, speed_run = 15,
|
||||
stand_start = 0, stand_end = 79,
|
||||
walk_start = 168, walk_end = 188,
|
||||
run_start = 168, run_end = 188,
|
||||
-- punch_start = 168, punch_end = 188,
|
||||
},
|
||||
blood_amount = 7,
|
||||
blood_texture = "default_sand.png",
|
||||
on_rightclick = function(self, clicker)
|
||||
minetest.log(dump(self))
|
||||
end,
|
||||
on_die = natspawner.on_mob_die
|
||||
})
|
||||
|
||||
mobs:register_mob("natspawner:sand_zombie", {
|
||||
type = "monster",
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
damage = 4,
|
||||
reach = 2,
|
||||
hp_min = 12,
|
||||
hp_max = 35,
|
||||
armor = 150,
|
||||
collisionbox = {-0.25, -1, -0.3, 0.25, 0.75, 0.3},
|
||||
visual = "mesh",
|
||||
mesh = "creatures_mob.x",
|
||||
textures = {
|
||||
{"mobs_zombie_sand.png"},
|
||||
},
|
||||
visual_size = {x=1, y=1},
|
||||
makes_footstep_sound = true,
|
||||
sounds = {
|
||||
random = "mobs_zombie",
|
||||
damage = "mobs_zombie_sand_hit",--"mobs_zombie_hit",
|
||||
attack = "mobs_zombie",
|
||||
death = "mobs_zombie_death",
|
||||
},
|
||||
walk_velocity = 0.5,
|
||||
run_velocity = 1.75,
|
||||
jump = true,
|
||||
floats = 0,
|
||||
view_range = 12,
|
||||
drops = {
|
||||
{name = "zombie:rotten_flesh", chance = 2, min = 3, max = 5},
|
||||
},
|
||||
water_damage = 0,
|
||||
lava_damage = 1,
|
||||
light_damage = 0,
|
||||
animation = {
|
||||
speed_normal = 10, speed_run = 15,
|
||||
stand_start = 0, stand_end = 79,
|
||||
walk_start = 168, walk_end = 188,
|
||||
run_start = 168, run_end = 188,
|
||||
-- punch_start = 168, punch_end = 188,
|
||||
},
|
||||
blood_amount = 7,
|
||||
blood_texture = "default_sand.png",
|
||||
on_rightclick = function(self, clicker)
|
||||
minetest.log(dump(self))
|
||||
end,
|
||||
on_die = function(self, pos)
|
||||
|
||||
-- TODO: Add particle effects
|
||||
--minetest.add_particle_spawner()
|
||||
local positions = {}
|
||||
for x = -1, 1 do
|
||||
for z = -1, 1 do
|
||||
local chance = math.random(1, 2)
|
||||
if (chance > 1) then
|
||||
minetest.set_node({x=pos.x + x, y=pos.y-1, z=pos.z + z}, {name="natspawner:evil_sand"})
|
||||
positions[#positions + 1] = {x=pos.x + x, y = pos.y-1, z=pos.z + z}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.after(1, function(positions)
|
||||
for i = 1, #positions do
|
||||
local chance = math.random(1, 10)
|
||||
if (chance > 5) then
|
||||
minetest.add_entity({x=positions[i].x, y=positions[i].y+1, z=positions[i].z}, "natspawner:sand_zombie_small")
|
||||
end
|
||||
end
|
||||
--minetest.add_entity({x=pos.x - 1, y=pos.y, z=pos.z}, "natspawner:sand_zombie_small")
|
||||
end, positions)
|
||||
|
||||
-- Spawner callback
|
||||
natspawner.on_mob_die(self, pos)
|
||||
end
|
||||
})
|
||||
|
||||
-- Nodes
|
||||
|
||||
|
||||
|
||||
minetest.register_node("natspawner:freezing_ice", {
|
||||
description = "Freezing Ice",
|
||||
tiles = {"frozen_ice.png"},
|
||||
groups = {cracky = 3, cools_lava = 1, slippery = 3, flammable = 2, liquid = 1},
|
||||
use_texture_alpha = true,
|
||||
sunlight_propagates = true,
|
||||
drawtype = "glasslike",
|
||||
paramtype = "light",
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
walkable = false,
|
||||
pointable = true,
|
||||
diggable = true,
|
||||
buildable_to = false,
|
||||
drop = "",
|
||||
drowning = 1,
|
||||
liquid_renewable = false,
|
||||
liquidtype = "source",
|
||||
liquid_range= 0,
|
||||
liquid_alternative_flowing = "natspawner:freezing_ice",
|
||||
liquid_alternative_source = "natspawner:freezing_ice",
|
||||
liquid_viscosity = 30,
|
||||
post_effect_color = {a = 128, r = 30, g = 60, b = 90},
|
||||
--groups = {cracky = 3, cools_lava = 1, slippery = 3, flammable=2, liquid=1, not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
minetest.register_node("natspawner:evil_sand", {
|
||||
description = "Evil Sand",
|
||||
tiles = {"default_sand.png"},
|
||||
inventory_image = "default_snowball.png",
|
||||
wield_image = "default_snowball.png",
|
||||
paramtype = "light",
|
||||
buildable_to = true,
|
||||
floodable = true,
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, -0.25, 0.5},
|
||||
},
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, -7 / 16, 0.5},
|
||||
},
|
||||
},
|
||||
groups = {crumbly = 3, falling_node = 1, sand = 1},
|
||||
sounds = default.node_sound_sand_defaults(),
|
||||
damage_per_second = 2
|
||||
})
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
Loading…
Reference in New Issue