EinsDreiDreiSieben/mods/nssm/nssm_api.lua
2025-05-10 23:49:11 +02:00

339 lines
7.1 KiB
Lua

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