update mobs mod
fix npc male/female not tamed reduce volume and convert npc female sound move .blend in others_thing chmod 755
@ -28,6 +28,7 @@ This mod contains the following additions:
|
||||
|
||||
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.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,4 +1,4 @@
|
||||
-- Mobs Api (17th September 2015)
|
||||
-- Mobs Api (27th September 2015)
|
||||
mobs = {}
|
||||
mobs.mod = "redo"
|
||||
|
||||
@ -10,6 +10,7 @@ mobs.protected = tonumber(minetest.setting_get("mobs_spawn_protected")) or 1
|
||||
mobs.remove = minetest.setting_getbool("remove_far_mobs")
|
||||
|
||||
function mobs:register_mob(name, def)
|
||||
|
||||
minetest.register_entity(name, {
|
||||
stepheight = def.stepheight or 0.6,
|
||||
name = name,
|
||||
@ -34,7 +35,7 @@ function mobs:register_mob(name, def)
|
||||
view_range = def.view_range or 5,
|
||||
walk_velocity = def.walk_velocity or 1,
|
||||
run_velocity = def.run_velocity or 2,
|
||||
damage = def.damage,
|
||||
damage = def.damage or 0,
|
||||
light_damage = def.light_damage or 0,
|
||||
water_damage = def.water_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,
|
||||
sounds = def.sounds or {},
|
||||
animation = def.animation,
|
||||
follow = def.follow, -- or "",
|
||||
follow = def.follow,
|
||||
jump = def.jump or true,
|
||||
walk_chance = def.walk_chance or 50,
|
||||
attacks_monsters = def.attacks_monsters or false,
|
||||
@ -67,7 +68,7 @@ function mobs:register_mob(name, def)
|
||||
replace_with = def.replace_with,
|
||||
replace_offset = def.replace_offset or 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},
|
||||
state = "stand",
|
||||
tamed = false,
|
||||
@ -77,8 +78,10 @@ function mobs:register_mob(name, def)
|
||||
child = false,
|
||||
gotten = false,
|
||||
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 math.random(0,100) < 90
|
||||
and self.sounds.war_cry then
|
||||
@ -88,8 +91,7 @@ function mobs:register_mob(name, def)
|
||||
})
|
||||
end
|
||||
self.state = "attack"
|
||||
self.attack.player = player
|
||||
self.attack.dist = dist
|
||||
self.attack = player
|
||||
end
|
||||
end,
|
||||
|
||||
@ -102,7 +104,11 @@ function mobs:register_mob(name, def)
|
||||
local yaw = self.object:getyaw() + self.rotate
|
||||
local x = math.sin(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,
|
||||
|
||||
get_velocity = function(self)
|
||||
@ -120,7 +126,6 @@ function mobs:register_mob(name, def)
|
||||
local d = {x = vx / ds, z = vz / ds}
|
||||
local p = {x = pos.x / ps, z = pos.z / ps}
|
||||
local an = (d.x * p.x) + (d.z * p.z)
|
||||
|
||||
if math.deg(math.acos(an)) > (self.fov / 2) then
|
||||
return false
|
||||
end
|
||||
@ -183,13 +188,14 @@ function mobs:register_mob(name, def)
|
||||
|
||||
on_step = function(self, dtime)
|
||||
|
||||
-- remove monsters if playing on peaceful
|
||||
if (self.type == "monster" and peaceful_only)
|
||||
or not within_limits(self.object:getpos(), 0) then
|
||||
self.object:remove()
|
||||
return
|
||||
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"
|
||||
and not self.tamed then
|
||||
self.lifetimer = self.lifetimer - dtime
|
||||
@ -203,7 +209,7 @@ function mobs:register_mob(name, def)
|
||||
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
|
||||
and self.child == false
|
||||
and math.random(1, self.replace_rate) == 1 then
|
||||
@ -215,7 +221,6 @@ function mobs:register_mob(name, def)
|
||||
and self.object:getvelocity().y == 0
|
||||
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 self.state == "stand" then
|
||||
minetest.set_node(pos, {name = self.replace_with})
|
||||
end
|
||||
end
|
||||
@ -225,14 +230,9 @@ function mobs:register_mob(name, def)
|
||||
if not self.fly then
|
||||
-- floating in water (or falling)
|
||||
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()
|
||||
|
||||
-- going up then apply gravity
|
||||
if v.y > 0.1 then
|
||||
self.object:setacceleration({
|
||||
x = 0,
|
||||
@ -240,7 +240,9 @@ function mobs:register_mob(name, def)
|
||||
z = 0
|
||||
})
|
||||
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
|
||||
self.object:setacceleration({
|
||||
x = 0,
|
||||
@ -249,6 +251,7 @@ function mobs:register_mob(name, def)
|
||||
})
|
||||
end
|
||||
else
|
||||
-- fall downwards
|
||||
self.object:setacceleration({
|
||||
x = 0,
|
||||
y = self.fall_speed,
|
||||
@ -287,6 +290,7 @@ function mobs:register_mob(name, def)
|
||||
self.timer = 0
|
||||
end
|
||||
|
||||
-- mob plays random sound at times
|
||||
if self.sounds.random
|
||||
and math.random(1, 100) <= 1 then
|
||||
minetest.sound_play(self.sounds.random, {
|
||||
@ -296,7 +300,9 @@ function mobs:register_mob(name, def)
|
||||
end
|
||||
|
||||
local do_env_damage = function(self)
|
||||
|
||||
if self.htimer > 0 then
|
||||
self.htimer = self.htimer - 1
|
||||
end
|
||||
local pos = self.object:getpos()
|
||||
local tod = minetest.get_timeofday()
|
||||
|
||||
@ -311,9 +317,9 @@ function mobs:register_mob(name, def)
|
||||
if check_for_death(self) then return end
|
||||
end
|
||||
|
||||
if self.water_damage ~= 0 or self.lava_damage ~= 0 then
|
||||
pos.y = pos.y + self.collisionbox[2] -- foot level
|
||||
local nod = minetest.get_node_or_nil(pos)
|
||||
if not nod then return end ; -- print ("standing in "..nod.name)
|
||||
local nod = node_ok(pos, "air") -- print ("standing in "..nod.name)
|
||||
local nodef = minetest.registered_nodes[nod.name]
|
||||
if not nodef then return end
|
||||
pos.y = pos.y + 1
|
||||
@ -330,12 +336,13 @@ function mobs:register_mob(name, def)
|
||||
if self.lava_damage ~= 0
|
||||
and (nodef.groups.lava
|
||||
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)
|
||||
effect(pos, 5, "fire_basic_flame.png")
|
||||
if check_for_death(self) then return end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
local do_jump = function(self)
|
||||
@ -343,32 +350,24 @@ function mobs:register_mob(name, def)
|
||||
return
|
||||
end
|
||||
|
||||
self.jumptimer = (self.jumptimer or 0) + 1
|
||||
if self.jumptimer < 3 then
|
||||
local pos = self.object:getpos()
|
||||
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)
|
||||
if not nod
|
||||
or not minetest.registered_nodes[nod.name]
|
||||
or minetest.registered_nodes[nod.name].walkable == false then
|
||||
if minetest.registered_nodes[nod.name].walkable == false then
|
||||
return
|
||||
end
|
||||
if self.direction then
|
||||
pos.y = pos.y + 0.5
|
||||
local nod = minetest.get_node_or_nil({
|
||||
local nod = node_ok({
|
||||
x = pos.x + self.direction.x,
|
||||
y = pos.y,
|
||||
z = pos.z + self.direction.z
|
||||
})
|
||||
--print ("in front:", nod.name, pos.y)
|
||||
if nod and nod.name and
|
||||
(nod.name ~= "air"
|
||||
or self.walk_chance == 0) then
|
||||
local def = minetest.registered_items[nod.name]
|
||||
if (def
|
||||
and def.walkable
|
||||
and not nod.name:find("fence"))
|
||||
if nod.name ~= "air"
|
||||
and minetest.registered_items[nod.name].walkable
|
||||
and not nod.name:find("fence")
|
||||
or self.walk_chance == 0 then
|
||||
local v = self.object:getvelocity()
|
||||
v.y = self.jump_height + 1
|
||||
@ -384,10 +383,6 @@ function mobs:register_mob(name, def)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
self.jumptimer = 0
|
||||
end
|
||||
end
|
||||
|
||||
-- environmental damage timer (every 1 second)
|
||||
self.env_damage_timer = self.env_damage_timer + dtime
|
||||
@ -454,7 +449,7 @@ function mobs:register_mob(name, def)
|
||||
end
|
||||
-- attack player
|
||||
if min_player then
|
||||
self.do_attack(self, min_player, min_dist)
|
||||
self.do_attack(self, min_player)
|
||||
end
|
||||
end
|
||||
|
||||
@ -482,11 +477,12 @@ function mobs:register_mob(name, def)
|
||||
end
|
||||
end
|
||||
if min_player then
|
||||
self.do_attack(self, min_player, min_dist)
|
||||
self.do_attack(self, min_player)
|
||||
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
|
||||
and self.hornytimer < 240
|
||||
and self.child == false then
|
||||
@ -497,7 +493,7 @@ function mobs:register_mob(name, def)
|
||||
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
|
||||
self.hornytimer = self.hornytimer + 1
|
||||
if self.hornytimer > 240 then
|
||||
@ -509,7 +505,7 @@ function mobs:register_mob(name, def)
|
||||
visual_size = self.base_size,
|
||||
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()
|
||||
v.y = self.jump_height
|
||||
v.x = 0 ; v.z = 0
|
||||
@ -517,7 +513,7 @@ function mobs:register_mob(name, def)
|
||||
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
|
||||
and self.hornytimer <= 40 then
|
||||
local pos = self.object:getpos()
|
||||
@ -552,6 +548,8 @@ function mobs:register_mob(name, def)
|
||||
and ent.hornytimer <= 40 then
|
||||
num = num + 1
|
||||
end
|
||||
|
||||
-- found your mate? then have a baby
|
||||
if num > 1 then
|
||||
self.hornytimer = 41
|
||||
ent.hornytimer = 41
|
||||
@ -618,13 +616,12 @@ function mobs:register_mob(name, def)
|
||||
-- stop following player if not holding specific item
|
||||
if self.following
|
||||
and self.following.is_player
|
||||
--and self.following:get_wielded_item():get_name() ~= self.follow then
|
||||
and follow_holding(self, self.following) == false then
|
||||
self.following = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- follow player or mob
|
||||
-- follow that thing
|
||||
if self.following then
|
||||
local s = self.object:getpos()
|
||||
local p
|
||||
@ -638,6 +635,8 @@ function mobs:register_mob(name, def)
|
||||
|
||||
if p then
|
||||
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
|
||||
self.following = nil
|
||||
else
|
||||
@ -649,7 +648,7 @@ function mobs:register_mob(name, def)
|
||||
self.object:setyaw(yaw)
|
||||
|
||||
-- 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
|
||||
if (self.jump
|
||||
and self.get_velocity(self) <= 0.5
|
||||
@ -658,7 +657,7 @@ function mobs:register_mob(name, def)
|
||||
and self.jump_chance > 0) then
|
||||
self.direction = {
|
||||
x = math.sin(yaw) * -1,
|
||||
y = -20,
|
||||
y = 0,
|
||||
z = math.cos(yaw)
|
||||
}
|
||||
do_jump(self)
|
||||
@ -677,15 +676,13 @@ function mobs:register_mob(name, def)
|
||||
end
|
||||
|
||||
if self.state == "stand" then
|
||||
-- randomly turn
|
||||
|
||||
if math.random(1, 4) == 1 then
|
||||
-- if there is a player nearby look at them
|
||||
local lp = nil
|
||||
local s = self.object:getpos()
|
||||
|
||||
if self.type == "npc" then
|
||||
local o = minetest.get_objects_inside_radius(self.object:getpos(), 3)
|
||||
|
||||
local yaw = 0
|
||||
for _,o in ipairs(o) do
|
||||
if o:is_player() then
|
||||
@ -695,6 +692,7 @@ function mobs:register_mob(name, def)
|
||||
end
|
||||
end
|
||||
|
||||
-- look at any players nearby, otherwise turn randomly
|
||||
if lp ~= nil then
|
||||
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
|
||||
@ -723,13 +721,6 @@ function mobs:register_mob(name, def)
|
||||
self.state = "walk"
|
||||
self.set_animation(self, "walk")
|
||||
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
|
||||
|
||||
elseif self.state == "walk" then
|
||||
@ -742,10 +733,12 @@ and self.fly_in == "default:water_source"
|
||||
and not lp then
|
||||
print ("out of water")
|
||||
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")
|
||||
return
|
||||
end
|
||||
|
||||
-- if water nearby then turn away
|
||||
if lp then
|
||||
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
|
||||
end
|
||||
self.object:setyaw(yaw)
|
||||
|
||||
-- otherwise randomly turn
|
||||
elseif math.random(1, 100) <= 30 then
|
||||
self.object:setyaw(self.object:getyaw() + ((math.random(0, 360) - 180) / 180 * math.pi))
|
||||
end
|
||||
|
||||
-- jump when walking comes to a halt
|
||||
if self.jump and self.get_velocity(self) <= 0.5
|
||||
and self.object:getvelocity().y == 0 then
|
||||
self.direction = {
|
||||
x = math.sin(yaw) * -1,
|
||||
y = -20,
|
||||
y = 0,
|
||||
z = math.cos(yaw)
|
||||
}
|
||||
do_jump(self)
|
||||
@ -777,40 +771,40 @@ end
|
||||
self:set_animation("stand")
|
||||
end
|
||||
|
||||
-- exploding mobs
|
||||
elseif self.state == "attack" and self.attack_type == "explode" then
|
||||
if not self.attack.player
|
||||
or not self.attack.player:is_player() then
|
||||
self.state = "stand"
|
||||
self:set_animation("stand")
|
||||
self.timer = 0
|
||||
self.blinktimer = 0
|
||||
return
|
||||
end
|
||||
-- attack routines (explode, dogfight, shoot, dogshoot)
|
||||
elseif self.state == "attack" then
|
||||
|
||||
-- calculate distance from mob and enemy
|
||||
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
|
||||
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.v_start = false
|
||||
self.set_velocity(self, 0)
|
||||
self:set_animation("stand")
|
||||
self.attack = nil
|
||||
self.v_start = false
|
||||
self.timer = 0
|
||||
self.blinktimer = 0
|
||||
self.attack = {player = nil, dist = nil}
|
||||
self:set_animation("stand")
|
||||
return
|
||||
else
|
||||
self:set_animation("walk")
|
||||
self.attack.dist = dist
|
||||
end
|
||||
|
||||
if self.attack_type == "explode" then
|
||||
|
||||
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
|
||||
if p.x > s.x then
|
||||
yaw = yaw + math.pi
|
||||
end
|
||||
self.object:setyaw(yaw)
|
||||
if self.attack.dist > 3 then
|
||||
|
||||
if dist > self.reach then
|
||||
if not self.v_start then
|
||||
self.v_start = true
|
||||
self.set_velocity(self, self.run_velocity)
|
||||
@ -843,6 +837,7 @@ end
|
||||
end
|
||||
if self.timer > 3 then
|
||||
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
|
||||
if minetest.find_node_near(pos, 1, {"group:water"})
|
||||
or minetest.is_protected(pos, "") then
|
||||
@ -862,26 +857,15 @@ end
|
||||
mobs:explosion(pos, 2, 0, 1, self.sounds.explode)
|
||||
end
|
||||
end
|
||||
-- end of exploding mobs
|
||||
|
||||
elseif self.state == "attack"
|
||||
and self.attack_type == "dogfight" 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
|
||||
elseif self.attack_type == "dogfight"
|
||||
or (self.attack_type == "dogshoot" and dist <= self.reach) then
|
||||
|
||||
-- fly bit modified from BlockMens creatures mod
|
||||
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 me_y = math.floor(p1.y)
|
||||
local p2 = p
|
||||
@ -921,16 +905,6 @@ end
|
||||
end
|
||||
-- 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}
|
||||
yaw = (math.atan(vec.z / vec.x) + math.pi / 2) - self.rotate
|
||||
@ -938,8 +912,11 @@ end
|
||||
yaw = yaw + math.pi
|
||||
end
|
||||
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
|
||||
if (self.jump
|
||||
and self.get_velocity(self) <= 0.5
|
||||
@ -948,7 +925,7 @@ end
|
||||
and self.jump_chance > 0) then
|
||||
self.direction = {
|
||||
x = math.sin(yaw) * -1,
|
||||
y = -20,
|
||||
y = 0,
|
||||
z = math.cos(yaw)
|
||||
}
|
||||
do_jump(self)
|
||||
@ -965,45 +942,28 @@ end
|
||||
p2.y = p2.y + 1.5
|
||||
s2.y = s2.y + 1.5
|
||||
if minetest.line_of_sight(p2, s2) == true then
|
||||
-- play attack sound
|
||||
if self.sounds.attack then
|
||||
minetest.sound_play(self.sounds.attack, {
|
||||
object = self.object,
|
||||
max_hear_distance = self.sounds.distance
|
||||
})
|
||||
end
|
||||
self.attack.player:punch(self.object, 1.0, {
|
||||
-- punch player
|
||||
self.attack:punch(self.object, 1.0, {
|
||||
full_punch_interval=1.0,
|
||||
damage_groups = {fleshy=self.damage}
|
||||
}, vec)
|
||||
if self.attack.player:get_hp() <= 0 then
|
||||
self.state = "stand"
|
||||
self:set_animation("stand")
|
||||
end
|
||||
}, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif self.state == "attack"
|
||||
and self.attack_type == "shoot" then
|
||||
elseif self.attack_type == "shoot"
|
||||
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
|
||||
s.y = s.y + .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}
|
||||
yaw = (math.atan(vec.z / vec.x) + math.pi / 2) - self.rotate
|
||||
@ -1017,11 +977,11 @@ end
|
||||
and self.timer > self.shoot_interval
|
||||
and math.random(1, 100) <= 60 then
|
||||
self.timer = 0
|
||||
|
||||
self:set_animation("punch")
|
||||
|
||||
if self.sounds.attack then
|
||||
minetest.sound_play(self.sounds.attack, {
|
||||
-- play shoot attack sound
|
||||
if self.sounds.shoot_attack then
|
||||
minetest.sound_play(self.sounds.shoot_attack, {
|
||||
object = self.object,
|
||||
max_hear_distance = self.sounds.distance
|
||||
})
|
||||
@ -1032,13 +992,16 @@ end
|
||||
local obj = minetest.add_entity(p, self.arrow)
|
||||
local amount = (vec.x ^ 2 + vec.y ^ 2 + vec.z ^ 2) ^ 0.5
|
||||
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.y = vec.y *v / amount
|
||||
vec.z = vec.z *v / amount
|
||||
obj:setvelocity(vec)
|
||||
end
|
||||
end
|
||||
|
||||
end -- END if self.state == "attack"
|
||||
end,
|
||||
|
||||
on_activate = function(self, staticdata, dtime_s)
|
||||
@ -1082,7 +1045,7 @@ end
|
||||
mesh = def.gotten_mesh
|
||||
end
|
||||
|
||||
-- if object is child then set half size
|
||||
-- set child objects to half size
|
||||
if self.child == true then
|
||||
vis_size = {
|
||||
x = self.base_size.x / 2,
|
||||
@ -1108,7 +1071,6 @@ end
|
||||
self.object:set_hp(self.health)
|
||||
self.object:set_armor_groups({fleshy = self.armor})
|
||||
self.state = "stand"
|
||||
--self.order = "stand"
|
||||
self.following = nil
|
||||
self.old_y = self.object:getpos().y
|
||||
self.object:setyaw(math.random(1, 360) / 180 * math.pi)
|
||||
@ -1119,7 +1081,6 @@ end
|
||||
self.visual_size = vis_size
|
||||
-- set anything changed above
|
||||
self.object:set_properties(self)
|
||||
|
||||
end,
|
||||
|
||||
get_staticdata = function(self)
|
||||
@ -1132,6 +1093,7 @@ end
|
||||
self.remove_ok = true
|
||||
self.attack = nil
|
||||
self.following = nil
|
||||
self.state = "stand"
|
||||
|
||||
local tmp = {}
|
||||
for _,stat in pairs(self) do
|
||||
@ -1203,7 +1165,7 @@ end
|
||||
if self.passive == false
|
||||
and not self.tamed then
|
||||
if self.state ~= "attack" then
|
||||
self.do_attack(self, hitter, 1)
|
||||
self.do_attack(self, hitter)
|
||||
end
|
||||
-- alert others to the attack
|
||||
local obj = nil
|
||||
@ -1213,18 +1175,19 @@ end
|
||||
if obj.group_attack == true
|
||||
and not obj.tamed --MFF(crabman) group tamed don't attack
|
||||
and obj.state ~= "attack" then
|
||||
obj.do_attack(obj, hitter, 1)
|
||||
obj.do_attack(obj, hitter)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
end -- END mobs:register_mob function
|
||||
|
||||
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
|
||||
minetest.register_abm({
|
||||
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
|
||||
if mobs.protected == 1
|
||||
and minetest.is_protected(pos, "")
|
||||
and not spawn_in_area then
|
||||
and not spawn_in_area then --MFF crabman
|
||||
return
|
||||
end
|
||||
|
||||
@ -1260,21 +1223,11 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter
|
||||
end
|
||||
|
||||
-- are we spawning inside a solid node?
|
||||
local 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
|
||||
if minetest.registered_nodes[node_ok(pos).name].walkable == true then
|
||||
return
|
||||
end
|
||||
|
||||
pos.y = pos.y + 1
|
||||
|
||||
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
|
||||
if minetest.registered_nodes[node_ok(pos).name].walkable == true then
|
||||
return
|
||||
end
|
||||
|
||||
@ -1357,7 +1310,8 @@ function mobs:explosion(pos, radius, fire, smoke, sound)
|
||||
and data[vi] ~= c_obsidian
|
||||
and data[vi] ~= c_brick
|
||||
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
|
||||
and minetest.get_item_group(n, "unbreakable") ~= 1 then
|
||||
-- if chest then drop items inside
|
||||
@ -1372,7 +1326,8 @@ function mobs:explosion(pos, radius, fire, smoke, sound)
|
||||
obj:setvelocity({
|
||||
x = math.random(-2, 2),
|
||||
y = 7,
|
||||
z = math.random(-2, 2)})
|
||||
z = math.random(-2, 2)
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1408,7 +1363,6 @@ function check_for_death(self)
|
||||
return false
|
||||
end
|
||||
local pos = self.object:getpos()
|
||||
pos.y = pos.y + 0.5 -- drop items half a block higher
|
||||
self.object:remove()
|
||||
local obj = nil
|
||||
for _,drop in ipairs(self.drops) do
|
||||
@ -1490,13 +1444,9 @@ function mobs:register_arrow(name, def)
|
||||
return
|
||||
end
|
||||
|
||||
local engage = 10 - (self.velocity / 2) -- clear entity before arrow becomes active
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if node then node = node.name else node = "air" end
|
||||
|
||||
if self.hit_node
|
||||
and minetest.registered_nodes[node]
|
||||
and minetest.registered_nodes[node].walkable then
|
||||
if self.hit_node then
|
||||
local node = node_ok(pos).name
|
||||
if minetest.registered_nodes[node].walkable then
|
||||
self.hit_node(self, pos, node)
|
||||
if self.drop == true then
|
||||
pos.y = pos.y + 1
|
||||
@ -1506,9 +1456,11 @@ function mobs:register_arrow(name, def)
|
||||
self.object:remove() ; -- print ("hit node")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
if self.hit_player
|
||||
and player:is_player() then
|
||||
@ -1545,16 +1497,19 @@ function mobs:register_egg(mob, desc, background, addegg)
|
||||
local pos = pointed_thing.above
|
||||
if pos and within_limits(pos, 0)
|
||||
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 ent = mob:get_luaentity()
|
||||
if ent.type ~= "monster" then
|
||||
-- set owner
|
||||
-- set owner and tame
|
||||
ent.owner = placer:get_player_name()
|
||||
ent.tamed = true
|
||||
end
|
||||
-- if not in creative then take item
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
itemstack:take_item()
|
||||
end
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
})
|
||||
@ -1642,30 +1597,29 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
|
||||
|
||||
if not self.follow then return false end
|
||||
|
||||
local item = clicker:get_wielded_item()
|
||||
|
||||
-- can eat/tame with item in hand
|
||||
if follow_holding(self, clicker) then
|
||||
|
||||
-- take item
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
local item = clicker:get_wielded_item()
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
end
|
||||
|
||||
-- heal health
|
||||
local hp = self.object:get_hp()
|
||||
--if hp < self.hp_max then
|
||||
hp = hp + 4
|
||||
if hp >= self.hp_max then
|
||||
if hp >= self.hp_max
|
||||
and self.htimer < 1 then
|
||||
hp = self.hp_max
|
||||
minetest.chat_send_player(clicker:get_player_name(),
|
||||
self.name:split(":")[2]
|
||||
.. " at full health")
|
||||
.. " at full health (" .. tostring(hp) .. ")")
|
||||
self.htimer = 5
|
||||
end
|
||||
self.object:set_hp(hp)
|
||||
self.health = hp
|
||||
--end
|
||||
|
||||
-- make children grow quicker
|
||||
if self.child == true then
|
||||
@ -1715,3 +1669,15 @@ function within_limits(pos, radius)
|
||||
return false -- beyond limits
|
||||
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
|
||||
|
@ -6,6 +6,7 @@ mobs:register_mob("mobs:bunny", {
|
||||
type = "animal",
|
||||
-- is it aggressive
|
||||
passive = true,
|
||||
reach = 1,
|
||||
-- health & armor
|
||||
hp_min = 3, hp_max = 6, armor = 200,
|
||||
-- textures and model
|
||||
@ -62,7 +63,6 @@ mobs:register_mob("mobs:bunny", {
|
||||
textures = {"mobs_bunny_evil.png"},
|
||||
})
|
||||
self.type = "monster"
|
||||
self.state = "attack"
|
||||
self.object:set_hp(20)
|
||||
return
|
||||
end
|
||||
|
@ -8,6 +8,7 @@ mobs:register_mob("mobs:cow", {
|
||||
passive = false,
|
||||
group_attack = true,
|
||||
attack_type = "dogfight",
|
||||
reach = 2,
|
||||
damage = 4,
|
||||
-- health & armor
|
||||
hp_min = 25,
|
||||
|
@ -7,6 +7,7 @@ mobs:register_mob("mobs:dirt_monster", {
|
||||
-- aggressive, deals 6 damage to player when hit
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
reach = 2,
|
||||
damage = 5,
|
||||
-- health & armor
|
||||
hp_min = 25,
|
||||
|
@ -10,7 +10,8 @@ mobs:register_mob("mobs:dungeon_master", {
|
||||
-- aggressive, shoots fireballs at player, deal 13 damages
|
||||
passive = false,
|
||||
damage = 12,
|
||||
attack_type = "shoot",
|
||||
attack_type = "dogshoot",
|
||||
reach = 3,
|
||||
shoot_interval = 2.5,
|
||||
arrow = "mobs:fireball",
|
||||
shoot_offset = 1,
|
||||
@ -32,7 +33,7 @@ mobs:register_mob("mobs:dungeon_master", {
|
||||
makes_footstep_sound = true,
|
||||
sounds = {
|
||||
random = "mobs_dungeonmaster",
|
||||
attack = "mobs_fireball",
|
||||
shoot_attack = "mobs_fireball",
|
||||
},
|
||||
-- speed and jump
|
||||
walk_velocity = 1,
|
||||
|
@ -7,6 +7,7 @@ mobs:register_mob("mobs:lava_flan", {
|
||||
-- aggressive, deals 5 damage to player when hit
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
reach = 2,
|
||||
damage = 5,
|
||||
-- health and armor
|
||||
hp_min = 20,
|
||||
|
0
mods/mobs/models/mobs_shark.b3d
Normal file → Executable file
@ -86,6 +86,7 @@ mobs:register_mob("mobs:npc", {
|
||||
end
|
||||
if self.diamond_count >= 4 then
|
||||
self.damages = 3
|
||||
self.tamed = true
|
||||
self.owner = clicker:get_player_name()
|
||||
end
|
||||
end
|
||||
|
@ -90,6 +90,7 @@ mobs:register_mob("mobs:npc_female", {
|
||||
end
|
||||
if self.diamond_count >= 4 then
|
||||
self.damages = 3
|
||||
self.tamed = true
|
||||
self.owner = clicker:get_player_name()
|
||||
end
|
||||
end
|
||||
|
@ -7,6 +7,7 @@ mobs:register_mob("mobs:oerkki", {
|
||||
-- aggressive, deals 7 damage when player hit
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
reach = 2,
|
||||
damage = 6,
|
||||
-- health & armor
|
||||
hp_min = 40,
|
||||
@ -25,7 +26,7 @@ mobs:register_mob("mobs:oerkki", {
|
||||
makes_footstep_sound = false,
|
||||
sounds = {
|
||||
random = "mobs_oerkki",
|
||||
attack = "mobs_oerkki_attack",
|
||||
shoot_attack = "mobs_oerkki_attack",
|
||||
},
|
||||
-- speed and jump
|
||||
walk_velocity = 2,
|
||||
|
@ -7,6 +7,7 @@ mobs:register_mob("mobs:sand_monster", {
|
||||
-- aggressive, deals 5 damage to player when hit
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
reach = 2,
|
||||
damage = 4,
|
||||
-- health & armor
|
||||
hp_min = 15,
|
||||
|
0
mods/mobs/shark.lua
Normal file → Executable file
@ -7,6 +7,7 @@ mobs:register_mob("mobs:spider", {
|
||||
-- agressive, does 6 damage to player when hit
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
reach = 2,
|
||||
damage = 5,
|
||||
-- health & armor
|
||||
hp_min = 30,
|
||||
|
@ -7,6 +7,7 @@ mobs:register_mob("mobs:stone_monster", {
|
||||
-- aggressive, deals 8 damage to player when hit
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
reach = 2,
|
||||
damage = 7,
|
||||
-- health & armor
|
||||
hp_min = 20,
|
||||
|
0
mods/mobs/textures/mobs_cow_inv.png
Normal file → Executable 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
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
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
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
0
mods/mobs/textures/shark_third.png
Normal file → Executable file
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@ -7,6 +7,7 @@ mobs:register_mob("mobs:tree_monster", {
|
||||
-- aggressive, deals 9 damage to player when hit
|
||||
passive = false,
|
||||
attack_type = "dogfight",
|
||||
reach = 2,
|
||||
damage = 8,
|
||||
-- health & armor
|
||||
hp_min = 40,
|
||||
|
@ -8,6 +8,7 @@ mobs:register_mob("mobs:pumba", {
|
||||
passive = false,
|
||||
group_attack = true,
|
||||
attack_type = "dogfight",
|
||||
reach = 2,
|
||||
damage = 4,
|
||||
-- health & armor
|
||||
hp_min = 15,
|
||||
|