Add coord safe infinite particlespawners api for mobs

This commit is contained in:
cora 2022-10-10 03:42:51 +02:00 committed by Gitea
parent dc873f4de2
commit ef4b243a30
2 changed files with 64 additions and 1 deletions

View file

@ -68,6 +68,7 @@ local disable_blood = minetest.settings:get_bool("mobs_disable_blood")
local mobs_drop_items = minetest.settings:get_bool("mobs_drop_items") ~= false local mobs_drop_items = minetest.settings:get_bool("mobs_drop_items") ~= false
local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false
local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false
local player_transfer_distance = minetest.settings:get("player_transfer_distance") or 128
local remove_far = true local remove_far = true
local difficulty = tonumber(minetest.settings:get("mob_difficulty")) or 1.0 local difficulty = tonumber(minetest.settings:get("mob_difficulty")) or 1.0
local show_health = false local show_health = false
@ -84,6 +85,8 @@ if minetest.settings:get_bool("only_peaceful_mobs", false) then
end) end)
end end
local active_particlespawners = {}
local function dir_to_pitch(dir) local function dir_to_pitch(dir)
--local dir2 = vector.normalize(dir) --local dir2 = vector.normalize(dir)
@ -121,6 +124,60 @@ minetest.register_chatcommand("clearmobs",{
end end
end}) end})
local function remove_particlespawners(pn,self)
if not active_particlespawners[pn] then return end
if not active_particlespawners[pn][self.object] then return end
for k,v in pairs(active_particlespawners[pn][self.object]) do
minetest.delete_particlespawner(v)
end
end
local function add_particlespawners(pn,self)
if not active_particlespawners[pn] then active_particlespawners[pn] = {} end
if not active_particlespawners[pn][object] then active_particlespawners[pn][self.object] = {} end
for _,ps in pairs(self.particlespawners) do
ps.attached = self.object
ps.playername = pn
table.insert(active_particlespawners[pn][self.object],minetest.add_particlespawner(ps))
end
end
local function particlespawner_check(self,dtime)
if not self.particlespawners then return end
--minetest.log(dump(active_particlespawners))
if self._particle_timer and self._particle_timer >= 1 then
self._particle_timer = 0
local players = {}
for _,player in pairs(minetest.get_connected_players()) do
local pn = player:get_player_name()
table.insert(players,pn)
if not active_particlespawners[pn] then
active_particlespawners[pn] = {} end
local dst = vector.distance(player:get_pos(),self.object:get_pos())
if dst < player_transfer_distance and not active_particlespawners[pn][self.object] then
add_particlespawners(pn,self)
elseif dst >= player_transfer_distance and active_particlespawners[pn][self.object] then
remove_particlespawners(pn,self)
end
end
elseif not self._particle_timer then
self._particle_timer = 0
end
self._particle_timer = self._particle_timer + dtime
end
minetest.register_on_leaveplayer(function(player)
local pn = player:get_player_name()
if not active_particlespawners[pn] then return end
for _,m in pairs(active_particlespawners[pn]) do
for k,v in pairs(m) do
minetest.delete_particlespawner(v)
end
end
active_particlespawners[pn] = nil
end)
----For Water Flowing: ----For Water Flowing:
local enable_physics = function(object, luaentity, ignore_check) local enable_physics = function(object, luaentity, ignore_check)
if luaentity.physical_state == false or ignore_check == true then if luaentity.physical_state == false or ignore_check == true then
@ -3477,7 +3534,9 @@ end
-- get entity staticdata -- get entity staticdata
local mob_staticdata = function(self) local mob_staticdata = function(self)
for _,p in pairs(minetest.get_connected_players()) do
remove_particlespawners(p:get_player_name(),self)
end
-- remove mob when out of range unless tamed -- remove mob when out of range unless tamed
if remove_far if remove_far
and self.can_despawn and self.can_despawn
@ -3711,6 +3770,7 @@ local mob_step = function(self, dtime)
self.lifetimer = self.lifetimer - dtime self.lifetimer = self.lifetimer - dtime
check_item_pickup(self) check_item_pickup(self)
check_aggro(self,dtime) check_aggro(self,dtime)
particlespawner_check(self,dtime)
if not self.fire_resistant then if not self.fire_resistant then
mcl_burning.tick(self.object, dtime, self) mcl_burning.tick(self.object, dtime, self)
-- mcl_burning.tick may remove object immediately -- mcl_burning.tick may remove object immediately
@ -4226,6 +4286,7 @@ minetest.register_entity(name, {
spawn_in_group = def.spawn_in_group, spawn_in_group = def.spawn_in_group,
spawn_in_group_min = def.spawn_in_group_min, spawn_in_group_min = def.spawn_in_group_min,
noyaw = def.noyaw or false, noyaw = def.noyaw or false,
particlespawners = def.particlespawners,
-- End of MCL2 extensions -- End of MCL2 extensions
on_spawn = def.on_spawn, on_spawn = def.on_spawn,

View file

@ -260,6 +260,8 @@ functions needed for the mob to work properly which contains the following:
'pick_up' table of itemstrings the mob will pick up (e.g. for breeding) 'pick_up' table of itemstrings the mob will pick up (e.g. for breeding)
'on_pick_up' function that will be called on item pickup - return true to not pickup the item 'on_pick_up' function that will be called on item pickup - return true to not pickup the item
'custom_visual_size' will not reset visual_size from the base class on reload 'custom_visual_size' will not reset visual_size from the base class on reload
'noyaw' If true this mob will not automatically change yaw
'particlespawners' Table of particlespawners attached to the mob. This is implemented in a coord safe manner i.e. spawners are only sent to players within the player_transfer_distance (and automatically removed). This enables infinitely lived particlespawners.
mobs:gopath(self,target,callback_arrived) pathfind a way to target and run callback on arrival mobs:gopath(self,target,callback_arrived) pathfind a way to target and run callback on arrival