mirror of
https://codeberg.org/tenplus1/mobs_redo.git
synced 2025-07-19 16:50:25 +02:00
Compare commits
19 Commits
245128f9e6
...
469e35d6e0
Author | SHA1 | Date | |
---|---|---|---|
469e35d6e0 | |||
1271570780 | |||
ec3c6fb518 | |||
c4f56f4204 | |||
4814f53885 | |||
f033cd401c | |||
903e81bdab | |||
81dd3d75c0 | |||
804f8b9a0c | |||
edf0469009 | |||
d20ea74890 | |||
ee8c19ce21 | |||
296fad85ca | |||
d65b80fa51 | |||
48bfa284d0 | |||
b17a5bfe77 | |||
dfdd55848d | |||
e63b1b478e | |||
ec122aa6de |
348
api.lua
348
api.lua
@ -6,7 +6,7 @@ local use_cmi = minetest.global_exists("cmi")
|
||||
|
||||
mobs = {
|
||||
mod = "redo",
|
||||
version = "20200619",
|
||||
version = "20200723",
|
||||
intllib = S,
|
||||
invis = minetest.global_exists("invisibility") and invisibility or {}
|
||||
}
|
||||
@ -196,6 +196,8 @@ end
|
||||
-- calculate distance
|
||||
local get_distance = function(a, b)
|
||||
|
||||
-- if not a or not b then return 50 end -- nil check
|
||||
|
||||
local x, y, z = a.x - b.x, a.y - b.y, a.z - b.z
|
||||
|
||||
return square(x * x + y * y + z * z)
|
||||
@ -206,7 +208,6 @@ end
|
||||
function mob_class:collision()
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
local vel = self.object:get_velocity()
|
||||
local x, z = 0, 0
|
||||
local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5
|
||||
|
||||
@ -229,12 +230,36 @@ function mob_class:collision()
|
||||
end
|
||||
|
||||
|
||||
-- check string against another string or table
|
||||
local check_for = function(look_for, look_inside)
|
||||
|
||||
if type(look_inside) == "string" and look_inside == look_for then
|
||||
|
||||
return true
|
||||
|
||||
elseif type(look_inside) == "table" then
|
||||
|
||||
for _, str in pairs(look_inside) do
|
||||
|
||||
if str == look_for then
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- move mob in facing direction
|
||||
function mob_class:set_velocity(v)
|
||||
|
||||
-- halt mob if it has been ordered to stay
|
||||
if self.order == "stand" then
|
||||
|
||||
self.object:set_velocity({x = 0, y = 0, z = 0})
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
@ -250,14 +275,26 @@ function mob_class:set_velocity(v)
|
||||
-- nil check for velocity
|
||||
v = v or 0
|
||||
|
||||
-- check if standing in liquid with max viscosity of 7
|
||||
local visc = min(minetest.registered_nodes[self.standing_in].liquid_viscosity, 7)
|
||||
|
||||
-- only slow mob trying to move while inside a viscous fluid that
|
||||
-- they aren't meant to be in (fish in water, spiders in cobweb etc)
|
||||
if v > 0 and visc and visc > 0
|
||||
and not check_for(self.standing_in, self.fly_in) then
|
||||
v = v / (visc + 1)
|
||||
end
|
||||
|
||||
-- set velocity with hard limit of 10
|
||||
local vel = self.object:get_velocity()
|
||||
|
||||
self.object:set_velocity({
|
||||
x = max(-10, min((sin(yaw) * -v) + c_x, 10)),
|
||||
y = max(-10, min((vel and vel.y or 0), 10)),
|
||||
z = max(-10, min((cos(yaw) * v) + c_y, 10))
|
||||
})
|
||||
local new_vel = {
|
||||
x = (sin(yaw) * -v) + c_x,
|
||||
y = vel.y,
|
||||
z = (cos(yaw) * v) + c_y
|
||||
}
|
||||
|
||||
self.object:set_velocity(new_vel)
|
||||
end
|
||||
|
||||
-- global version of above function
|
||||
@ -550,20 +587,9 @@ function mob_class:flight_check()
|
||||
|
||||
if not def then return false end
|
||||
|
||||
if type(self.fly_in) == "string"
|
||||
and self.standing_in == self.fly_in then
|
||||
|
||||
-- are we standing inside what we should be to fly/swim ?
|
||||
if check_for(self.standing_in, self.fly_in) then
|
||||
return true
|
||||
|
||||
elseif type(self.fly_in) == "table" then
|
||||
|
||||
for _,fly_in in pairs(self.fly_in) do
|
||||
|
||||
if self.standing_in == fly_in then
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- stops mobs getting stuck inside stairs and plantlike nodes
|
||||
@ -645,7 +671,14 @@ local effect = function(pos, amount, texture, min_size, max_size,
|
||||
max_size = max_size or 1
|
||||
gravity = gravity or -10
|
||||
glow = glow or 0
|
||||
fall = fall and 0 or -radius
|
||||
|
||||
if fall == true then
|
||||
fall = 0
|
||||
elseif fall == false then
|
||||
fall = radius
|
||||
else
|
||||
fall = -radius
|
||||
end
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount = amount,
|
||||
@ -665,6 +698,12 @@ local effect = function(pos, amount, texture, min_size, max_size,
|
||||
})
|
||||
end
|
||||
|
||||
function mobs:effect(pos, amount, texture, min_size, max_size,
|
||||
radius, gravity, glow, fall)
|
||||
|
||||
effect(pos, amount, texture, min_size, max_size, radius, gravity, glow, fall)
|
||||
end
|
||||
|
||||
|
||||
-- update nametag colour
|
||||
function mob_class:update_tag()
|
||||
@ -775,6 +814,11 @@ local remove_mob = function(self, decrease)
|
||||
--print("-- active mobs: " .. active_mobs .. " / " .. active_limit)
|
||||
end
|
||||
|
||||
-- global function for removing mobs
|
||||
function mobs:remove(self, decrease)
|
||||
remove_mob(self, decrease)
|
||||
end
|
||||
|
||||
|
||||
-- check if mob is dead or only hurt
|
||||
function mob_class:check_for_death(cmi_cause)
|
||||
@ -976,7 +1020,7 @@ function mob_class:do_env_damage()
|
||||
self:update_tag()
|
||||
end
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
local pos = self.object:get_pos() ; if not pos then return end
|
||||
|
||||
self.time_of_day = minetest.get_timeofday()
|
||||
|
||||
@ -1107,14 +1151,8 @@ function mob_class:do_jump()
|
||||
-- sanity check
|
||||
if not yaw then return false end
|
||||
|
||||
-- what is mob standing on?
|
||||
pos.y = pos.y + self.collisionbox[2] - 0.2
|
||||
|
||||
local nod = node_ok(pos)
|
||||
|
||||
--print("standing on:", nod.name, pos.y)
|
||||
|
||||
if minetest.registered_nodes[nod.name].walkable == false then
|
||||
-- we can only jump if standing on solid node
|
||||
if minetest.registered_nodes[self.standing_on].walkable == false then
|
||||
return false
|
||||
end
|
||||
|
||||
@ -1122,22 +1160,22 @@ function mob_class:do_jump()
|
||||
local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5)
|
||||
local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5)
|
||||
|
||||
-- set y_pos to base of mob
|
||||
pos.y = pos.y + self.collisionbox[2]
|
||||
|
||||
-- what is in front of mob?
|
||||
local nod = node_ok({
|
||||
x = pos.x + dir_x,
|
||||
y = pos.y + 0.5,
|
||||
z = pos.z + dir_z
|
||||
x = pos.x + dir_x, y = pos.y + 0.5, z = pos.z + dir_z
|
||||
})
|
||||
|
||||
-- what is above and in front?
|
||||
local nodt = node_ok({
|
||||
x = pos.x + dir_x,
|
||||
y = pos.y + 1.5,
|
||||
z = pos.z + dir_z
|
||||
x = pos.x + dir_x, y = pos.y + 1.5, z = pos.z + dir_z
|
||||
})
|
||||
|
||||
local blocked = minetest.registered_nodes[nodt.name].walkable
|
||||
|
||||
--print("standing on:", self.standing_on, pos.y - 0.25)
|
||||
--print("in front:", nod.name, pos.y + 0.5)
|
||||
--print("in front above:", nodt.name, pos.y + 1.5)
|
||||
|
||||
@ -1239,22 +1277,10 @@ function mob_class:follow_holding(clicker)
|
||||
end
|
||||
|
||||
local item = clicker:get_wielded_item()
|
||||
local t = type(self.follow)
|
||||
|
||||
-- single item
|
||||
if t == "string"
|
||||
and item:get_name() == self.follow then
|
||||
-- are we holding an item mob can follow ?
|
||||
if check_for(item:get_name(), self.follow) then
|
||||
return true
|
||||
|
||||
-- multiple items
|
||||
elseif t == "table" then
|
||||
|
||||
for no = 1, #self.follow do
|
||||
|
||||
if self.follow[no] == item:get_name() then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
@ -1519,7 +1545,9 @@ local height_switcher = false
|
||||
function mob_class:smart_mobs(s, p, dist, dtime)
|
||||
|
||||
local s1 = self.path.lastpos
|
||||
local target_pos = self.attack:get_pos()
|
||||
-- local target_pos = self.attack:get_pos()
|
||||
local target_pos = p
|
||||
|
||||
|
||||
-- is it becoming stuck?
|
||||
if abs(s1.x - s.x) + abs(s1.z - s.z) < .5 then
|
||||
@ -1583,10 +1611,6 @@ function mob_class:smart_mobs(s, p, dist, dtime)
|
||||
|
||||
minetest.after(1, function(self)
|
||||
|
||||
if not self.object:get_luaentity() then
|
||||
return
|
||||
end
|
||||
|
||||
if self.object:get_luaentity() then
|
||||
|
||||
if has_lineofsight then
|
||||
@ -1668,7 +1692,10 @@ function mob_class:smart_mobs(s, p, dist, dtime)
|
||||
]]
|
||||
|
||||
self.state = ""
|
||||
|
||||
if self.attack then
|
||||
self:do_attack(self.attack)
|
||||
end
|
||||
|
||||
-- no path found, try something else
|
||||
if not self.path.way then
|
||||
@ -1766,12 +1793,16 @@ function mob_class:smart_mobs(s, p, dist, dtime)
|
||||
-- will try again in 2 second
|
||||
self.path.stuck_timer = stuck_timeout - 2
|
||||
|
||||
elseif s.y < p1.y and (not self.fly) then
|
||||
elseif s.y < p1.y and (not self.fly) then
|
||||
self:do_jump() --add jump to pathfinding
|
||||
self.path.following = true
|
||||
else
|
||||
-- yay i found path
|
||||
if self.attack then
|
||||
self:mob_sound(self.sounds.war_cry)
|
||||
else
|
||||
self:mob_sound(self.sounds.random)
|
||||
end
|
||||
self:set_velocity(self.walk_velocity)
|
||||
|
||||
-- follow path now that it has it
|
||||
@ -1812,7 +1843,7 @@ function mob_class:general_attack()
|
||||
return
|
||||
end
|
||||
|
||||
local s = self.object:get_pos()
|
||||
local s = self.object:get_pos() ; if not s then return end
|
||||
local objs = minetest.get_objects_inside_radius(s, self.view_range)
|
||||
|
||||
-- remove entities we aren't interested in
|
||||
@ -1944,8 +1975,8 @@ function mob_class:do_runaway_from()
|
||||
if name ~= "" and name ~= self.name
|
||||
and specific_runaway(self.runaway_from, name) then
|
||||
|
||||
p = player:get_pos()
|
||||
sp = s
|
||||
p = player and player:get_pos() or s
|
||||
|
||||
-- aim higher to make looking up hills more realistic
|
||||
p.y = p.y + 1
|
||||
@ -1982,7 +2013,7 @@ function mob_class:follow_flop()
|
||||
and self.state ~= "attack"
|
||||
and self.state ~= "runaway" then
|
||||
|
||||
local s = self.object:get_pos()
|
||||
local s = self.object:get_pos() ; if not s then return end
|
||||
local players = minetest.get_connected_players()
|
||||
|
||||
for n = 1, #players do
|
||||
@ -2113,11 +2144,11 @@ end
|
||||
-- execute current state (stand, walk, run, attacks)
|
||||
function mob_class:do_states(dtime)
|
||||
|
||||
local yaw = self.object:get_yaw() or 0
|
||||
local yaw = self.object:get_yaw() ; if not yaw then return end
|
||||
|
||||
if self.state == "stand" then
|
||||
|
||||
if random(4) == 1 then
|
||||
if self.randomly_turn and random(4) == 1 then
|
||||
|
||||
local lp
|
||||
local s = self.object:get_pos()
|
||||
@ -2205,7 +2236,7 @@ function mob_class:do_states(dtime)
|
||||
yaw = self:set_yaw(yaw, 8)
|
||||
|
||||
-- otherwise randomly turn
|
||||
elseif random(100) <= 30 then
|
||||
elseif self.randomly_turn and random(100) <= 30 then
|
||||
|
||||
yaw = yaw + random(-0.5, 0.5)
|
||||
|
||||
@ -2265,12 +2296,12 @@ function mob_class:do_states(dtime)
|
||||
-- attack routines (explode, dogfight, shoot, dogshoot)
|
||||
elseif self.state == "attack" then
|
||||
|
||||
-- calculate distance from mob and enemy
|
||||
-- get mob and enemy positions and distance between
|
||||
local s = self.object:get_pos()
|
||||
local p = self.attack:get_pos() or s
|
||||
local dist = get_distance(p, s)
|
||||
local p = self.attack:get_pos()
|
||||
local dist = p and get_distance(p, s) or 500
|
||||
|
||||
-- stop attacking if player invisible or out of range
|
||||
-- stop attacking if player out of range or invisible
|
||||
if dist > self.view_range
|
||||
or not self.attack
|
||||
or not self.attack:get_pos()
|
||||
@ -2352,10 +2383,10 @@ function mob_class:do_states(dtime)
|
||||
self.blinktimer = 0
|
||||
|
||||
if self.blinkstatus then
|
||||
-- self.object:set_texture_mod("")
|
||||
|
||||
self.object:set_texture_mod(self.texture_mods)
|
||||
else
|
||||
-- self.object:set_texture_mod("^[brighten")
|
||||
|
||||
self.object:set_texture_mod(self.texture_mods
|
||||
.. "^[brighten")
|
||||
end
|
||||
@ -2406,7 +2437,8 @@ function mob_class:do_states(dtime)
|
||||
|
||||
elseif self.attack_type == "dogfight"
|
||||
or (self.attack_type == "dogshoot" and self:dogswitch(dtime) == 2)
|
||||
or (self.attack_type == "dogshoot" and dist <= self.reach and self:dogswitch() == 0) then
|
||||
or (self.attack_type == "dogshoot" and dist <= self.reach
|
||||
and self:dogswitch() == 0) then
|
||||
|
||||
if self.fly
|
||||
and dist > self.reach then
|
||||
@ -2453,7 +2485,6 @@ function mob_class:do_states(dtime)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- rnd: new movement direction
|
||||
@ -2567,11 +2598,7 @@ function mob_class:do_states(dtime)
|
||||
p.y = p.y - .5
|
||||
s.y = s.y + .5
|
||||
|
||||
local vec = {
|
||||
x = p.x - s.x,
|
||||
y = p.y - s.y,
|
||||
z = p.z - s.z
|
||||
}
|
||||
local vec = {x = p.x - s.x, y = p.y - s.y, z = p.z - s.z}
|
||||
|
||||
yaw = yaw_to_pos(self, p)
|
||||
|
||||
@ -2628,39 +2655,33 @@ function mob_class:falling(pos)
|
||||
-- sanity check
|
||||
if not v then return end
|
||||
|
||||
if v.y > 0 then
|
||||
local fall_speed = -10 -- gravity
|
||||
|
||||
-- apply gravity when moving up
|
||||
self.object:set_acceleration({
|
||||
x = 0,
|
||||
y = -10,
|
||||
z = 0
|
||||
})
|
||||
|
||||
elseif v.y <= 0 and v.y > self.fall_speed then
|
||||
|
||||
-- fall downwards at set speed
|
||||
self.object:set_acceleration({
|
||||
x = 0,
|
||||
y = self.fall_speed,
|
||||
z = 0
|
||||
})
|
||||
else
|
||||
-- stop accelerating once max fall speed hit
|
||||
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||
-- don't exceed mob fall speed
|
||||
if v.y < self.fall_speed then
|
||||
fall_speed = self.fall_speed
|
||||
end
|
||||
|
||||
-- in water then float up
|
||||
if self.standing_in
|
||||
and minetest.registered_nodes[self.standing_in].groups.water then
|
||||
-- in water then use liquid viscosity for float/sink speed
|
||||
if (self.standing_in
|
||||
and minetest.registered_nodes[self.standing_in].groups.liquid) --water)
|
||||
or (self.standing_on
|
||||
and minetest.registered_nodes[self.standing_in].groups.liquid) then -- water) then
|
||||
|
||||
local visc = min(
|
||||
minetest.registered_nodes[self.standing_in].liquid_viscosity, 7)
|
||||
|
||||
if self.floats == 1 then
|
||||
|
||||
self.object:set_acceleration({
|
||||
x = 0,
|
||||
y = -self.fall_speed / (max(1, v.y) ^ 8), -- 8 was 2
|
||||
z = 0
|
||||
})
|
||||
-- floating up
|
||||
if visc > 0 then
|
||||
fall_speed = max(1, v.y) / (visc + 1)
|
||||
end
|
||||
else
|
||||
-- sinking down
|
||||
if visc > 0 then
|
||||
fall_speed = -(max(1, v.y) / (visc + 1))
|
||||
end
|
||||
end
|
||||
else
|
||||
|
||||
@ -2684,6 +2705,13 @@ function mob_class:falling(pos)
|
||||
self.old_y = self.object:get_pos().y
|
||||
end
|
||||
end
|
||||
|
||||
-- fall at set speed
|
||||
self.object:set_acceleration({
|
||||
x = 0,
|
||||
y = fall_speed,
|
||||
z = 0
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
@ -3170,6 +3198,7 @@ function mob_class:mob_activate(staticdata, def, dtime)
|
||||
self.selectionbox = selbox
|
||||
self.visual_size = vis_size
|
||||
self.standing_in = "air"
|
||||
self.standing_on = "air"
|
||||
|
||||
-- check existing nametag
|
||||
if not self.nametag then
|
||||
@ -3296,6 +3325,9 @@ function mob_class:on_step(dtime, moveresult)
|
||||
self.standing_in = node_ok({
|
||||
x = pos.x, y = pos.y + y_level + 0.25, z = pos.z}, "air").name
|
||||
|
||||
self.standing_on = node_ok({
|
||||
x = pos.x, y = pos.y + y_level - 0.25, z = pos.z}, "air").name
|
||||
|
||||
--print("standing in " .. self.standing_in)
|
||||
|
||||
-- if standing inside solid block then jump to escape
|
||||
@ -3451,7 +3483,7 @@ mobs.spawning_mobs = {}
|
||||
-- register mob entity
|
||||
function mobs:register_mob(name, def)
|
||||
|
||||
mobs.spawning_mobs[name] = true
|
||||
mobs.spawning_mobs[name] = {}
|
||||
|
||||
minetest.register_entity(name, setmetatable({
|
||||
|
||||
@ -3544,6 +3576,7 @@ minetest.register_entity(name, setmetatable({
|
||||
owner_loyal = def.owner_loyal,
|
||||
pushable = def.pushable,
|
||||
stay_near = def.stay_near,
|
||||
randomly_turn = def.randomly_turn ~= false,
|
||||
|
||||
on_spawn = def.on_spawn,
|
||||
|
||||
@ -3598,6 +3631,106 @@ end
|
||||
|
||||
-- global functions
|
||||
|
||||
function mobs:add_mob(pos, def)
|
||||
|
||||
-- is mob actually registered?
|
||||
if not mobs.spawning_mobs[def.name]
|
||||
or not minetest.registered_entities[def.name] then
|
||||
--print("--- mob doesn't exist", def.name)
|
||||
return
|
||||
end
|
||||
|
||||
-- are we over active mob limit
|
||||
if active_limit > 0 and active_mobs >= active_limit then
|
||||
--print("--- active mob limit reached", active_mobs, active_limit)
|
||||
return
|
||||
end
|
||||
|
||||
-- get total number of this mob in area
|
||||
local num_mob, is_pla = count_mobs(pos, def.name)
|
||||
|
||||
if not is_pla then
|
||||
--print("--- no players within active area, will not spawn " .. def.name)
|
||||
return
|
||||
end
|
||||
|
||||
local aoc = mobs.spawning_mobs[def.name]
|
||||
and mobs.spawning_mobs[def.name].aoc or 1
|
||||
|
||||
if def.ignore_count ~= true and num_mob >= aoc then
|
||||
--print("--- too many " .. def.name .. " in area", num_mob .. "/" .. aoc)
|
||||
return
|
||||
end
|
||||
|
||||
local mob = minetest.add_entity(pos, def.name)
|
||||
|
||||
--print("[mobs] Spawned " .. def.name .. " at " .. minetest.pos_to_string(pos))
|
||||
|
||||
local ent = mob:get_luaentity()
|
||||
|
||||
if not ent then
|
||||
--print("[mobs] entity not found " .. def.name)
|
||||
return false
|
||||
end
|
||||
|
||||
if def.child then
|
||||
|
||||
local textures = ent.base_texture
|
||||
|
||||
-- using specific child texture (if found)
|
||||
if ent.child_texture then
|
||||
textures = ent.child_texture[1]
|
||||
end
|
||||
|
||||
-- and resize to half height
|
||||
mob:set_properties({
|
||||
textures = textures,
|
||||
visual_size = {
|
||||
x = ent.base_size.x * .5,
|
||||
y = ent.base_size.y * .5
|
||||
},
|
||||
collisionbox = {
|
||||
ent.base_colbox[1] * .5,
|
||||
ent.base_colbox[2] * .5,
|
||||
ent.base_colbox[3] * .5,
|
||||
ent.base_colbox[4] * .5,
|
||||
ent.base_colbox[5] * .5,
|
||||
ent.base_colbox[6] * .5
|
||||
},
|
||||
selectionbox = {
|
||||
ent.base_selbox[1] * .5,
|
||||
ent.base_selbox[2] * .5,
|
||||
ent.base_selbox[3] * .5,
|
||||
ent.base_selbox[4] * .5,
|
||||
ent.base_selbox[5] * .5,
|
||||
ent.base_selbox[6] * .5
|
||||
},
|
||||
})
|
||||
|
||||
ent.child = true
|
||||
end
|
||||
|
||||
if def.owner then
|
||||
ent.tamed = true
|
||||
ent.owner = def.owner
|
||||
end
|
||||
|
||||
if def.nametag then
|
||||
|
||||
-- limit name entered to 64 characters long
|
||||
if def.nametag:len() > 64 then
|
||||
def.nametag = def.nametag:sub(1, 64)
|
||||
end
|
||||
|
||||
ent.nametag = def.nametag
|
||||
|
||||
ent:update_tag()
|
||||
end
|
||||
|
||||
return ent
|
||||
end
|
||||
|
||||
|
||||
function mobs:spawn_abm_check(pos, node, name)
|
||||
-- global function to add additional spawn checks
|
||||
-- return true to stop spawning mob
|
||||
@ -3608,7 +3741,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light,
|
||||
interval, chance, aoc, min_height, max_height, day_toggle, on_spawn)
|
||||
|
||||
-- Do mobs spawn at all?
|
||||
if not mobs_spawn then
|
||||
if not mobs_spawn or not mobs.spawning_mobs[name] then
|
||||
return
|
||||
end
|
||||
|
||||
@ -3632,6 +3765,8 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light,
|
||||
|
||||
end
|
||||
|
||||
mobs.spawning_mobs[name].aoc = aoc
|
||||
|
||||
minetest.register_abm({
|
||||
|
||||
label = name .. " spawning",
|
||||
@ -3862,6 +3997,7 @@ function mobs:register_arrow(name, def)
|
||||
drop = def.drop or false, -- drops arrow as registered item when true
|
||||
collisionbox = def.collisionbox or {-.1, -.1, -.1, .1, .1, .1},
|
||||
timer = 0,
|
||||
lifetime = def.lifetime or 4.5,
|
||||
switch = 0,
|
||||
owner_id = def.owner_id,
|
||||
rotate = def.rotate,
|
||||
@ -3876,11 +4012,11 @@ function mobs:register_arrow(name, def)
|
||||
|
||||
on_step = def.on_step or function(self, dtime)
|
||||
|
||||
self.timer = self.timer + 1
|
||||
self.timer = self.timer + dtime
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
|
||||
if self.switch == 0 or self.timer > 150 then
|
||||
if self.switch == 0 or self.timer > self.lifetime then
|
||||
|
||||
self.object:remove() ; -- print("removed arrow")
|
||||
|
||||
|
43
api.txt
43
api.txt
@ -31,13 +31,15 @@ functions needed for the mob to work properly which contains the following:
|
||||
'hp_max' has the maximum health value the mob can spawn with.
|
||||
'armor' holds strength of mob, 100 is normal, lower is more powerful
|
||||
and needs more hits and better weapons to kill.
|
||||
'passive' when true allows animals to defend themselves when hit,
|
||||
'passive' when false allows animals to defend themselves when hit,
|
||||
otherwise they amble onwards.
|
||||
'walk_velocity' is the speed that your mob can walk around.
|
||||
'run_velocity' is the speed your mob can run with, usually when attacking.
|
||||
'stand_chance' has a 0-100 chance value your mob will stand from walking.
|
||||
'walk_chance' has a 0-100 chance value your mob will walk from standing,
|
||||
set to 0 for jumping mobs only.
|
||||
'randomly_turn' if set to false then mob will not turn to face player or
|
||||
randomly turn while walking or standing.
|
||||
'jump' when true allows your mob to jump updwards.
|
||||
'jump_height' holds the height your mob can jump, 0 to disable jumping.
|
||||
'stepheight' height of a block that your mob can easily walk up onto,
|
||||
@ -293,7 +295,8 @@ enhance mob functionality and have them do many interesting things:
|
||||
'custom_attack' when set this function is called instead of the normal mob
|
||||
melee attack, parameters are (self, to_attack) and if true
|
||||
is returned normal attack function continued.
|
||||
'on_die' a function that is called when mob is killed (self, pos)
|
||||
'on_die' a function that is called when mob is killed (self, pos), also
|
||||
has access to self.cause_of_death table.
|
||||
'do_custom' a custom function that is called every tick while mob is
|
||||
active and which has access to all of the self.* variables
|
||||
e.g. (self.health for health or self.standing_in for node
|
||||
@ -327,6 +330,20 @@ for each mob.
|
||||
'self.nametag' contains the name of the mob which it can show above
|
||||
|
||||
|
||||
Adding Mobs in World
|
||||
--------------------
|
||||
|
||||
mobs:add_mob(pos, {
|
||||
name = "mobs_animal:chicken",
|
||||
child = true,
|
||||
owner = "singleplayer",
|
||||
nametag = "Bessy",
|
||||
ignore_count = true -- ignores mob count per map area
|
||||
})
|
||||
|
||||
Returns false if mob could not be added, returns mob object if spawned ok.
|
||||
|
||||
|
||||
Spawning Mobs in World
|
||||
----------------------
|
||||
|
||||
@ -387,6 +404,24 @@ true the mob will not spawn.
|
||||
'name' is the name of the animal/monster
|
||||
|
||||
|
||||
Particle Effects
|
||||
----------------
|
||||
|
||||
mobs:effect(pos, amount, texture, min_size, max_size, radius, gravity, glow, fall)
|
||||
|
||||
This function provides a quick way to spawn particles as an effect.
|
||||
|
||||
'pos' center position of particle effect.
|
||||
'amount' how many particles.
|
||||
'texture' texture filename to use for effect.
|
||||
'min_size' smallest particle size.
|
||||
'max_size' largest particle size.
|
||||
'radius' how far particles spread outward from center.
|
||||
'gravity' gravity applied to particles once they spawn.
|
||||
'glow' number between 1 and 15 for glowing particles.
|
||||
'fall' when true particles fall, false has them rising, nil has them scatter.
|
||||
|
||||
|
||||
Making Arrows
|
||||
-------------
|
||||
|
||||
@ -422,7 +457,9 @@ This function registers a arrow for mobs with the attack type shoot.
|
||||
'on_step' is a custom function when arrow is active, nil for
|
||||
default.
|
||||
'on_punch' is a custom function when arrow is punched, nil by default
|
||||
'collisionbox' is hitbox table for arrow, {0,0,0,0,0,0} by default.
|
||||
'collisionbox' is hitbox table for arrow, {-.1,-.1,-.1,.1,.1,.1} by default.
|
||||
'lifetime' contains float value for how many seconds arrow exists in
|
||||
world before being removed (default is 4.5 seconds).
|
||||
|
||||
|
||||
Spawn Eggs
|
||||
|
@ -106,13 +106,17 @@ msgid "Mob Spawner"
|
||||
msgstr ""
|
||||
|
||||
#: spawner.lua
|
||||
msgid "Mob MinLight MaxLight Amount PlayerDist"
|
||||
msgid "(mob name) (min light) (max light) (amount) (player distance) (Y offset)"
|
||||
msgstr ""
|
||||
|
||||
#: spawner.lua
|
||||
msgid "Spawner Not Active (enter settings)"
|
||||
msgstr ""
|
||||
|
||||
#@ spawner.lua
|
||||
msgid "Command:"
|
||||
msgstr ""
|
||||
|
||||
#: spawner.lua
|
||||
msgid "Spawner Active (@1)"
|
||||
msgstr ""
|
||||
|
@ -84,7 +84,7 @@ local function force_detach(player)
|
||||
|
||||
local entity = attached_to:get_luaentity()
|
||||
|
||||
if entity.driver
|
||||
if entity and entity.driver
|
||||
and entity.driver == player then
|
||||
|
||||
entity.driver = nil
|
||||
|
@ -23,8 +23,8 @@ Lucky Blocks: 9
|
||||
|
||||
|
||||
Changelog:
|
||||
- 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game
|
||||
(default is 0 for unlimited), removed {immortal} from mob armor
|
||||
- 1.52 - Added 'mob_active_limit' in settings to set number of mobs in game
|
||||
(default is 0 for unlimited), removed {immortal} from mob armor, fluid viscocity slows mobs
|
||||
- 1.51 - Added some node checks for dangerous nodes, jumping and falling tweaks, spawn area check (thx for idea wuzzy), re-enabled mob suffocation, add 'mob_nospawn_range' setting
|
||||
- 1.50 - Added new line_of_sight function that uses raycasting if mt5.0 is found, (thanks Astrobe), dont spawn mobs if world anchor nearby (technic or simple_anchor mods), chinese local added
|
||||
- 1.49- Added mobs:force_capture(self, player) function, api functions now use metatables thanks to bell07
|
||||
|
17
spawner.lua
17
spawner.lua
@ -3,7 +3,7 @@ local S = mobs.intllib
|
||||
|
||||
-- mob spawner
|
||||
|
||||
local spawner_default = "mobs_animal:pumba 10 15 0 0"
|
||||
local spawner_default = "mobs_animal:pumba 10 15 0 0 0"
|
||||
|
||||
minetest.register_node("mobs:spawner", {
|
||||
tiles = {"mob_spawner.png"},
|
||||
@ -17,10 +17,17 @@ minetest.register_node("mobs:spawner", {
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
-- setup formspec
|
||||
local head = S("(mob name) (min light) (max light) (amount)"
|
||||
.. " (player distance) (Y offset)")
|
||||
|
||||
-- text entry formspec
|
||||
meta:set_string("formspec",
|
||||
"field[text;" .. S("Mob MinLight MaxLight Amount PlayerDist")
|
||||
"size[9,3.5]"
|
||||
.. "label[0.15,0.5;" .. minetest.formspec_escape(head) .. "]"
|
||||
.. "field[1,2.5;7.5,0.8;text;" .. S("Command:")
|
||||
.. ";${command}]")
|
||||
|
||||
meta:set_string("infotext", S("Spawner Not Active (enter settings)"))
|
||||
meta:set_string("command", spawner_default)
|
||||
end,
|
||||
@ -54,11 +61,11 @@ minetest.register_node("mobs:spawner", {
|
||||
local pla = tonumber(comm[5]) -- player distance (0 to disable)
|
||||
local yof = tonumber(comm[6]) or 0 -- Y offset to spawn mob
|
||||
|
||||
if mob and mob ~= "" and mobs.spawning_mobs[mob] == true
|
||||
if mob and mob ~= "" and mobs.spawning_mobs[mob]
|
||||
and num and num >= 0 and num <= 10
|
||||
and mlig and mlig >= 0 and mlig <= 15
|
||||
and xlig and xlig >= 0 and xlig <= 15
|
||||
and pla and pla >=0 and pla <= 20
|
||||
and pla and pla >= 0 and pla <= 20
|
||||
and yof and yof > -10 and yof < 10 then
|
||||
|
||||
meta:set_string("command", fields.text)
|
||||
@ -67,7 +74,7 @@ minetest.register_node("mobs:spawner", {
|
||||
else
|
||||
minetest.chat_send_player(name, S("Mob Spawner settings failed!"))
|
||||
minetest.chat_send_player(name,
|
||||
S("Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] distance[1-20] y_offset[-10 to 10]”"))
|
||||
S("Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] player_distance[1-20] y_offset[-10 to 10]”"))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
Reference in New Issue
Block a user