180 lines
4.2 KiB
Lua

function mobs.register_component(name, def)
if not(def.action) or not(name) then
return false
end
mobs.components[name] = def
return true
end
function mobs.get_velocity(v, yaw, y)
local x = -math.sin(yaw) * v
local z = math.cos(yaw) * v
return {x = x, y = y, z = z}
end
function mobs.update_components(components, self, def)
for i,v in ipairs(components) do
if v.name and mobs.components[v.name] then
local output = mobs.components[v.name].action(self, v, def)
print("[mobs] call : " .. v.name .. " -> " .. output)
if output == 0 and v.failure then
print("[mobs] FAILURE")
mobs.update_components(v.failure, self, def)
elseif output == 1 and v.success then
mobs.update_components(v.success, self, def)
elseif output == 2 and v.done then
mobs.update_components(v.done, self, def)
end
end
end
end
function mobs.register_mob(name, def)
mobs.mobs[#mobs.mobs+1] = {name, def.lvl}
if not def.hp then
if def.lvl and def.hits then
def.hp = skills.get_dmg(def.lvl)*def.hits
end
end
def.behaviour = def.behaviour or {
{
name = "walk",
speed = 3,
distance = 3
}, {
name = "attack"
}, {
name = "find_player",
range = 15,
failure = {
{
name = "randomize_destination"
}
}
}
}
minetest.register_entity(name, {
hp_max = def.hp,
physical = true,
collisionbox = def.collisionbox,
visual = def.visual or "upright_sprite",
visual_size = def.visual_size or {x=1, y=1},
textures = def.textures,
mesh = def.mesh or nil,
spritediv = {x=1, y=1},
initial_sprite_basepos = {x=0, y=0},
is_visible = true,
makes_footstep_sound = false,
automatic_rotate = true,
stepheight = def.stepheight or 1.1,
speed = 0,
anim = "",
time = 0.0,
destination = nil,
on_punch = function(self, player)
if self.object:get_hp() <= 0 then
if player and player:is_player() then
xp.add_xp(player, def.xp or xp.get_xp(def.lvl, 10))
if math.random(0,10) == 5 then
minetest.spawn_item(self.object:getpos(),"potions:upgrading")
else
if def.drops then
minetest.spawn_item(self.object:getpos(), def.drops[math.random(1, #def.drops)])
else
minetest.spawn_item(self.object:getpos(), "money:silver_coin")
end
end
mobs.count = mobs.count - 1
self.object:remove()
end
end
end,
on_step = function(self, dtime)
self.time = self.time + dtime
if self.time > 1 then
print("[mobs] -----------------")
mobs.update_components(def.behaviour, self, def)
self.time = 0
end
end,
})
minetest.register_craftitem(name, {
description = def.description,
inventory_image = "mobs_spawn.png",
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return
end
local p = {x=pointed_thing.above.x, y=pointed_thing.above.y+2, z=pointed_thing.above.z}
minetest.add_entity(p, name)
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end,
})
end
function mobs.get_mob(lvl)
local a = {}
local found_mob = false
for i,n in ipairs(mobs.mobs) do
if n[2] < lvl +5 and n[2] > lvl-5 then
found_mob = true
a[#a+1] = n[1]
end
end
if found_mob then
return a[math.random(1, #a)]
end
a = {}
found_mob = false
for i,n in ipairs(mobs.mobs) do
if n[2] < lvl +5 then
found_mob = true
a[#a+1] = n[1]
end
end
if found_mob then
return a[math.random(1, #a)]
end
return mobs.mobs[math.random(1, #mobs.mobs)][1]
end
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime;
if timer >= 10 then
print("[mobs] mob count = " .. tostring(mobs.count))
if mobs.count > (#minetest.get_connected_players())*2 then
print("[mobs] canceled spawning")
timer = 0
return
end
for _, player in pairs(minetest.get_connected_players()) do
local p = player:getpos()
local a = {-1, 1}
local x = math.random(20, 40)*a[math.random(1,2)] + p.x
local z = math.random(20, 40)*a[math.random(1,2)] + p.z
if minetest.get_node(vector.new(x, p.y+2, z)).name == "air" then
local n = mobs.get_mob(xp.player_levels[player:get_player_name()])
minetest.add_entity(vector.new(x, p.y+2, z), n)
mobs.count = mobs.count +1
end
end
timer = 0
end
end)