1
0
mirror of https://github.com/sys4-fr/server-nalc.git synced 2024-12-25 18:20:36 +01:00

update mobs mod

fix npc male/female not tamed
reduce volume and convert npc female sound
move .blend in others_thing
chmod 755
This commit is contained in:
crabman77 2015-09-30 03:43:51 +02:00
parent 4664c11f59
commit 2c47322feb
28 changed files with 1190 additions and 1211 deletions

View File

@ -28,6 +28,7 @@ This mod contains the following additions:
Changelog: Changelog:
1.17- Added 'dogshoot' attack type, shoots when out of reach, melee attack when in reach, also api tweaks and self.reach added
1.16- Mobs follow multiple items now, Npc's can breed 1.16- Mobs follow multiple items now, Npc's can breed
1.15- Added Feeding/Taming/Breeding function, right-click to pick up any sheep with X mark on them and replace with new one to fix compatibility. 1.15- Added Feeding/Taming/Breeding function, right-click to pick up any sheep with X mark on them and replace with new one to fix compatibility.
1.14- All .self variables saved in staticdata, Fixed self.health bug 1.14- All .self variables saved in staticdata, Fixed self.health bug

View File

@ -1,4 +1,4 @@
-- Mobs Api (17th September 2015) -- Mobs Api (27th September 2015)
mobs = {} mobs = {}
mobs.mod = "redo" mobs.mod = "redo"
@ -10,7 +10,8 @@ mobs.protected = tonumber(minetest.setting_get("mobs_spawn_protected")) or 1
mobs.remove = minetest.setting_getbool("remove_far_mobs") mobs.remove = minetest.setting_getbool("remove_far_mobs")
function mobs:register_mob(name, def) function mobs:register_mob(name, def)
minetest.register_entity(name, {
minetest.register_entity(name, {
stepheight = def.stepheight or 0.6, stepheight = def.stepheight or 0.6,
name = name, name = name,
fly = def.fly, fly = def.fly,
@ -34,7 +35,7 @@ function mobs:register_mob(name, def)
view_range = def.view_range or 5, view_range = def.view_range or 5,
walk_velocity = def.walk_velocity or 1, walk_velocity = def.walk_velocity or 1,
run_velocity = def.run_velocity or 2, run_velocity = def.run_velocity or 2,
damage = def.damage, damage = def.damage or 0,
light_damage = def.light_damage or 0, light_damage = def.light_damage or 0,
water_damage = def.water_damage or 0, water_damage = def.water_damage or 0,
lava_damage = def.lava_damage or 0, lava_damage = def.lava_damage or 0,
@ -49,7 +50,7 @@ function mobs:register_mob(name, def)
shoot_interval = def.shoot_interval, shoot_interval = def.shoot_interval,
sounds = def.sounds or {}, sounds = def.sounds or {},
animation = def.animation, animation = def.animation,
follow = def.follow, -- or "", follow = def.follow,
jump = def.jump or true, jump = def.jump or true,
walk_chance = def.walk_chance or 50, walk_chance = def.walk_chance or 50,
attacks_monsters = def.attacks_monsters or false, attacks_monsters = def.attacks_monsters or false,
@ -67,7 +68,7 @@ function mobs:register_mob(name, def)
replace_with = def.replace_with, replace_with = def.replace_with,
replace_offset = def.replace_offset or 0, replace_offset = def.replace_offset or 0,
timer = 0, timer = 0,
env_damage_timer = 0, -- only if state = "attack" env_damage_timer = 0, -- only used when state = "attack"
attack = {player = nil, dist = nil}, attack = {player = nil, dist = nil},
state = "stand", state = "stand",
tamed = false, tamed = false,
@ -77,8 +78,10 @@ function mobs:register_mob(name, def)
child = false, child = false,
gotten = false, gotten = false,
health = 0, health = 0,
reach = def.reach or 3,
htimer = 0,
do_attack = function(self, player, dist) do_attack = function(self, player)
if self.state ~= "attack" then if self.state ~= "attack" then
if math.random(0,100) < 90 if math.random(0,100) < 90
and self.sounds.war_cry then and self.sounds.war_cry then
@ -88,8 +91,7 @@ function mobs:register_mob(name, def)
}) })
end end
self.state = "attack" self.state = "attack"
self.attack.player = player self.attack = player
self.attack.dist = dist
end end
end, end,
@ -102,7 +104,11 @@ function mobs:register_mob(name, def)
local yaw = self.object:getyaw() + self.rotate local yaw = self.object:getyaw() + self.rotate
local x = math.sin(yaw) * -v local x = math.sin(yaw) * -v
local z = math.cos(yaw) * v local z = math.cos(yaw) * v
self.object:setvelocity({x = x, y = self.object:getvelocity().y, z = z}) self.object:setvelocity({
x = x,
y = self.object:getvelocity().y,
z = z}
)
end, end,
get_velocity = function(self) get_velocity = function(self)
@ -120,7 +126,6 @@ function mobs:register_mob(name, def)
local d = {x = vx / ds, z = vz / ds} local d = {x = vx / ds, z = vz / ds}
local p = {x = pos.x / ps, z = pos.z / ps} local p = {x = pos.x / ps, z = pos.z / ps}
local an = (d.x * p.x) + (d.z * p.z) local an = (d.x * p.x) + (d.z * p.z)
if math.deg(math.acos(an)) > (self.fov / 2) then if math.deg(math.acos(an)) > (self.fov / 2) then
return false return false
end end
@ -183,13 +188,14 @@ function mobs:register_mob(name, def)
on_step = function(self, dtime) on_step = function(self, dtime)
-- remove monsters if playing on peaceful
if (self.type == "monster" and peaceful_only) if (self.type == "monster" and peaceful_only)
or not within_limits(self.object:getpos(), 0) then or not within_limits(self.object:getpos(), 0) then
self.object:remove() self.object:remove()
return return
end end
-- if lifetimer run out and not npc; tamed or attacking then remove mob -- when lifetimer expires remove mob (except npc and tamed)
if self.type ~= "npc" if self.type ~= "npc"
and not self.tamed then and not self.tamed then
self.lifetimer = self.lifetimer - dtime self.lifetimer = self.lifetimer - dtime
@ -203,10 +209,10 @@ function mobs:register_mob(name, def)
end end
end end
-- check for mob drop/replace (used for chicken egg and sheep eating grass/wheat) -- node replace check (chicken lays egg, cow eats grass etc)
if self.replace_rate if self.replace_rate
and self.child == false and self.child == false
and math.random(1,self.replace_rate) == 1 then and math.random(1, self.replace_rate) == 1 then
local pos = self.object:getpos() local pos = self.object:getpos()
local nodeunder = minetest.get_node_or_nil({x=pos.x, y=pos.y-1, z=pos.z}) --MFF (Mg egg not in air) local nodeunder = minetest.get_node_or_nil({x=pos.x, y=pos.y-1, z=pos.z}) --MFF (Mg egg not in air)
pos.y = pos.y + self.replace_offset pos.y = pos.y + self.replace_offset
@ -215,7 +221,6 @@ function mobs:register_mob(name, def)
and self.object:getvelocity().y == 0 and self.object:getvelocity().y == 0
and #minetest.find_nodes_in_area(pos, pos, self.replace_what) > 0 --then and #minetest.find_nodes_in_area(pos, pos, self.replace_what) > 0 --then
and nodeunder and nodeunder.name ~= "air" then --MFF (Mg egg not in air) and nodeunder and nodeunder.name ~= "air" then --MFF (Mg egg not in air)
--and self.state == "stand" then
minetest.set_node(pos, {name = self.replace_with}) minetest.set_node(pos, {name = self.replace_with})
end end
end end
@ -225,14 +230,9 @@ function mobs:register_mob(name, def)
if not self.fly then if not self.fly then
-- floating in water (or falling) -- floating in water (or falling)
local pos = self.object:getpos() local pos = self.object:getpos()
local nod = minetest.get_node_or_nil(pos)
if nod then nod = nod.name else nod = "default:dirt" end
local nodef = minetest.registered_nodes[nod]
if not nodef then
nodef = {groups = {}}
end
local v = self.object:getvelocity() local v = self.object:getvelocity()
-- going up then apply gravity
if v.y > 0.1 then if v.y > 0.1 then
self.object:setacceleration({ self.object:setacceleration({
x = 0, x = 0,
@ -240,7 +240,9 @@ function mobs:register_mob(name, def)
z = 0 z = 0
}) })
end end
if nodef.groups.water then
-- in water then float up
if minetest.registered_nodes[node_ok(pos).name].groups.water then
if self.floats == 1 then if self.floats == 1 then
self.object:setacceleration({ self.object:setacceleration({
x = 0, x = 0,
@ -249,6 +251,7 @@ function mobs:register_mob(name, def)
}) })
end end
else else
-- fall downwards
self.object:setacceleration({ self.object:setacceleration({
x = 0, x = 0,
y = self.fall_speed, y = self.fall_speed,
@ -287,6 +290,7 @@ function mobs:register_mob(name, def)
self.timer = 0 self.timer = 0
end end
-- mob plays random sound at times
if self.sounds.random if self.sounds.random
and math.random(1, 100) <= 1 then and math.random(1, 100) <= 1 then
minetest.sound_play(self.sounds.random, { minetest.sound_play(self.sounds.random, {
@ -296,7 +300,9 @@ function mobs:register_mob(name, def)
end end
local do_env_damage = function(self) local do_env_damage = function(self)
if self.htimer > 0 then
self.htimer = self.htimer - 1
end
local pos = self.object:getpos() local pos = self.object:getpos()
local tod = minetest.get_timeofday() local tod = minetest.get_timeofday()
@ -311,9 +317,9 @@ function mobs:register_mob(name, def)
if check_for_death(self) then return end if check_for_death(self) then return end
end end
if self.water_damage ~= 0 or self.lava_damage ~= 0 then
pos.y = pos.y + self.collisionbox[2] -- foot level pos.y = pos.y + self.collisionbox[2] -- foot level
local nod = minetest.get_node_or_nil(pos) local nod = node_ok(pos, "air") -- print ("standing in "..nod.name)
if not nod then return end ; -- print ("standing in "..nod.name)
local nodef = minetest.registered_nodes[nod.name] local nodef = minetest.registered_nodes[nod.name]
if not nodef then return end if not nodef then return end
pos.y = pos.y + 1 pos.y = pos.y + 1
@ -330,12 +336,13 @@ function mobs:register_mob(name, def)
if self.lava_damage ~= 0 if self.lava_damage ~= 0
and (nodef.groups.lava and (nodef.groups.lava
or nod.name == "fire:basic_flame" or nod.name == "fire:basic_flame"
or nod.name == "xanadu:safe_fire") then or nod.name == "xanadu:safe_fire"
or nod.name == "fire:eternal_flame") then
self.object:set_hp(self.object:get_hp() - self.lava_damage) self.object:set_hp(self.object:get_hp() - self.lava_damage)
effect(pos, 5, "fire_basic_flame.png") effect(pos, 5, "fire_basic_flame.png")
if check_for_death(self) then return end if check_for_death(self) then return end
end end
end
end end
local do_jump = function(self) local do_jump = function(self)
@ -343,32 +350,24 @@ function mobs:register_mob(name, def)
return return
end end
self.jumptimer = (self.jumptimer or 0) + 1
if self.jumptimer < 3 then
local pos = self.object:getpos() local pos = self.object:getpos()
pos.y = (pos.y + self.collisionbox[2]) - 0.2 pos.y = (pos.y + self.collisionbox[2]) - 0.2
local nod = minetest.get_node_or_nil(pos) local nod = node_ok(pos)
--print ("standing on:", nod.name, pos.y) --print ("standing on:", nod.name, pos.y)
if not nod if minetest.registered_nodes[nod.name].walkable == false then
or not minetest.registered_nodes[nod.name]
or minetest.registered_nodes[nod.name].walkable == false then
return return
end end
if self.direction then if self.direction then
pos.y = pos.y + 0.5 pos.y = pos.y + 0.5
local nod = minetest.get_node_or_nil({ local nod = node_ok({
x = pos.x + self.direction.x, x = pos.x + self.direction.x,
y = pos.y, y = pos.y,
z = pos.z + self.direction.z z = pos.z + self.direction.z
}) })
--print ("in front:", nod.name, pos.y) --print ("in front:", nod.name, pos.y)
if nod and nod.name and if nod.name ~= "air"
(nod.name ~= "air" and minetest.registered_items[nod.name].walkable
or self.walk_chance == 0) then and not nod.name:find("fence")
local def = minetest.registered_items[nod.name]
if (def
and def.walkable
and not nod.name:find("fence"))
or self.walk_chance == 0 then or self.walk_chance == 0 then
local v = self.object:getvelocity() local v = self.object:getvelocity()
v.y = self.jump_height + 1 v.y = self.jump_height + 1
@ -384,10 +383,6 @@ function mobs:register_mob(name, def)
end end
end end
end end
else
self.jumptimer = 0
end
end
-- environmental damage timer (every 1 second) -- environmental damage timer (every 1 second)
self.env_damage_timer = self.env_damage_timer + dtime self.env_damage_timer = self.env_damage_timer + dtime
@ -454,7 +449,7 @@ function mobs:register_mob(name, def)
end end
-- attack player -- attack player
if min_player then if min_player then
self.do_attack(self, min_player, min_dist) self.do_attack(self, min_player)
end end
end end
@ -482,11 +477,12 @@ function mobs:register_mob(name, def)
end end
end end
if min_player then if min_player then
self.do_attack(self, min_player, min_dist) self.do_attack(self, min_player)
end 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
if self.horny == true if self.horny == true
and self.hornytimer < 240 and self.hornytimer < 240
and self.child == false then and self.child == false then
@ -497,7 +493,7 @@ function mobs:register_mob(name, def)
end end
end end
-- if animal is child take 240 seconds before growing into adult -- child take 240 seconds before growing into adult
if self.child == true then if self.child == true then
self.hornytimer = self.hornytimer + 1 self.hornytimer = self.hornytimer + 1
if self.hornytimer > 240 then if self.hornytimer > 240 then
@ -509,7 +505,7 @@ function mobs:register_mob(name, def)
visual_size = self.base_size, visual_size = self.base_size,
collisionbox = self.base_colbox, collisionbox = self.base_colbox,
}) })
-- jump when grown to now fall into ground -- jump when grown so not to fall into ground
local v = self.object:getvelocity() local v = self.object:getvelocity()
v.y = self.jump_height v.y = self.jump_height
v.x = 0 ; v.z = 0 v.x = 0 ; v.z = 0
@ -517,7 +513,7 @@ function mobs:register_mob(name, def)
end end
end end
-- if animal is horny, find another same animal who is horny and mate -- find another same animal who is also horny and mate
if self.horny == true if self.horny == true
and self.hornytimer <= 40 then and self.hornytimer <= 40 then
local pos = self.object:getpos() local pos = self.object:getpos()
@ -552,6 +548,8 @@ function mobs:register_mob(name, def)
and ent.hornytimer <= 40 then and ent.hornytimer <= 40 then
num = num + 1 num = num + 1
end end
-- found your mate? then have a baby
if num > 1 then if num > 1 then
self.hornytimer = 41 self.hornytimer = 41
ent.hornytimer = 41 ent.hornytimer = 41
@ -618,13 +616,12 @@ function mobs:register_mob(name, def)
-- stop following player if not holding specific item -- stop following player if not holding specific item
if self.following if self.following
and self.following.is_player and self.following.is_player
--and self.following:get_wielded_item():get_name() ~= self.follow then
and follow_holding(self, self.following) == false then and follow_holding(self, self.following) == false then
self.following = nil self.following = nil
end end
end end
-- follow player or mob -- follow that thing
if self.following then if self.following then
local s = self.object:getpos() local s = self.object:getpos()
local p local p
@ -638,6 +635,8 @@ function mobs:register_mob(name, def)
if p then if p then
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
-- dont follow if out of range
if dist > self.view_range then if dist > self.view_range then
self.following = nil self.following = nil
else else
@ -649,7 +648,7 @@ function mobs:register_mob(name, def)
self.object:setyaw(yaw) self.object:setyaw(yaw)
-- anyone but standing npc's can move along -- anyone but standing npc's can move along
if dist > 4 --/MFF (Crabman|07/14/2015) follow but at distance, default value is 2 if dist > self.reach
and self.order ~= "stand" then and self.order ~= "stand" then
if (self.jump if (self.jump
and self.get_velocity(self) <= 0.5 and self.get_velocity(self) <= 0.5
@ -658,7 +657,7 @@ function mobs:register_mob(name, def)
and self.jump_chance > 0) then and self.jump_chance > 0) then
self.direction = { self.direction = {
x = math.sin(yaw) * -1, x = math.sin(yaw) * -1,
y = -20, y = 0,
z = math.cos(yaw) z = math.cos(yaw)
} }
do_jump(self) do_jump(self)
@ -677,15 +676,13 @@ function mobs:register_mob(name, def)
end end
if self.state == "stand" then if self.state == "stand" then
-- randomly turn
if math.random(1, 4) == 1 then if math.random(1, 4) == 1 then
-- if there is a player nearby look at them
local lp = nil local lp = nil
local s = self.object:getpos() local s = self.object:getpos()
if self.type == "npc" then if self.type == "npc" then
local o = minetest.get_objects_inside_radius(self.object:getpos(), 3) local o = minetest.get_objects_inside_radius(self.object:getpos(), 3)
local yaw = 0 local yaw = 0
for _,o in ipairs(o) do for _,o in ipairs(o) do
if o:is_player() then if o:is_player() then
@ -695,6 +692,7 @@ function mobs:register_mob(name, def)
end end
end end
-- look at any players nearby, otherwise turn randomly
if lp ~= nil then if lp ~= nil then
local vec = {x = lp.x - s.x, y = lp.y - s.y, z = lp.z - s.z} local vec = {x = lp.x - s.x, y = lp.y - s.y, z = lp.z - s.z}
yaw = (math.atan(vec.z / vec.x) + math.pi / 2) - self.rotate yaw = (math.atan(vec.z / vec.x) + math.pi / 2) - self.rotate
@ -723,29 +721,24 @@ function mobs:register_mob(name, def)
self.state = "walk" self.state = "walk"
self.set_animation(self, "walk") self.set_animation(self, "walk")
end end
-- jumping mobs only
-- if self.jump and math.random(1, 100) <= self.jump_chance then
-- self.direction = {x = 0, y = 0, z = 0}
-- do_jump(self)
-- self.set_velocity(self, self.walk_velocity)
-- end
end end
elseif self.state == "walk" then elseif self.state == "walk" then
local s = self.object:getpos() local s = self.object:getpos()
local lp = minetest.find_node_near(s, 1, {"group:water"}) local lp = minetest.find_node_near(s, 1, {"group:water"})
-- water swimmers cannot move out of water -- water swimmers cannot move out of water
if self.fly if self.fly
and self.fly_in == "default:water_source" and self.fly_in == "default:water_source"
and not lp then and not lp then
print ("out of water") print ("out of water")
self.set_velocity(self, 0) self.set_velocity(self, 0)
self.state = "flop" -- change to undefined state so nothing more happens -- change to undefined state so nothing more happens
self.state = "flop"
self:set_animation("stand") self:set_animation("stand")
return return
end end
-- if water nearby then turn away -- if water nearby then turn away
if lp then if lp then
local vec = {x = lp.x - s.x, y = lp.y - s.y, z = lp.z - s.z} local vec = {x = lp.x - s.x, y = lp.y - s.y, z = lp.z - s.z}
@ -754,16 +747,17 @@ end
yaw = yaw + math.pi yaw = yaw + math.pi
end end
self.object:setyaw(yaw) self.object:setyaw(yaw)
-- otherwise randomly turn -- otherwise randomly turn
elseif math.random(1, 100) <= 30 then elseif math.random(1, 100) <= 30 then
self.object:setyaw(self.object:getyaw() + ((math.random(0, 360) - 180) / 180 * math.pi)) self.object:setyaw(self.object:getyaw() + ((math.random(0, 360) - 180) / 180 * math.pi))
end end
-- jump when walking comes to a halt
if self.jump and self.get_velocity(self) <= 0.5 if self.jump and self.get_velocity(self) <= 0.5
and self.object:getvelocity().y == 0 then and self.object:getvelocity().y == 0 then
self.direction = { self.direction = {
x = math.sin(yaw) * -1, x = math.sin(yaw) * -1,
y = -20, y = 0,
z = math.cos(yaw) z = math.cos(yaw)
} }
do_jump(self) do_jump(self)
@ -777,40 +771,40 @@ end
self:set_animation("stand") self:set_animation("stand")
end end
-- exploding mobs -- attack routines (explode, dogfight, shoot, dogshoot)
elseif self.state == "attack" and self.attack_type == "explode" then elseif self.state == "attack" then
if not self.attack.player
or not self.attack.player:is_player() then -- calculate distance from mob and enemy
self.state = "stand"
self:set_animation("stand")
self.timer = 0
self.blinktimer = 0
return
end
local s = self.object:getpos() local s = self.object:getpos()
local p = self.attack.player:getpos() local p = self.attack:getpos() or s
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 or self.attack.player:get_hp() <= 0 then
-- stop attacking if no player or out of range
if dist > self.view_range
or not self.attack
or not self.attack:getpos()
or self.attack:get_hp() <= 0 then
--print(" ** stop attacking **", dist, self.view_range)
self.state = "stand" self.state = "stand"
self.v_start = false
self.set_velocity(self, 0) self.set_velocity(self, 0)
self:set_animation("stand")
self.attack = nil
self.v_start = false
self.timer = 0 self.timer = 0
self.blinktimer = 0 self.blinktimer = 0
self.attack = {player = nil, dist = nil}
self:set_animation("stand")
return return
else
self:set_animation("walk")
self.attack.dist = dist
end end
if self.attack_type == "explode" then
local vec = {x = p.x - s.x, y = p.y - s.y, z = p.z - s.z} local vec = {x = p.x - s.x, y = p.y - s.y, z = p.z - s.z}
yaw = math.atan(vec.z / vec.x) + math.pi / 2 - self.rotate yaw = math.atan(vec.z / vec.x) + math.pi / 2 - self.rotate
if p.x > s.x then if p.x > s.x then
yaw = yaw + math.pi yaw = yaw + math.pi
end end
self.object:setyaw(yaw) self.object:setyaw(yaw)
if self.attack.dist > 3 then
if dist > self.reach then
if not self.v_start then if not self.v_start then
self.v_start = true self.v_start = true
self.set_velocity(self, self.run_velocity) self.set_velocity(self, self.run_velocity)
@ -843,6 +837,7 @@ end
end end
if self.timer > 3 then if self.timer > 3 then
local pos = vector.round(self.object:getpos()) local pos = vector.round(self.object:getpos())
-- hurt player/mobs caught in blast area
entity_physics(pos, 3, self) -- hurt player/mobs caught in blast area --/MFF (Crabman|06/23/2015)add self to use punch function entity_physics(pos, 3, self) -- hurt player/mobs caught in blast area --/MFF (Crabman|06/23/2015)add self to use punch function
if minetest.find_node_near(pos, 1, {"group:water"}) if minetest.find_node_near(pos, 1, {"group:water"})
or minetest.is_protected(pos, "") then or minetest.is_protected(pos, "") then
@ -862,26 +857,15 @@ end
mobs:explosion(pos, 2, 0, 1, self.sounds.explode) mobs:explosion(pos, 2, 0, 1, self.sounds.explode)
end end
end end
-- end of exploding mobs
elseif self.state == "attack" elseif self.attack_type == "dogfight"
and self.attack_type == "dogfight" then or (self.attack_type == "dogshoot" and dist <= self.reach) then
if not self.attack.player
or not self.attack.player:getpos() then
print("stop attacking")
self.state = "stand"
self:set_animation("stand")
return
end
local s = self.object:getpos()
local p = self.attack.player:getpos()
local dist = ((p.x - s.x) ^ 2 + (p.y - s.y) ^ 2 + (p.z - s.z) ^ 2) ^ 0.5
-- fly bit modified from BlockMens creatures mod -- fly bit modified from BlockMens creatures mod
if self.fly if self.fly
and dist > 2 then and dist > self.reach then
local nod = minetest.get_node_or_nil(s) local nod = node_ok(s)
local p1 = s local p1 = s
local me_y = math.floor(p1.y) local me_y = math.floor(p1.y)
local p2 = p local p2 = p
@ -921,16 +905,6 @@ end
end end
-- end fly bit -- end fly bit
if dist > self.view_range
or self.attack.player:get_hp() <= 0 then
self.state = "stand"
self.set_velocity(self, 0)
self.attack = {player = nil, dist = nil}
self:set_animation("stand")
return
else
self.attack.dist = dist
end
local vec = {x = p.x - s.x, y = p.y - s.y, z = p.z - s.z} local vec = {x = p.x - s.x, y = p.y - s.y, z = p.z - s.z}
yaw = (math.atan(vec.z / vec.x) + math.pi / 2) - self.rotate yaw = (math.atan(vec.z / vec.x) + math.pi / 2) - self.rotate
@ -938,8 +912,11 @@ end
yaw = yaw + math.pi yaw = yaw + math.pi
end end
self.object:setyaw(yaw) self.object:setyaw(yaw)
-- 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 -- move towards enemy if beyond mob reach
-- set reach for each mob (default is 3)
if dist > self.reach then
-- jump attack -- jump attack
if (self.jump if (self.jump
and self.get_velocity(self) <= 0.5 and self.get_velocity(self) <= 0.5
@ -948,7 +925,7 @@ end
and self.jump_chance > 0) then and self.jump_chance > 0) then
self.direction = { self.direction = {
x = math.sin(yaw) * -1, x = math.sin(yaw) * -1,
y = -20, y = 0,
z = math.cos(yaw) z = math.cos(yaw)
} }
do_jump(self) do_jump(self)
@ -965,45 +942,28 @@ end
p2.y = p2.y + 1.5 p2.y = p2.y + 1.5
s2.y = s2.y + 1.5 s2.y = s2.y + 1.5
if minetest.line_of_sight(p2, s2) == true then if minetest.line_of_sight(p2, s2) == true then
-- play attack sound
if self.sounds.attack then if self.sounds.attack then
minetest.sound_play(self.sounds.attack, { minetest.sound_play(self.sounds.attack, {
object = self.object, object = self.object,
max_hear_distance = self.sounds.distance max_hear_distance = self.sounds.distance
}) })
end end
self.attack.player:punch(self.object, 1.0, { -- punch player
self.attack:punch(self.object, 1.0, {
full_punch_interval=1.0, full_punch_interval=1.0,
damage_groups = {fleshy=self.damage} damage_groups = {fleshy=self.damage}
}, vec) }, nil)
if self.attack.player:get_hp() <= 0 then
self.state = "stand"
self:set_animation("stand")
end
end end
end end
end end
elseif self.state == "attack" elseif self.attack_type == "shoot"
and self.attack_type == "shoot" then or (self.attack_type == "dogshoot" and dist > self.reach) then
local s = self.object:getpos()
local p = self.attack.player:getpos()
if not p then
self.state = "stand"
return
end
p.y = p.y - .5 p.y = p.y - .5
s.y = s.y + .5 s.y = s.y + .5
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
or self.attack.player:get_hp() <= 0 then
self.state = "stand"
self.set_velocity(self, 0)
self:set_animation("stand")
return
else
self.attack.dist = dist
end
local vec = {x = p.x - s.x, y = p.y - s.y, z = p.z - s.z} local vec = {x = p.x - s.x, y = p.y - s.y, z = p.z - s.z}
yaw = (math.atan(vec.z / vec.x) + math.pi / 2) - self.rotate yaw = (math.atan(vec.z / vec.x) + math.pi / 2) - self.rotate
@ -1017,11 +977,11 @@ end
and self.timer > self.shoot_interval and self.timer > self.shoot_interval
and math.random(1, 100) <= 60 then and math.random(1, 100) <= 60 then
self.timer = 0 self.timer = 0
self:set_animation("punch") self:set_animation("punch")
if self.sounds.attack then -- play shoot attack sound
minetest.sound_play(self.sounds.attack, { if self.sounds.shoot_attack then
minetest.sound_play(self.sounds.shoot_attack, {
object = self.object, object = self.object,
max_hear_distance = self.sounds.distance max_hear_distance = self.sounds.distance
}) })
@ -1032,13 +992,16 @@ end
local obj = minetest.add_entity(p, self.arrow) local obj = minetest.add_entity(p, self.arrow)
local amount = (vec.x ^ 2 + vec.y ^ 2 + vec.z ^ 2) ^ 0.5 local amount = (vec.x ^ 2 + vec.y ^ 2 + vec.z ^ 2) ^ 0.5
local v = obj:get_luaentity().velocity local v = obj:get_luaentity().velocity
vec.y = vec.y + self.shoot_offset -- this makes shoot aim accurate -- offset makes shoot aim accurate
vec.y = vec.y + self.shoot_offset
vec.x = vec.x *v / amount vec.x = vec.x *v / amount
vec.y = vec.y *v / amount vec.y = vec.y *v / amount
vec.z = vec.z *v / amount vec.z = vec.z *v / amount
obj:setvelocity(vec) obj:setvelocity(vec)
end end
end end
end -- END if self.state == "attack"
end, end,
on_activate = function(self, staticdata, dtime_s) on_activate = function(self, staticdata, dtime_s)
@ -1082,7 +1045,7 @@ end
mesh = def.gotten_mesh mesh = def.gotten_mesh
end end
-- if object is child then set half size -- set child objects to half size
if self.child == true then if self.child == true then
vis_size = { vis_size = {
x = self.base_size.x / 2, x = self.base_size.x / 2,
@ -1105,10 +1068,9 @@ end
self.health = math.random (self.hp_min, self.hp_max) self.health = math.random (self.hp_min, self.hp_max)
end end
self.object:set_hp( self.health ) self.object:set_hp(self.health)
self.object:set_armor_groups({fleshy = self.armor}) self.object:set_armor_groups({fleshy = self.armor})
self.state = "stand" self.state = "stand"
--self.order = "stand"
self.following = nil self.following = nil
self.old_y = self.object:getpos().y self.old_y = self.object:getpos().y
self.object:setyaw(math.random(1, 360) / 180 * math.pi) self.object:setyaw(math.random(1, 360) / 180 * math.pi)
@ -1119,7 +1081,6 @@ end
self.visual_size = vis_size self.visual_size = vis_size
-- set anything changed above -- set anything changed above
self.object:set_properties(self) self.object:set_properties(self)
end, end,
get_staticdata = function(self) get_staticdata = function(self)
@ -1132,6 +1093,7 @@ end
self.remove_ok = true self.remove_ok = true
self.attack = nil self.attack = nil
self.following = nil self.following = nil
self.state = "stand"
local tmp = {} local tmp = {}
for _,stat in pairs(self) do for _,stat in pairs(self) do
@ -1203,7 +1165,7 @@ end
if self.passive == false if self.passive == false
and not self.tamed then and not self.tamed then
if self.state ~= "attack" then if self.state ~= "attack" then
self.do_attack(self, hitter, 1) self.do_attack(self, hitter)
end end
-- alert others to the attack -- alert others to the attack
local obj = nil local obj = nil
@ -1213,18 +1175,19 @@ end
if obj.group_attack == true if obj.group_attack == true
and not obj.tamed --MFF(crabman) group tamed don't attack and not obj.tamed --MFF(crabman) group tamed don't attack
and obj.state ~= "attack" then and obj.state ~= "attack" then
obj.do_attack(obj, hitter, 1) obj.do_attack(obj, hitter)
end end
end end
end end
end end
end, end,
}) })
end
end -- END mobs:register_mob function
mobs.spawning_mobs = {} mobs.spawning_mobs = {}
function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval, chance, active_object_count, min_height, max_height, spawn_in_area) function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval, chance, active_object_count, min_height, max_height, spawn_in_area) --MFF crabman
mobs.spawning_mobs[name] = true mobs.spawning_mobs[name] = true
minetest.register_abm({ minetest.register_abm({
nodenames = nodes, nodenames = nodes,
@ -1245,7 +1208,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
-- mobs cannot spawn inside protected areas if enabled -- mobs cannot spawn inside protected areas if enabled
if mobs.protected == 1 if mobs.protected == 1
and minetest.is_protected(pos, "") and minetest.is_protected(pos, "")
and not spawn_in_area then and not spawn_in_area then --MFF crabman
return return
end end
@ -1260,21 +1223,11 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
end end
-- are we spawning inside a solid node? -- are we spawning inside a solid node?
local nod = minetest.get_node_or_nil(pos) if minetest.registered_nodes[node_ok(pos).name].walkable == true then
if not nod
or not nod.name
or not minetest.registered_nodes[nod.name]
or minetest.registered_nodes[nod.name].walkable == true then
return return
end end
pos.y = pos.y + 1 pos.y = pos.y + 1
if minetest.registered_nodes[node_ok(pos).name].walkable == true then
nod = minetest.get_node_or_nil(pos)
if not nod
or not nod.name
or not minetest.registered_nodes[nod.name]
or minetest.registered_nodes[nod.name].walkable == true then
return return
end end
@ -1357,7 +1310,8 @@ function mobs:explosion(pos, radius, fire, smoke, sound)
and data[vi] ~= c_obsidian and data[vi] ~= c_obsidian
and data[vi] ~= c_brick and data[vi] ~= c_brick
and data[vi] ~= c_chest then and data[vi] ~= c_chest then
local n = minetest.get_node(p).name local n = node_ok(p).name
if not minetest.is_protected(p, "") --/MFF (Crabman|06/23/2015) re-added node protected in areas if not minetest.is_protected(p, "") --/MFF (Crabman|06/23/2015) re-added node protected in areas
and minetest.get_item_group(n, "unbreakable") ~= 1 then and minetest.get_item_group(n, "unbreakable") ~= 1 then
-- if chest then drop items inside -- if chest then drop items inside
@ -1372,7 +1326,8 @@ function mobs:explosion(pos, radius, fire, smoke, sound)
obj:setvelocity({ obj:setvelocity({
x = math.random(-2, 2), x = math.random(-2, 2),
y = 7, y = 7,
z = math.random(-2, 2)}) z = math.random(-2, 2)
})
end end
end end
end end
@ -1408,7 +1363,6 @@ function check_for_death(self)
return false return false
end end
local pos = self.object:getpos() local pos = self.object:getpos()
pos.y = pos.y + 0.5 -- drop items half a block higher
self.object:remove() self.object:remove()
local obj = nil local obj = nil
for _,drop in ipairs(self.drops) do for _,drop in ipairs(self.drops) do
@ -1490,13 +1444,9 @@ function mobs:register_arrow(name, def)
return return
end end
local engage = 10 - (self.velocity / 2) -- clear entity before arrow becomes active if self.hit_node then
local node = minetest.get_node_or_nil(pos) local node = node_ok(pos).name
if node then node = node.name else node = "air" end if minetest.registered_nodes[node].walkable then
if self.hit_node
and minetest.registered_nodes[node]
and minetest.registered_nodes[node].walkable then
self.hit_node(self, pos, node) self.hit_node(self, pos, node)
if self.drop == true then if self.drop == true then
pos.y = pos.y + 1 pos.y = pos.y + 1
@ -1506,9 +1456,11 @@ function mobs:register_arrow(name, def)
self.object:remove() ; -- print ("hit node") self.object:remove() ; -- print ("hit node")
return return
end end
end
if (self.hit_player or self.hit_mob) if (self.hit_player or self.hit_mob)
and self.timer > engage then -- clear entity before arrow becomes active
and self.timer > (10 - (self.velocity / 2)) then
for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.0)) do for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.0)) do
if self.hit_player if self.hit_player
and player:is_player() then and player:is_player() then
@ -1545,16 +1497,19 @@ function mobs:register_egg(mob, desc, background, addegg)
local pos = pointed_thing.above local pos = pointed_thing.above
if pos and within_limits(pos, 0) if pos and within_limits(pos, 0)
and not minetest.is_protected(pos, placer:get_player_name()) then and not minetest.is_protected(pos, placer:get_player_name()) then
pos.y = pos.y + 0.5 pos.y = pos.y + 1
local mob = minetest.add_entity(pos, mob) local mob = minetest.add_entity(pos, mob)
local ent = mob:get_luaentity() local ent = mob:get_luaentity()
if ent.type ~= "monster" then if ent.type ~= "monster" then
-- set owner -- set owner and tame
ent.owner = placer:get_player_name() ent.owner = placer:get_player_name()
ent.tamed = true ent.tamed = true
end end
-- if not in creative then take item
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item() itemstack:take_item()
end end
end
return itemstack return itemstack
end, end,
}) })
@ -1642,30 +1597,29 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
if not self.follow then return false end if not self.follow then return false end
local item = clicker:get_wielded_item()
-- can eat/tame with item in hand -- can eat/tame with item in hand
if follow_holding(self, clicker) then if follow_holding(self, clicker) then
-- take item -- take item
if not minetest.setting_getbool("creative_mode") then if not minetest.setting_getbool("creative_mode") then
local item = clicker:get_wielded_item()
item:take_item() item:take_item()
clicker:set_wielded_item(item) clicker:set_wielded_item(item)
end end
-- heal health -- heal health
local hp = self.object:get_hp() local hp = self.object:get_hp()
--if hp < self.hp_max then
hp = hp + 4 hp = hp + 4
if hp >= self.hp_max then if hp >= self.hp_max
and self.htimer < 1 then
hp = self.hp_max hp = self.hp_max
minetest.chat_send_player(clicker:get_player_name(), minetest.chat_send_player(clicker:get_player_name(),
self.name:split(":")[2] self.name:split(":")[2]
.. " at full health") .. " at full health (" .. tostring(hp) .. ")")
self.htimer = 5
end end
self.object:set_hp(hp) self.object:set_hp(hp)
self.health = hp self.health = hp
--end
-- make children grow quicker -- make children grow quicker
if self.child == true then if self.child == true then
@ -1715,3 +1669,15 @@ function within_limits(pos, radius)
return false -- beyond limits return false -- beyond limits
end end
function node_ok(pos, fallback)
fallback = fallback or "default:dirt"
local node = minetest.get_node_or_nil(pos)
if not node then
return minetest.registered_nodes[fallback]
end
local nodef = minetest.registered_nodes[node.name]
if nodef then
return node
end
return minetest.registered_nodes[fallback]
end

View File

@ -6,6 +6,7 @@ mobs:register_mob("mobs:bunny", {
type = "animal", type = "animal",
-- is it aggressive -- is it aggressive
passive = true, passive = true,
reach = 1,
-- health & armor -- health & armor
hp_min = 3, hp_max = 6, armor = 200, hp_min = 3, hp_max = 6, armor = 200,
-- textures and model -- textures and model
@ -62,7 +63,6 @@ mobs:register_mob("mobs:bunny", {
textures = {"mobs_bunny_evil.png"}, textures = {"mobs_bunny_evil.png"},
}) })
self.type = "monster" self.type = "monster"
self.state = "attack"
self.object:set_hp(20) self.object:set_hp(20)
return return
end end

View File

@ -8,6 +8,7 @@ mobs:register_mob("mobs:cow", {
passive = false, passive = false,
group_attack = true, group_attack = true,
attack_type = "dogfight", attack_type = "dogfight",
reach = 2,
damage = 4, damage = 4,
-- health & armor -- health & armor
hp_min = 25, hp_min = 25,

View File

@ -7,6 +7,7 @@ mobs:register_mob("mobs:dirt_monster", {
-- aggressive, deals 6 damage to player when hit -- aggressive, deals 6 damage to player when hit
passive = false, passive = false,
attack_type = "dogfight", attack_type = "dogfight",
reach = 2,
damage = 5, damage = 5,
-- health & armor -- health & armor
hp_min = 25, hp_min = 25,

View File

@ -10,7 +10,8 @@ mobs:register_mob("mobs:dungeon_master", {
-- aggressive, shoots fireballs at player, deal 13 damages -- aggressive, shoots fireballs at player, deal 13 damages
passive = false, passive = false,
damage = 12, damage = 12,
attack_type = "shoot", attack_type = "dogshoot",
reach = 3,
shoot_interval = 2.5, shoot_interval = 2.5,
arrow = "mobs:fireball", arrow = "mobs:fireball",
shoot_offset = 1, shoot_offset = 1,
@ -32,7 +33,7 @@ mobs:register_mob("mobs:dungeon_master", {
makes_footstep_sound = true, makes_footstep_sound = true,
sounds = { sounds = {
random = "mobs_dungeonmaster", random = "mobs_dungeonmaster",
attack = "mobs_fireball", shoot_attack = "mobs_fireball",
}, },
-- speed and jump -- speed and jump
walk_velocity = 1, walk_velocity = 1,

View File

@ -7,6 +7,7 @@ mobs:register_mob("mobs:lava_flan", {
-- aggressive, deals 5 damage to player when hit -- aggressive, deals 5 damage to player when hit
passive = false, passive = false,
attack_type = "dogfight", attack_type = "dogfight",
reach = 2,
damage = 5, damage = 5,
-- health and armor -- health and armor
hp_min = 20, hp_min = 20,

0
mods/mobs/models/mobs_shark.b3d Normal file → Executable file
View File

View File

@ -86,6 +86,7 @@ mobs:register_mob("mobs:npc", {
end end
if self.diamond_count >= 4 then if self.diamond_count >= 4 then
self.damages = 3 self.damages = 3
self.tamed = true
self.owner = clicker:get_player_name() self.owner = clicker:get_player_name()
end end
end end

View File

@ -90,6 +90,7 @@ mobs:register_mob("mobs:npc_female", {
end end
if self.diamond_count >= 4 then if self.diamond_count >= 4 then
self.damages = 3 self.damages = 3
self.tamed = true
self.owner = clicker:get_player_name() self.owner = clicker:get_player_name()
end end
end end

View File

@ -7,6 +7,7 @@ mobs:register_mob("mobs:oerkki", {
-- aggressive, deals 7 damage when player hit -- aggressive, deals 7 damage when player hit
passive = false, passive = false,
attack_type = "dogfight", attack_type = "dogfight",
reach = 2,
damage = 6, damage = 6,
-- health & armor -- health & armor
hp_min = 40, hp_min = 40,
@ -25,7 +26,7 @@ mobs:register_mob("mobs:oerkki", {
makes_footstep_sound = false, makes_footstep_sound = false,
sounds = { sounds = {
random = "mobs_oerkki", random = "mobs_oerkki",
attack = "mobs_oerkki_attack", shoot_attack = "mobs_oerkki_attack",
}, },
-- speed and jump -- speed and jump
walk_velocity = 2, walk_velocity = 2,

View File

@ -7,6 +7,7 @@ mobs:register_mob("mobs:sand_monster", {
-- aggressive, deals 5 damage to player when hit -- aggressive, deals 5 damage to player when hit
passive = false, passive = false,
attack_type = "dogfight", attack_type = "dogfight",
reach = 2,
damage = 4, damage = 4,
-- health & armor -- health & armor
hp_min = 15, hp_min = 15,

0
mods/mobs/shark.lua Normal file → Executable file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -7,6 +7,7 @@ mobs:register_mob("mobs:spider", {
-- agressive, does 6 damage to player when hit -- agressive, does 6 damage to player when hit
passive = false, passive = false,
attack_type = "dogfight", attack_type = "dogfight",
reach = 2,
damage = 5, damage = 5,
-- health & armor -- health & armor
hp_min = 30, hp_min = 30,

View File

@ -7,6 +7,7 @@ mobs:register_mob("mobs:stone_monster", {
-- aggressive, deals 8 damage to player when hit -- aggressive, deals 8 damage to player when hit
passive = false, passive = false,
attack_type = "dogfight", attack_type = "dogfight",
reach = 2,
damage = 7, damage = 7,
-- health & armor -- health & armor
hp_min = 20, hp_min = 20,

0
mods/mobs/textures/mobs_cow_inv.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

0
mods/mobs/textures/mobs_shark_shark_item.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

0
mods/mobs/textures/shark_first.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

0
mods/mobs/textures/shark_second.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

0
mods/mobs/textures/shark_third.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -7,6 +7,7 @@ mobs:register_mob("mobs:tree_monster", {
-- aggressive, deals 9 damage to player when hit -- aggressive, deals 9 damage to player when hit
passive = false, passive = false,
attack_type = "dogfight", attack_type = "dogfight",
reach = 2,
damage = 8, damage = 8,
-- health & armor -- health & armor
hp_min = 40, hp_min = 40,

View File

@ -8,6 +8,7 @@ mobs:register_mob("mobs:pumba", {
passive = false, passive = false,
group_attack = true, group_attack = true,
attack_type = "dogfight", attack_type = "dogfight",
reach = 2,
damage = 4, damage = 4,
-- health & armor -- health & armor
hp_min = 15, hp_min = 15,