Compare commits

...

10 Commits

Author SHA1 Message Date
e58f20bebb fix default self.state
* backported upstream commit 903b1e34dfe15e0c90b7dee012c9b569f0c0c4a7
2024-04-07 22:58:08 -04:00
2276603a13 fix is_inside function error misctake at end with + 2024-04-07 22:57:05 -04:00
1cd4884707 mobs:add_mob() can now set mob texture
* backported upstream commit ce47b81da56bba7618f1ab62ede0daaca1b88ced
2024-04-07 22:18:25 -04:00
359ad19bf2 check for fire/lava in mob collisionbox area
* backported upstream commit ba79c2f1f14583a87163b0c4bed6a1fe20e0cd5c
2024-04-07 22:07:28 -04:00
ae003fe323 add spawn check for collisionbox
* backported upstream commit d1f23e8ed848cbe0d7827c19285ff256a78fb6fe
2024-04-07 22:04:49 -04:00
81066c8b92 do not regiter mobs if there is not a mob
* backported from undocumented upstream
  commit 812f18430c343c9ac70b83276faa3aabf5a25116
2024-04-07 21:59:29 -04:00
d0938ff178 property check player object as must be cos engine returns false positives 2024-04-07 21:48:34 -04:00
d871b18e8f fix and tweak limit mobs reached that player spawns from "code tweaks"
* backport only the tweak of "code tweaks" of
  upstream commit 457eb1838cd1e694052298a42c84cd7b061d809d
  limit mobs reached that player spawns from creative or something
* add the check for player before send the chat msg, missing
  from upstream
2024-04-07 20:52:18 -04:00
fe3c543136 fix and tweak runaway_timer from "code tweaks"
* backport only the tweak of "code tweaks" of
 upstream commit 457eb1838cd1e694052298a42c84cd7b061d809d
 run away soon and early
2024-04-07 20:48:35 -04:00
21cf18990b backport and tweak internal functions and document it
* backported internal fucntions cos the narcisits tenplus1 dont
  property document the changes.. the commit 457eb1838cd1e694052298a42c84cd7b061d809d
  of main master upstream tag has bugs inside changes and undocumented
  changes too, this commit was named "code tweaks" only!
* also backported commit ed74f3c4c4d3f4c7e17127fa26ac4f0adbd2900d
  named "add :is_inside() function (thx cora for idea)" non credited
  in changes
* add global node_ok, effect and yaw_to_pos global deprecated functions for
  backguard compatibility
* add selft mob_class list of functions also is_inside, yaw_to_pos,
  set_velocity
2024-04-07 20:31:25 -04:00
2 changed files with 161 additions and 92 deletions

224
api.lua
View File

@ -33,7 +33,7 @@ local use_mc2 = minetest.get_modpath("mcl_core")
-- Global -- Global
mobs = { mobs = {
mod = "redo", mod = "redo",
version = "20231106", version = "20231111",
translate = S, intllib = S, translate = S, intllib = S,
invis = minetest.global_exists("invisibility") and invisibility or {}, invis = minetest.global_exists("invisibility") and invisibility or {},
node_ice = "default:ice", node_ice = "default:ice",
@ -151,6 +151,7 @@ local creatura = minetest.get_modpath("creatura") and
mobs.mob_class = { mobs.mob_class = {
state = "stand",
stepheight = 1.1, stepheight = 1.1,
fly_in = "air", fly_in = "air",
owner = "", owner = "",
@ -183,7 +184,7 @@ mobs.mob_class = {
walk_chance = 50, walk_chance = 50,
stand_chance = 30, stand_chance = 30,
attack_chance = 5, attack_chance = 5,
attack_patience = 11 attack_patience = 11,
passive = false, passive = false,
blood_amount = 5, blood_amount = 5,
blood_texture = "mobs_blood.png", blood_texture = "mobs_blood.png",
@ -227,7 +228,7 @@ local mob_class = mobs.mob_class -- Compatibility
local mob_class_meta = {__index = mob_class} local mob_class_meta = {__index = mob_class}
-- play sound -- function mob_sound play sound
function mob_class:mob_sound(sound) function mob_class:mob_sound(sound)
if not sound then return end if not sound then return end
@ -247,7 +248,7 @@ function mob_class:mob_sound(sound)
end end
-- attack player/mob -- function do_class attack player/mob
function mob_class:do_attack(player) function mob_class:do_attack(player)
if self.state == "attack" then if self.state == "attack" then
@ -283,7 +284,7 @@ local function is_player(player)
end end
-- collision function based on jordan4ibanez' open_ai mod -- function collision based on jordan4ibanez' open_ai mod
function mob_class:collision() function mob_class:collision()
local pos = self.object:get_pos() ; if not pos then return {0, 0} end local pos = self.object:get_pos() ; if not pos then return {0, 0} end
@ -345,7 +346,7 @@ local function check_for(look_for, look_inside)
end end
-- move mob in facing direction -- function set_velocity move mob in facing direction
function mob_class:set_velocity(v) function mob_class:set_velocity(v)
-- halt mob if it has been ordered to stay -- halt mob if it has been ordered to stay
@ -390,13 +391,13 @@ function mob_class:set_velocity(v)
self.object:set_velocity(new_vel) self.object:set_velocity(new_vel)
end end
-- global version of above function -- global version of above function [deprecated]
function mobs:set_velocity(entity, v) function mobs:set_velocity(entity, v)
mob_class.set_velocity(entity, v) mob_class.set_velocity(entity, v)
end end
-- calculate mob velocity -- function get_velocity calculate mob velocity
function mob_class:get_velocity() function mob_class:get_velocity()
local v = self.object:get_velocity() local v = self.object:get_velocity()
@ -407,7 +408,7 @@ function mob_class:get_velocity()
end end
-- set and return valid yaw -- function set_yaw set and return valid yaw
function mob_class:set_yaw(yaw, delay) function mob_class:set_yaw(yaw, delay)
if not yaw or yaw ~= yaw then if not yaw or yaw ~= yaw then
@ -442,7 +443,7 @@ function mobs:yaw(entity, yaw, delay)
end end
-- set defined animation -- function set_animation set defined animation
function mob_class:set_animation(anim, force) function mob_class:set_animation(anim, force)
if not self.animation or not anim then return end if not self.animation or not anim then return end
@ -487,6 +488,7 @@ function mob_class:set_animation(anim, force)
0, self.animation[anim .. "_loop"] ~= false) 0, self.animation[anim .. "_loop"] ~= false)
end end
-- global function to set mob animation [deprecated
function mobs:set_animation(entity, anim) function mobs:set_animation(entity, anim)
entity.set_animation(entity, anim) entity.set_animation(entity, anim)
end end
@ -630,7 +632,7 @@ local function ray_line_of_sight(self, pos1, pos2)
return true return true
end end
-- function line_of_sight autodetectyion with raycasting support if any
function mob_class:line_of_sight(pos1, pos2, stepsize) function mob_class:line_of_sight(pos1, pos2, stepsize)
if minetest.raycast then -- only use if minetest 5.0 is detected if minetest.raycast then -- only use if minetest 5.0 is detected
@ -640,12 +642,13 @@ function mob_class:line_of_sight(pos1, pos2, stepsize)
return line_of_sight(self, pos1, pos2, stepsize) return line_of_sight(self, pos1, pos2, stepsize)
end end
-- global function -- global function line of sight [deprecated]
function mobs:line_of_sight(entity, pos1, pos2, stepsize) function mobs:line_of_sight(entity, pos1, pos2, stepsize)
return entity:line_of_sight(pos1, pos2, stepsize) return entity:line_of_sight(pos1, pos2, stepsize)
end end
-- function attempt_flight_correction internal
function mob_class:attempt_flight_correction(override) function mob_class:attempt_flight_correction(override)
if self:flight_check() and override ~= true then return true end if self:flight_check() and override ~= true then return true end
@ -676,7 +679,7 @@ function mob_class:attempt_flight_correction(override)
end end
-- are we flying in what we are suppose to? (taikedz) -- function flight_check - are we flying in what we are suppose to? (taikedz)
function mob_class:flight_check() function mob_class:flight_check()
local def = minetest.registered_nodes[self.standing_in] local def = minetest.registered_nodes[self.standing_in]
@ -699,8 +702,8 @@ function mob_class:flight_check()
end end
-- turn mob to face position -- function yaw_to_pos turn mob to face position
local function yaw_to_pos(self, target, rot) function mob_class:yaw_to_pos(target, rot)
rot = rot or 0 rot = rot or 0
@ -717,12 +720,13 @@ local function yaw_to_pos(self, target, rot)
return yaw return yaw
end end
-- global [deprecated]
function mobs:yaw_to_pos(self, target, rot) function mobs:yaw_to_pos(self, target, rot)
return yaw_to_pos(self, target, rot) return self:yaw_to_pos(target, rot)
end end
-- if stay near set then periodically check for nodes and turn towards them -- function do_stay_near if stay near set then periodically check for nodes and turn towards them
function mob_class:do_stay_near() function mob_class:do_stay_near()
if not self.stay_near then return false end if not self.stay_near then return false end
@ -748,7 +752,7 @@ function mob_class:do_stay_near()
return false return false
end end
yaw_to_pos(self, nearby_nodes[random(#nearby_nodes)]) self:yaw_to_pos(nearby_nodes[random(#nearby_nodes)])
self:set_animation("walk") self:set_animation("walk")
@ -794,6 +798,7 @@ local function effect(
}) })
end end
-- global function effect
function mobs:effect( function mobs:effect(
pos, amount, texture, min_size, max_size, radius, gravity, glow, fall) pos, amount, texture, min_size, max_size, radius, gravity, glow, fall)
@ -808,7 +813,7 @@ local HORNY_AGAIN_TIME = 60 * 5 -- 5 minutes
local CHILD_GROW_TIME = 60 * 20 -- 20 minutes local CHILD_GROW_TIME = 60 * 20 -- 20 minutes
-- update nametag and infotext -- function update_tag update nametag and infotext
function mob_class:update_tag() function mob_class:update_tag()
local col local col
@ -858,7 +863,7 @@ function mob_class:update_tag()
end end
-- drop items -- function item_drop drop items
function mob_class:item_drop() function mob_class:item_drop()
-- no drops if disabled by setting or mob is child -- no drops if disabled by setting or mob is child
@ -941,7 +946,7 @@ function mob_class:item_drop()
end end
-- remove mob and descrease counter -- TODO make object class function - remove mob and descrease counter
local function remove_mob(self, decrease) local function remove_mob(self, decrease)
self.object:remove() self.object:remove()
@ -962,7 +967,7 @@ function mobs:remove(self, decrease)
end end
-- check if mob is dead or only hurt -- function check_for_deathcheck if mob is dead or only hurt
function mob_class:check_for_death(cmi_cause) function mob_class:check_for_death(cmi_cause)
-- We dead already -- We dead already
@ -1087,6 +1092,11 @@ local function node_ok(pos, fallback)
return minetest.registered_nodes[(fallback or mobs.fallback_node)] return minetest.registered_nodes[(fallback or mobs.fallback_node)]
end end
-- global function node_ok
function mobs:node_ok(pos, fallback)
return node_ok(pos, fallback)
end
-- Returns true is node can deal damage to self -- Returns true is node can deal damage to self
function mobs:is_node_dangerous(mob_object, nodename) function mobs:is_node_dangerous(mob_object, nodename)
@ -1118,7 +1128,7 @@ local function is_node_dangerous(mob_object, nodename)
end end
-- is mob facing a cliff -- function is_at_cliff is mob facing a cliff
function mob_class:is_at_cliff() function mob_class:is_at_cliff()
if self.driver or self.fear_height == 0 then -- 0 for no falling protection! if self.driver or self.fear_height == 0 then -- 0 for no falling protection!
@ -1157,7 +1167,29 @@ function mob_class:is_at_cliff()
end end
-- environmental damage (water, lava, fire, light etc.) -- function is_inside check for nodes or groups inside mob
function mob_class:is_inside(itemtable)
local cb
if self.object:get_properties() then
if self.object:get_properties().collisionbox then
cb = self.object:get_properties().collisionbox
else
cb = self.collisionbox
end
else
cb = self.collisionbox
end
local pos = self.object:get_pos()
local nn = minetest.find_nodes_in_area(
vector.offset(pos, cb[1], cb[2], cb[3]),
vector.offset(pos, cb[4], cb[5], cb[6]), itemtable)
if nn and #nn > 0 then return true else return false end
end
-- function do_env_damage environmental damage (water, lava, fire, light etc.)
function mob_class:do_env_damage() function mob_class:do_env_damage()
self:update_tag() self:update_tag()
@ -1196,7 +1228,7 @@ function mob_class:do_env_damage()
end end
-- lava damage -- lava damage
elseif self.lava_damage ~= 0 and nodef.groups.lava then elseif self.lava_damage ~= 0 and self:is_inside("group:lava") then -- nodef.groups.lava then
self.health = self.health - self.lava_damage self.health = self.health - self.lava_damage
@ -1301,7 +1333,7 @@ function mob_class:do_env_damage()
end end
-- jump if facing a solid node (not fences or gates) -- function do_jump jump if facing a solid node (not fences or gates)
function mob_class:do_jump() function mob_class:do_jump()
local vel = self.object:get_velocity() ; if not vel then return false end local vel = self.object:get_velocity() ; if not vel then return false end
@ -1417,7 +1449,7 @@ local function is_invisible(self, player_name)
end end
-- should mob follow what I'm holding ? -- function follow_holding should mob follow what I'm holding ?
function mob_class:follow_holding(clicker) function mob_class:follow_holding(clicker)
if is_invisible(self, clicker:get_player_name()) then if is_invisible(self, clicker:get_player_name()) then
@ -1435,7 +1467,7 @@ function mob_class:follow_holding(clicker)
end end
-- find two animals of same type and breed if nearby and horny -- function breed find two animals of same type and breed if nearby and horny
function mob_class:breed() function mob_class:breed()
-- child takes a long time before growing into adult -- child takes a long time before growing into adult
@ -1543,8 +1575,8 @@ function mob_class:breed()
local pos2 = ent.object:get_pos() local pos2 = ent.object:get_pos()
-- Have mobs face one another -- Have mobs face one another
yaw_to_pos(self, pos2) self:yaw_to_pos(pos2)
yaw_to_pos(ent, self.object:get_pos()) ent:yaw_to_pos(self.object:get_pos())
self.hornytimer = HORNY_TIME + 1 self.hornytimer = HORNY_TIME + 1
ent.hornytimer = HORNY_TIME + 1 ent.hornytimer = HORNY_TIME + 1
@ -1639,7 +1671,7 @@ function mob_class:breed()
end end
-- find and replace what mob is looking for (grass, wheat etc.) -- function replace find and replace what mob is looking for (grass, wheat etc.)
function mob_class:replace(pos) function mob_class:replace(pos)
local vel = self.object:get_velocity() local vel = self.object:get_velocity()
@ -1696,7 +1728,7 @@ function mob_class:replace(pos)
end end
-- check if daytime and also if mob is docile during daylight hours -- function day_docile check if daytime and also if mob is docile during daylight hours
function mob_class:day_docile() function mob_class:day_docile()
if self.docile_by_day == false then if self.docile_by_day == false then
@ -1751,6 +1783,7 @@ end
local pathfinder_mod = minetest.get_modpath("pathfinder") local pathfinder_mod = minetest.get_modpath("pathfinder")
-- function smart_mobs
-- path finding and smart mob routine by rnd, -- path finding and smart mob routine by rnd,
-- line_of_sight and other edits by Elkien3 -- line_of_sight and other edits by Elkien3
function mob_class:smart_mobs(s, p, dist, dtime) function mob_class:smart_mobs(s, p, dist, dtime)
@ -2001,12 +2034,12 @@ end
local function is_peaceful_player(player) local function is_peaceful_player(player)
-- main setting enabled -- main setting enabled
if peaceful_player_enabled and player:is_player() then if is_player(player) then
local player_name = player:get_player_name() local player_name = player:get_player_name()
-- player priv enabled -- player priv enabled
if player_name and minetest.check_player_privs(player_name, "peaceful_player") then if player_name and peaceful_player_enabled and minetest.check_player_privs(player_name, "peaceful_player") then
return true return true
end end
end end
@ -2015,7 +2048,7 @@ local function is_peaceful_player(player)
end end
-- general attack function for all mobs -- function general_attack function for all mobs
function mob_class:general_attack() function mob_class:general_attack()
-- return if already attacking, passive or docile during day -- return if already attacking, passive or docile during day
@ -2042,8 +2075,7 @@ function mob_class:general_attack()
or self.attack_players == false or self.attack_players == false
or (self.owner and self.type ~= "monster") or (self.owner and self.type ~= "monster")
or is_invisible(self, objs[n]:get_player_name()) or is_invisible(self, objs[n]:get_player_name())
or (self.specific_attack or (self.specific_attack and not check_for("player", self.specific_attack)) then
and not check_for("player", self.specific_attack)) then
objs[n] = nil objs[n] = nil
--print("- pla", n) --print("- pla", n)
end end
@ -2055,10 +2087,8 @@ function mob_class:general_attack()
-- monsters attack all creatura mobs, npc and animals will only attack -- monsters attack all creatura mobs, npc and animals will only attack
-- if the animal owner is currently being attacked by creatura mob -- if the animal owner is currently being attacked by creatura mob
if self.name == ent.name if self.name == ent.name
or (self.type ~= "monster" or (self.type ~= "monster" and self.owner ~= (ent._target and ent._target:get_player_name() or "."))
and self.owner ~= (ent._target and ent._target:get_player_name() or ".")) or (self.specific_attack and not check_for(ent.name, self.specific_attack)) then
or (self.specific_attack
and not check_for(ent.name, self.specific_attack)) then
objs[n] = nil objs[n] = nil
--print("-- creatura", ent.name) --print("-- creatura", ent.name)
@ -2072,8 +2102,7 @@ function mob_class:general_attack()
or (not self.attack_animals and ent.type == "animal") or (not self.attack_animals and ent.type == "animal")
or (not self.attack_monsters and ent.type == "monster") or (not self.attack_monsters and ent.type == "monster")
or (not self.attack_npcs and ent.type == "npc") or (not self.attack_npcs and ent.type == "npc")
or (self.specific_attack or (self.specific_attack and not check_for(ent.name, self.specific_attack)) then
and not check_for(ent.name, self.specific_attack)) then
objs[n] = nil objs[n] = nil
--print("- mob", n, self.name, ent.name) --print("- mob", n, self.name, ent.name)
end end
@ -2117,7 +2146,7 @@ function mob_class:general_attack()
end end
-- find someone to runaway from -- function do_runaway_from find someone to runaway from
function mob_class:do_runaway_from() function mob_class:do_runaway_from()
if not self.runaway_from then if not self.runaway_from then
@ -2177,7 +2206,7 @@ function mob_class:do_runaway_from()
if min_player then if min_player then
yaw_to_pos(self, min_player:get_pos(), 3) self:yaw_to_pos(min_player:get_pos(), 3)
self.state = "runaway" self.state = "runaway"
self.runaway_timer = 3 self.runaway_timer = 3
@ -2191,7 +2220,7 @@ function mob_class:do_runaway_from()
if objs then if objs then
yaw_to_pos(self, objs, 3) self:yaw_to_pos(objs, 3)
self.state = "runaway" self.state = "runaway"
self.runaway_timer = 3 self.runaway_timer = 3
@ -2200,7 +2229,7 @@ function mob_class:do_runaway_from()
end end
-- follow player if owner or holding item, if fish outta water then flop -- function follow_flop follow player if owner or holding item, if fish outta water then flop
function mob_class:follow_flop() function mob_class:follow_flop()
-- find player to follow -- find player to follow
@ -2215,7 +2244,7 @@ function mob_class:follow_flop()
for n = 1, #players do for n = 1, #players do
if players[n] then if players[n] then
if players[n]:is_player() then if is_player(players[n]) then
if not is_invisible(self, players[n]:get_player_name()) if not is_invisible(self, players[n]:get_player_name())
and get_distance(players[n]:get_pos(), s) < self.view_range then and get_distance(players[n]:get_pos(), s) < self.view_range then
self.following = players[n] self.following = players[n]
@ -2239,7 +2268,7 @@ function mob_class:follow_flop()
else else
-- stop following player if not holding specific item or mob is horny -- stop following player if not holding specific item or mob is horny
if self.following and is_player(self.following) if self.following and is_player(self.following)
and (self:follow_holding(self.following) == false or self.horny) then and (self.horny or not self:follow_holding(self.following)) then
self.following = nil self.following = nil
end end
@ -2265,7 +2294,7 @@ function mob_class:follow_flop()
if dist > self.view_range then if dist > self.view_range then
self.following = nil self.following = nil
else else
yaw_to_pos(self, p) self:yaw_to_pos(p)
-- anyone but standing npc's can move along -- anyone but standing npc's can move along
if dist >= self.reach if dist >= self.reach
@ -2316,7 +2345,7 @@ function mob_class:follow_flop()
end end
-- dogshoot attack switch and counter function -- function dogswitch dogshoot attack switch and counter function
function mob_class:dogswitch(dtime) function mob_class:dogswitch(dtime)
-- switch mode not activated -- switch mode not activated
@ -2342,7 +2371,7 @@ function mob_class:dogswitch(dtime)
end end
-- stop attack -- function stop_attack
function mob_class:stop_attack() function mob_class:stop_attack()
self.attack = nil self.attack = nil
@ -2357,7 +2386,7 @@ function mob_class:stop_attack()
end end
-- execute current state (stand, walk, run, attacks) -- function do_states execute current state (stand, walk, run, attacks)
function mob_class:do_states(dtime) function mob_class:do_states(dtime)
local yaw = self.object:get_yaw() ; if not yaw then return end local yaw = self.object:get_yaw() ; if not yaw then return end
@ -2389,7 +2418,7 @@ function mob_class:do_states(dtime)
-- select position of random block to climb onto -- select position of random block to climb onto
lp = lp[random(#lp)] lp = lp[random(#lp)]
yaw = yaw_to_pos(self, lp) yaw = self:yaw_to_pos(lp)
end end
self.pause_timer = 3 self.pause_timer = 3
@ -2421,7 +2450,7 @@ function mob_class:do_states(dtime)
-- look at any players nearby, otherwise turn randomly -- look at any players nearby, otherwise turn randomly
if lp then if lp then
yaw = yaw_to_pos(self, lp) yaw = self:yaw_to_pos(lp)
else else
yaw = yaw + random(-0.5, 0.5) yaw = yaw + random(-0.5, 0.5)
end end
@ -2499,8 +2528,8 @@ function mob_class:do_states(dtime)
self.runaway_timer = self.runaway_timer + 1 self.runaway_timer = self.runaway_timer + 1
-- stop after 5 seconds or when at cliff -- stop early after 3 or 2 seconds or when at cliff cos defaults start at 0 but on some states is 3
if self.runaway_timer > 5 if self.runaway_timer > 4
or self.at_cliff or self.at_cliff
or self.order == "stand" then or self.order == "stand" then
self.runaway_timer = 0 self.runaway_timer = 0
@ -2526,17 +2555,11 @@ function mob_class:do_states(dtime)
local dist = p and get_distance(p, s) or 500 local dist = p and get_distance(p, s) or 500
-- stop attacking if player out of range or invisible -- stop attacking if player out of range or invisible
if dist > self.view_range if dist > self.view_range and not self.attack and not is_player(self.attack) then
or not self.attack if not self.attack:get_pos() or self.attack:get_hp() <= 0 and is_invisible(self, self.attack:get_player_name()) then
or not self.attack:get_pos()
or self.attack:get_hp() <= 0
or (is_player(self.attack)
and is_invisible(self, self.attack:get_player_name())) then
--print(" ** stop attacking **", self.name, self.health, dist, self.view_range) --print(" ** stop attacking **", self.name, self.health, dist, self.view_range)
self:stop_attack() self:stop_attack()
end
return return
end end
@ -2559,7 +2582,7 @@ function mob_class:do_states(dtime)
if self.attack_type == "explode" then if self.attack_type == "explode" then
yaw_to_pos(self, p) self:yaw_to_pos(p)
local node_break_radius = self.explosion_radius or 1 local node_break_radius = self.explosion_radius or 1
local entity_damage_radius = self.explosion_damage_radius local entity_damage_radius = self.explosion_damage_radius
@ -2710,7 +2733,7 @@ function mob_class:do_states(dtime)
p = {x = p1.x, y = p1.y, z = p1.z} p = {x = p1.x, y = p1.y, z = p1.z}
end end
yaw_to_pos(self, p) self:yaw_to_pos(p)
-- move towards enemy if beyond mob reach -- move towards enemy if beyond mob reach
if dist > (self.reach + (self.reach_ext or 0)) then if dist > (self.reach + (self.reach_ext or 0)) then
@ -2802,7 +2825,7 @@ function mob_class:do_states(dtime)
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_to_pos(self, p) self:yaw_to_pos(p)
self:set_velocity(0) self:set_velocity(0)
@ -2849,7 +2872,7 @@ function mob_class:do_states(dtime)
end end
-- falling and fall damage -- function falling and fall damage
function mob_class:falling(pos) function mob_class:falling(pos)
if self.fly or self.disable_falling then if self.fly or self.disable_falling then
@ -2904,7 +2927,7 @@ end
-- is Took Ranks mod active? -- is Took Ranks mod active?
local tr = minetest.get_modpath("toolranks") local tr = minetest.get_modpath("toolranks")
-- deal damage and effects when mob punched -- function on_punch deal damage and effects when mob punched
function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage) function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
-- mob health check -- mob health check
@ -3150,7 +3173,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage)
local lp = hitter:get_pos() local lp = hitter:get_pos()
yaw_to_pos(self, lp, 3) self:yaw_to_pos(lp, 3)
self.state = "runaway" self.state = "runaway"
self.runaway_timer = 0 self.runaway_timer = 0
@ -3225,7 +3248,7 @@ local function clean_staticdata(self)
end end
-- get entity staticdata -- function mob_staticdata get entity staticdata
function mob_class:mob_staticdata() function mob_class:mob_staticdata()
-- this handles mob count for mobs activated, unloaded, reloaded -- this handles mob count for mobs activated, unloaded, reloaded
@ -3290,7 +3313,7 @@ function mob_class:mob_staticdata()
end end
-- activate mob and reload settings -- function mob_activate activate mob and reload settings
function mob_class:mob_activate(staticdata, def, dtime) function mob_class:mob_activate(staticdata, def, dtime)
-- if dtime == 0 then entity has just been created -- if dtime == 0 then entity has just been created
@ -3462,7 +3485,7 @@ function mob_class:mob_activate(staticdata, def, dtime)
end end
-- handle mob lifetimer and expiration -- function mob_expire handle mob lifetimer and expiration
function mob_class:mob_expire(pos, dtime) function mob_class:mob_expire(pos, dtime)
-- when lifetimer expires remove mob (except npc and tamed) -- when lifetimer expires remove mob (except npc and tamed)
@ -3501,7 +3524,7 @@ function mob_class:mob_expire(pos, dtime)
end end
-- get nodes mob is standing on/in, facing/above -- function get_nodes get nodes mob is standing on/in, facing/above
function mob_class:get_nodes() function mob_class:get_nodes()
local pos = self.object:get_pos() local pos = self.object:get_pos()
@ -3545,7 +3568,7 @@ print("on: " .. self.standing_on
end end
-- main mob function -- function on_step main mob function
function mob_class:on_step(dtime, moveresult) function mob_class:on_step(dtime, moveresult)
if self.state == "die" then return end if self.state == "die" then return end
@ -3701,7 +3724,7 @@ function mob_class:on_step(dtime, moveresult)
end end
-- default function when mobs are blown up with TNT -- function on_blast default function when mobs are blown up with TNT
function mob_class:on_blast(damage) function mob_class:on_blast(damage)
--print("-- blast damage", damage) --print("-- blast damage", damage)
@ -3989,8 +4012,13 @@ function mobs:add_mob(pos, def)
effect(pos, 15, "tnt_smoke.png", 1, 2, 2, 15, 5) effect(pos, 15, "tnt_smoke.png", 1, 2, 2, 15, 5)
end end
-- use new texture if found
local new_texture = def.texture or ent.base_texture
if def.child then if def.child then
ent.mommy_tex = new_texture -- how baby looks when grown
ent.base_texture = new_texture
local textures = ent.base_texture local textures = ent.base_texture
-- using specific child texture (if found) -- using specific child texture (if found)
@ -4024,6 +4052,12 @@ function mobs:add_mob(pos, def)
}) })
ent.child = true ent.child = true
-- if not child set new texture
elseif def.texture then
ent.base_texture = new_texture
mob:set_properties({textures = new_texture})
end end
if def.owner then if def.owner then
@ -4194,6 +4228,11 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
local ent = minetest.registered_entities[name] local ent = minetest.registered_entities[name]
if not ent or not ent.base_colbox then
print("[MOBS] Error spawning mob: " .. name)
return
end
-- should we check mob area for obstructions ? -- should we check mob area for obstructions ?
if mob_area_spawn ~= true then if mob_area_spawn ~= true then
@ -4496,6 +4535,16 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative)
"^[mask:mobs_chicken_egg_overlay.png)" "^[mask:mobs_chicken_egg_overlay.png)"
end end
-- does mob/entity exist
local is_mob = minetest.registered_entities[mob]
if not is_mob then
print("[Mobs Redo] Spawn Egg cannot be created for " .. mob)
return
end
-- these are only created for animals and npc mobs, not monsters TODO
-- if is_mob.type ~= "monster" then return end
-- register new spawn egg containing mob information (cannot be stacked) -- register new spawn egg containing mob information (cannot be stacked)
minetest.register_craftitem(mob .. "_set", { minetest.register_craftitem(mob .. "_set", {
@ -4518,10 +4567,15 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative)
pointed_thing.under, under, placer, itemstack, pointed_thing) pointed_thing.under, under, placer, itemstack, pointed_thing)
end end
if pos if pos and not minetest.is_protected(pos, placer:get_player_name()) then
and not minetest.is_protected(pos, placer:get_player_name()) then
if not minetest.registered_entities[mob] then if active_limit > 0 and active_mobs >= active_limit then
if is_player(placer) then
minetest.chat_send_player(placer:get_player_name(),
S("Active Mob Limit Reached!")
.. " (" .. active_mobs
.. " / " .. active_limit .. ")")
end
return return
end end
@ -4571,16 +4625,14 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative)
if pos and not minetest.is_protected(pos, placer:get_player_name()) then if pos and not minetest.is_protected(pos, placer:get_player_name()) then
if not minetest.registered_entities[mob] then
return
end
-- have we reached active mob limit -- have we reached active mob limit
if active_limit > 0 and active_mobs >= active_limit then if active_limit > 0 and active_mobs >= active_limit then
if is_player(placer) then
minetest.chat_send_player(placer:get_player_name(), minetest.chat_send_player(placer:get_player_name(),
S("Active Mob Limit Reached!") S("Active Mob Limit Reached!")
.. " (" .. active_mobs .. " (" .. active_mobs
.. " / " .. active_limit .. ")") .. " / " .. active_limit .. ")")
end
return return
end end
@ -4790,7 +4842,7 @@ function mobs:protect(self, clicker)
pos.y = pos.y + self.collisionbox[2] + 0.5 pos.y = pos.y + self.collisionbox[2] + 0.5
effect(self.object:get_pos(), 25, "mobs_protect_particle.png", 0.5, 4, 2, 15) effect(pos, 25, "mobs_protect_particle.png", 0.5, 4, 2, 15)
self:mob_sound("mobs_spell") self:mob_sound("mobs_spell")

19
api.txt
View File

@ -388,14 +388,31 @@ for each mob.
'self.facing_fence' True if mob facing node containing "wall", "fence", "gate" 'self.facing_fence' True if mob facing node containing "wall", "fence", "gate"
in it's name. in it's name.
Internal Functions Internal Functions
------------------ ------------------
Each mob contains a set of functions that can be called for use internally or from Each mob contains a set of functions that can be called for use internally or from
another mod entirely, replace mob_class with the mob entity variable: another mod entirely, replace mob_class with the mob entity variable:
mob_class:mob_sound(sound) -- play sound at mob position
mob_class:do_attack(player) -- if not already attacking, attack object given
mob_class:stop_attack() -- stops mob attacking mob_class:stop_attack() -- stops mob attacking
mob_class:collision() -- checks for player collision with mob and returns {x, z} vector
mob_class:set_velocity(velocity) -- move at velocity in the facing direction
mob_class:get_velocity() -- returns mob speed value
mob_class:set_yaw(yaw, delay) -- change mob yaw, delay is for smooth rotation (default:0)
mob_class:yaw_to_pos(pos, delay) -- rotates mod to look at position and returns new yaw
mob_class:set_animation(animation, force) -- set mob animation
mob_class:line_of_sight(pos1, pos2) -- internal line of sight function
mob_class:attempt_flight_correction(override) -- check for stuck flying mobs and fix
mob_class:update_tag(newname) -- update nametag or give new name
mob_class:do_jump() -- check if mob can jump then jump
mob_class:follow_holding(clicker) -- return True if mob likes what player is holding
mob_class:day_docile() -- return True if mob docile during current daytime
mob_class:mob_expire(pos, dtime) -- check if mob is to despawn
mob_class:get_nodes() -- get specific nodes around mob
mob_class:on_blast(damage) -- function called when mob in blast area
mob_class:is_inside(itemtable) -- returns True is mob collisionbox inside any node/group in table
Adding Mobs in World Adding Mobs in World