Compare commits

..

No commits in common. "e58f20bebb2cb381d03fd5263fb6ba73147c6c5b" and "8ddc9217895072f94f635a54576e355319d65e15" have entirely different histories.

2 changed files with 92 additions and 161 deletions

234
api.lua
View File

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

19
api.txt
View File

@ -388,31 +388,14 @@ for each mob.
'self.facing_fence' True if mob facing node containing "wall", "fence", "gate"
in it's name.
Internal Functions
------------------
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:
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: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