nssm.lessvirulent = core.settings:get_bool("nssm.lessvirulent") or false nssm.safebones = core.settings:get_bool("nssm.safebones") or false nssm.cryosave = core.settings:get_bool("nssm.cryosave") or false local function virulence(mobe) if not nssm.lessvirulent then return 0 end return math.ceil(100 / mobe.hp_max) end function nssm:affectbones(mobe) -- as function for adaptable heuristic return not nssm.safebones end function nssm:drops(drop) if drop then drop:set_velocity({ x = math.random(-10, 10) / 9, y = 5, z = math.random(-10, 10) / 9 }) end end local function perpendicular_vector(vec) --returns a vector rotated of 90° in 2D local ang = math.pi / 2 local c = math.cos(ang) local s = math.sin(ang) local i = vec.x * c - vec.z * s local k = vec.x * s + vec.z * c local j = 0 return {x = i, y = j, z = k} end function nssm:add_entity_and_particles(entity, pos, particles, multiplier) core.add_particlespawner({ amount = 100 * multiplier, time = 2, minpos = {x = pos.x - 2, y = pos.y - 1, z = pos.z - 2}, maxpos = {x = pos.x + 2, y = pos.y + 4, z = pos.z + 2}, minvel = {x = 0, y = 0, z = 0}, maxvel = {x = 1, y = 2, z = 1}, minacc = {x = -0.5, y = 0.6, z = -0.5}, maxacc = {x = 0.5, y = 0.7, z = 0.5}, minexptime = 2, maxexptime = 3, minsize = 3, maxsize = 5, collisiondetection = false, vertical = false, texture = particles }) core.add_entity(pos, entity) end -- compatibility function function nssm:node_ok(pos, fallback) return mobs:node_ok(pos, fallback) end function nssm:dist_pos(p, s) local v = { x = math.abs(s.x - p.x), y = math.abs(s.y - p.y), z = math.abs(s.z - p.z) } return math.sqrt(v.x ^ 2 + v.y ^ 2 + v.z ^ 2) end local function round(n) if (n > 0) then return n % 1 >= 0.5 and math.ceil(n) or math.floor(n) else n = -n local t = n % 1 >= 0.5 and math.ceil(n) or math.floor(n) return -t end end function nssm:explosion_particles(pos, exp_radius) core.add_particlespawner({ amount = 100 * exp_radius / 2, time = 0.1, minpos = {x = pos.x - exp_radius, y = pos.y - exp_radius, z = pos.z - exp_radius}, maxpos = {x = pos.x + exp_radius, y = pos.y + exp_radius, z = pos.z + exp_radius}, minvel = {x = 0, y = 0, z = 0}, maxvel = {x = 0.1, y = 0.3, z = 0.1}, minacc = {x = -0.5, y = 1, z = -0.5}, maxacc = {x = 0.5, y = 1, z = 0.5}, minexptime = 0.1, maxexptime = 4, minsize = 6, maxsize = 12, collisiondetection = false, texture = "tnt_smoke.png" }) end function nssm:digging_attack( self, --the entity of the mob group, --group of the blocks the mob can dig: nil=everything max_vel, --max velocity of the mob dim --vector representing the dimensions of the mob ) if self.attack and self.attack:is_player() then local s = self.object:get_pos() local p = self.attack:get_pos() local dir = vector.subtract(p,s) dir = vector.normalize(dir) local per = perpendicular_vector(dir) local posp = vector.add(s,dir) posp = vector.subtract(posp,per) for j = 1, 3 do if core.is_protected(posp, "") then return end local pos1 = posp for i = 0, dim.y do local n = core.get_node(pos1).name if group == nil then if core.get_item_group(n, "unbreakable") == 1 or core.is_protected(pos1, "") or (n == "bones:bones" and not nssm:affectbones(self) ) then else core.remove_node(pos1) end else if ((core.get_item_group(n, group) == 1) and (core.get_item_group(n, "unbreakable") ~= 1) and (n ~= "bones:bones") and not (core.is_protected(pos1, "")) ) then core.remove_node(pos1) end end pos1.y = pos1.y + 1 end posp.y = s.y posp = vector.add(posp,per) end end end function nssm:putting_ability( --puts under the mob the block defined as 'p_block' self, --the entity of the mob p_block, --definition of the block to use max_vel --max velocity of the mob ) local v = self.object:get_velocity() ; if not v then return end local dx = 0 local dz = 0 if math.abs(v.x) > math.abs(v.z) then if (v.x) > 0 then dx = 1 else dx = -1 end else if (v.z) > 0 then dz = 1 else dz = -1 end end local pos = self.object:get_pos() local pos1 pos.y = pos.y - 1 pos1 = {x = pos.x + dx, y = pos.y, z = pos.z + dz} local n = core.get_node(pos).name local n1 = core.get_node(pos1).name local oldmetainf = { core.get_meta(pos):to_table(), core.get_meta(pos1):to_table() } if n ~= p_block and not core.is_protected(pos, "") and (n == "bones:bones" and nssm:affectbones(self) ) and n ~= "air" then core.set_node(pos, {name=p_block}) if nssm.cryosave then local metai = core.get_meta(pos) metai:from_table(oldmetainf[1]) -- this is enough to save the meta metai:set_string("nssm", n) end end if n1 ~= p_block and not core.is_protected(pos1, "") and (n == "bones:bones" and nssm:affectbones(self) ) and n ~= "air" then core.set_node(pos1, {name = p_block}) if nssm.cryosave then local metai = core.get_meta(pos1) metai:from_table(oldmetainf[2]) -- this is enough to save the meta metai:set_string("nssm", n1) end end end function nssm:webber_ability( --puts randomly around the block defined as w_block self, --the entity of the mob w_block, --definition of the block to use radius --max distance the block can be put ) if virulence(self) ~= 0 and math.random(1, virulence(self)) ~= 1 then return end local pos = self.object:get_pos() if math.random(55) == 1 then local dx = math.random(radius) local dz = math.random(radius) local p = {x = pos.x + dx, y = pos.y - 1, z = pos.z + dz} local t = {x = pos.x + dx, y = pos.y, z = pos.z + dz} local n = core.get_node(p).name local k = core.get_node(t).name if (n ~= "air" and k == "air") and not core.is_protected(t, "") then core.set_node(t, {name = w_block}) end end end function nssm:midas_ability( --ability to transform every blocks it touches in the m_block block self, --the entity of the mob m_block, max_vel, --max velocity of the mob mult, --multiplier of the dimensions of the area around that need the transformation height --height of the mob ) local v = self.object:get_velocity() ; if not v then return end local pos = self.object:get_pos() if core.is_protected(pos, "") then return end local max = 0 local yaw = (self.object:get_yaw() + self.rotate) or 0 local x = math.sin(yaw) * -1 local z = math.cos(yaw) local i = 1 local i1 = -1 local k = 1 local k1 = -1 local multiplier = mult if x > 0 then i = round(x * max_vel) * multiplier else i1 = round(x * max_vel) * multiplier end if z > 0 then k = round(z * max_vel) * multiplier else k1 = round(z * max_vel) * multiplier end for dx = i1, i do for dy = -1, height do for dz = k1, k do local p = {x = pos.x + dx, y = pos.y + dy, z = pos.z + dz} local n = core.get_node(p).name local d = core.registered_nodes[n] if d.drawtype ~= "normal" or n == m_block or core.get_item_group(n, "unbreakable") == 1 or core.is_protected(p, "") or (n == "bones:bones" and not nssm:affectbones(self)) then -- do nothing else core.set_node(p, {name = m_block}) end end end end end