1
0
mirror of https://github.com/sys4-fr/server-nalc.git synced 2024-09-27 15:00:35 +02:00

Update API.lua of mobs mod

This commit is contained in:
Ombridride 2015-04-27 22:38:49 +02:00
parent 7494dd8aa8
commit 720b7629c5

198
mods/mobs/api.lua Executable file → Normal file
View File

@ -1,4 +1,4 @@
-- Mobs Api (20th April 2015) -- Mobs Api (26th April 2015)
mobs = {} mobs = {}
mobs.mod = "redo" mobs.mod = "redo"
@ -16,11 +16,11 @@ function mobs:register_mob(name, def)
owner = def.owner, owner = def.owner,
order = def.order or "", order = def.order or "",
on_die = def.on_die, on_die = def.on_die,
jump_height = def.jump_height or 6, jump_height = def.jump_height or 6,
jump_chance = def.jump_chance or 0, jump_chance = def.jump_chance or 0,
rotate = def.rotate or 0, -- 0=front, 1.5=side, 3.0=back, 4.5=side2 rotate = def.rotate or 0, -- 0=front, 1.5=side, 3.0=back, 4.5=side2
lifetimer = def.lifetimer or 600, lifetimer = def.lifetimer or 600,
hp_min = def.hp_min or 5, hp_min = def.hp_min or 5,
hp_max = def.hp_max or 10, hp_max = def.hp_max or 10,
physical = true, physical = true,
@ -312,9 +312,12 @@ function mobs:register_mob(name, def)
if self.type == "monster" and damage_enabled and self.state ~= "attack" then if self.type == "monster" and damage_enabled and self.state ~= "attack" then
local s = self.object:getpos() local s = self.object:getpos()
local p, sp, dist
local player = nil local player = nil
local type = nil local type = nil
local obj = nil local obj = nil
local min_dist = self.view_range + 1
local min_player = nil
for _,oir in ipairs(minetest.get_objects_inside_radius(s,self.view_range)) do for _,oir in ipairs(minetest.get_objects_inside_radius(s,self.view_range)) do
@ -337,30 +340,43 @@ function mobs:register_mob(name, def)
sp.y = sp.y + 1 -- aim higher to make looking up hills more realistic sp.y = sp.y + 1 -- aim higher to make looking up hills more realistic
local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
if dist < self.view_range then -- and self.in_fov(self,p) then if dist < self.view_range then -- and self.in_fov(self,p) then
if minetest.line_of_sight(sp,p,2) == true then -- choose closest player to attack
self.do_attack(self,player,dist) if minetest.line_of_sight(sp,p,2) == true
break and dist < min_dist then
min_dist = dist
min_player = player
end end
end end
end end
end end
-- attack player
if min_player then
self.do_attack(self, min_player, min_dist)
end
end end
-- npc, find monster to attack -- npc, find closest monster to attack
local min_dist = self.view_range + 1
local min_player = nil
if self.type == "npc" and self.attacks_monsters and self.state ~= "attack" then if self.type == "npc" and self.attacks_monsters and self.state ~= "attack" then
local s = self.object:getpos() local s = self.object:getpos()
local obj = nil local obj = nil
local p, dist
for _, oir in pairs(minetest.get_objects_inside_radius(s,self.view_range)) do for _, oir in pairs(minetest.get_objects_inside_radius(s,self.view_range)) do
obj = oir:get_luaentity() obj = oir:get_luaentity()
if obj and obj.type == "monster" then if obj and obj.type == "monster" then
-- attack monster -- attack monster
p = obj.object:getpos() p = obj.object:getpos()
dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
self.do_attack(self,obj.object,dist) if dist < min_dist then
break min_dist = dist
min_player = obj.object
end
end end
end end
if min_player then
self.do_attack(self, min_player, min_dist)
end
end end
-- horny animal can mate for 40 seconds, afterwards horny animal cannot mate again for 200 seconds -- horny animal can mate for 40 seconds, afterwards horny animal cannot mate again for 200 seconds
@ -548,7 +564,6 @@ function mobs:register_mob(name, def)
elseif self.state == "walk" then elseif self.state == "walk" then
local lp = nil
local s = self.object:getpos() local s = self.object:getpos()
-- if there is water nearby, try to avoid it -- if there is water nearby, try to avoid it
local lp = minetest.find_node_near(s, 2, {"group:water"}) local lp = minetest.find_node_near(s, 2, {"group:water"})
@ -578,7 +593,7 @@ function mobs:register_mob(name, def)
self:set_animation("stand") self:set_animation("stand")
end end
-- Modif MFF "attack type kamicaze" des creepers /DEBUT -- exploding mobs
elseif self.state == "attack" and self.attack_type == "explode" then elseif self.state == "attack" and self.attack_type == "explode" then
if not self.attack.player or not self.attack.player:is_player() then if not self.attack.player or not self.attack.player:is_player() then
self.state = "stand" self.state = "stand"
@ -631,20 +646,20 @@ function mobs:register_mob(name, def)
self.set_velocity(self, 0) self.set_velocity(self, 0)
self.timer = self.timer + dtime self.timer = self.timer + dtime
self.blinktimer = (self.blinktimer or 0) + dtime self.blinktimer = (self.blinktimer or 0) + dtime
if self.blinktimer > 0.2 then if self.blinktimer > 0.2 then
self.blinktimer = 0 -- self.blinktimer - 0.2 self.blinktimer = 0
if self.blinkstatus then if self.blinkstatus then
self.object:settexturemod("") self.object:settexturemod("")
else else
self.object:settexturemod("^[brighten") self.object:settexturemod("^[brighten")
end
self.blinkstatus = not self.blinkstatus
end end
if self.timer > 3 then self.blinkstatus = not self.blinkstatus
local pos = vector.round(self.object:getpos()) end
do_tnt_physics(pos, 3, self) -- hurt player/mobs in blast area if self.timer > 3 then
if minetest.find_node_near(pos, 1, {"group:water"}) local pos = vector.round(self.object:getpos())
or minetest.is_protected(pos, "") then entity_physics(pos, 3) -- hurt player/mobs caught in blast area
if minetest.find_node_near(pos, 1, {"group:water"})
or minetest.is_protected(pos, "") then
self.object:remove() self.object:remove()
if self.sounds.explode ~= "" then if self.sounds.explode ~= "" then
minetest.sound_play(self.sounds.explode, {pos = pos, gain = 1.0, max_hear_distance = 16}) minetest.sound_play(self.sounds.explode, {pos = pos, gain = 1.0, max_hear_distance = 16})
@ -653,10 +668,18 @@ function mobs:register_mob(name, def)
return return
end end
self.object:remove() self.object:remove()
mobs:explosion(pos, 2, 1, 1, "tnt_explode", self.sounds.explode) if self.sounds.explode ~= "" then
minetest.sound_play(self.sounds.explode, {pos = pos, gain = 1.0, max_hear_distance = 16})
end
pos.y = pos.y + 1
effect(pos, 15, "tnt_smoke.png", 5)
return
end end
self.object:remove()
mobs:explosion(pos, 2, 0, 1, "tnt_explode", self.sounds.explode)
end
end end
-- Modif MFF "attack type kamicaze" des creepers /FIN -- end of exploding mobs
elseif self.state == "attack" and self.attack_type == "dogfight" then elseif self.state == "attack" and self.attack_type == "dogfight" then
@ -685,7 +708,8 @@ function mobs:register_mob(name, def)
yaw = yaw+math.pi yaw = yaw+math.pi
end end
self.object:setyaw(yaw) self.object:setyaw(yaw)
if self.attack.dist > 3 then -- was set to 2 but slimes didnt hurt when above player -- attack distance is 2 + half of mob width so the bigger mobs can attack (like slimes)
if self.attack.dist > ((-self.collisionbox[1]+self.collisionbox[4])/2)+2 then
-- jump attack -- jump attack
if (self.jump and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0) if (self.jump and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0)
or (self.object:getvelocity().y == 0 and self.jump_chance > 0) then or (self.object:getvelocity().y == 0 and self.jump_chance > 0) then
@ -968,7 +992,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
-- spawn mob half block higher -- spawn mob half block higher
pos.y = pos.y - 0.5 pos.y = pos.y - 0.5
minetest.add_entity(pos, name) minetest.add_entity(pos, name)
--print ("Spawned "..name.." at "..minetest.pos_to_string(pos)) --print ("Spawned "..name.." at "..minetest.pos_to_string(pos).." on "..node.name.." near "..neighbors[1])
end end
}) })
@ -980,7 +1004,7 @@ function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_o
end end
-- particle effects -- particle effects
function effect(pos, amount, texture) function effect(pos, amount, texture, max_size)
minetest.add_particlespawner({ minetest.add_particlespawner({
amount = amount, amount = amount,
time = 0.25, time = 0.25,
@ -993,7 +1017,7 @@ function effect(pos, amount, texture)
minexptime = 0.1, minexptime = 0.1,
maxexptime = 1, maxexptime = 1,
minsize = 0.5, minsize = 0.5,
maxsize = 1, maxsize = (max_size or 1),
texture = texture, texture = texture,
}) })
end end
@ -1010,7 +1034,7 @@ function mobs:explosion(pos, radius, fire, smoke, sound)
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
local data = vm:get_data() local data = vm:get_data()
local p = {} local p = {}
local undestroyed = { local undestroyed = { --Modif MFF DEBUT
minetest.get_content_id("air"), minetest.get_content_id("air"),
minetest.get_content_id("ignore"), minetest.get_content_id("ignore"),
minetest.get_content_id("default:obsidian"), minetest.get_content_id("default:obsidian"),
@ -1027,8 +1051,15 @@ function mobs:explosion(pos, radius, fire, smoke, sound)
minetest.get_content_id("more_chests:secret"), minetest.get_content_id("more_chests:secret"),
minetest.get_content_id("more_chests:dropbox"), minetest.get_content_id("more_chests:dropbox"),
minetest.get_content_id("more_chests:shared_chest") minetest.get_content_id("more_chests:shared_chest")
} } --Modif MFF DEBUT
if sound and sound ~= "" then minetest.sound_play(sound, {pos = pos, gain = 1.0, max_hear_distance = 16}) end local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
local c_obsidian = minetest.get_content_id("default:obsidian")
local c_brick = minetest.get_content_id("default:obsidianbrick")
local c_chest = minetest.get_content_id("default:chest_locked")
if sound and sound ~= "" then
minetest.sound_play(sound, {pos = pos, gain = 1.0, max_hear_distance = 16})
end
for z = -radius, radius do for z = -radius, radius do
for y = -radius, radius do for y = -radius, radius do
local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z) local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z)
@ -1036,28 +1067,22 @@ function mobs:explosion(pos, radius, fire, smoke, sound)
p.x = pos.x + x p.x = pos.x + x
p.y = pos.y + y p.y = pos.y + y
p.z = pos.z + z p.z = pos.z + z
local is_destroyed = true if data[vi] ~= c_air and data[vi] ~= c_ignore and data[vi] ~= c_obsidian and data[vi] ~= c_brick and data[vi] ~= c_chest then
for _,value in pairs(undestroyed) do
if data[vi] == value then
is_destroyed = false
end
end
if is_destroyed then
local n = minetest.get_node(p).name local n = minetest.get_node(p).name
-- do NOT destroy protection nodes but DO destroy nodes in protected area -- do NOT destroy protection nodes but DO destroy nodes in protected area
if not n:find("protector:") if not n:find("protector:")
--and not minetest.is_protected(p, "") --and not minetest.is_protected(p, "")
and minetest.get_item_group(n, "unbreakable") == 0 and minetest.get_item_group(n.name, "unbreakable") ~= 1 then
and next(areas:getAreasAtPos(p)) == nil then -- if chest then drop items inside
-- if chest then drop items inside if n == "default:chest" then
if n == "default:chest" then local meta = minetest.get_meta(p)
local meta = minetest.get_meta(p) local inv = meta:get_inventory()
local inv = meta:get_inventory() for i = 1,32 do
for i = 1,32 do local m_stack = inv:get_stack("main",i)
local m_stack = inv:get_stack("main",i) local obj = minetest.add_item(pos,m_stack)
local obj = minetest.add_item(pos,m_stack) if obj then
if obj then obj:setvelocity({x=math.random(-2,2), y=7, z=math.random(-2,2)})
obj:setvelocity({x=math.random(-2,2), y=7, z=math.random(-2,2)}) end
end end
end end
end end
@ -1066,12 +1091,14 @@ function mobs:explosion(pos, radius, fire, smoke, sound)
elseif n.name == "doors:door_wood_t_1" then elseif n.name == "doors:door_wood_t_1" then
minetest.remove_node({x=np.x,y=np.y-1,z=np.z}) minetest.remove_node({x=np.x,y=np.y-1,z=np.z})
end end
if fire > 0 and (minetest.registered_nodes[n].groups.flammable or math.random(1, 100) <= 30) then if fire > 0 and (minetest.registered_nodes[n].groups.flammable or math.random(1, 100) <= 30) then
minetest.set_node(p, {name="fire:basic_flame"}) minetest.set_node(p, {name="fire:basic_flame"})
else else
minetest.remove_node(p) minetest.remove_node(p)
end end
if smoke > 0 then effect(p, 1, "tnt_smoke.png") end if smoke > 0 then
effect(p, 2, "tnt_smoke.png", 5)
end
end end
end end
vi = vi + 1 vi = vi + 1
@ -1111,28 +1138,37 @@ function check_for_death(self)
end end
end end
-- Modif MFF "fonction TNT" des creepers /DEBUT -- from TNT mod
function do_tnt_physics(tnt_np,tntr,entity) function calc_velocity(pos1, pos2, old_vel, power)
local objs = minetest.get_objects_inside_radius(tnt_np, tntr) local vel = vector.direction(pos1, pos2)
for k, obj in pairs(objs) do vel = vector.normalize(vel)
local oname = obj:get_entity_name() vel = vector.multiply(vel, power)
local v = obj:getvelocity() local dist = vector.distance(pos1, pos2)
local p = obj:getpos() dist = math.max(dist, 1)
if v ~= nil then vel = vector.divide(vel, dist)
obj:setvelocity({x=(p.x - tnt_np.x) + (tntr / 4) + v.x, y=(p.y - tnt_np.y) + (tntr / 2) + v.y, z=(p.z - tnt_np.z) + (tntr / 4) + v.z}) vel = vector.add(vel, old_vel)
else return vel
if obj:get_player_name() ~= nil then
if entity.object ~= nil then
obj:punch(entity.object, 1.0, {full_punch_interval=1.0,damage_groups = {fleshy=entity.damage}})
else
obj:set_hp(obj:get_hp() - 21)
end
end
end
end
end end
-- Modif MFF "fonction TNT" des creepers /FIN
-- modified from TNT mod
function entity_physics(pos, radius)
radius = radius * 2
local objs = minetest.get_objects_inside_radius(pos, radius)
local obj_pos, obj_vel, dist
for _, obj in pairs(objs) do
obj_pos = obj:getpos()
obj_vel = obj:getvelocity()
dist = math.max(1, vector.distance(pos, obj_pos))
if obj_vel ~= nil then
obj:setvelocity(calc_velocity(pos, obj_pos,
obj_vel, radius * 10))
end
local damage = (4 / dist) * radius
obj:set_hp(obj:get_hp() - damage)
end
end
-- register arrow for shoot attack
function mobs:register_arrow(name, def) function mobs:register_arrow(name, def)
if not name or not def then return end -- errorcheck if not name or not def then return end -- errorcheck
minetest.register_entity(name, { minetest.register_entity(name, {