update mobs mod (add pathfinding) https://github.com/MinetestForFun/server-minetestforfun/issues/393
parent
fe63e264c0
commit
e45cf90460
|
@ -28,6 +28,13 @@ This mod contains the following additions:
|
||||||
|
|
||||||
Changelog:
|
Changelog:
|
||||||
|
|
||||||
|
1.26- Pathfinding feature added thanks to rnd, when monsters attack they become scary smart in finding you :)
|
||||||
|
1.25- Mobs no longer spawn within 12 blocks of player or despawn within same range, spawners now have player detection, Code tidy and tweak.
|
||||||
|
1.24- Added feature where certain animals run away when punched (runaway = true in mob definition)
|
||||||
|
1.23- Added mob spawner block for admin to setup spawners in-game (place and right click to enter settings)
|
||||||
|
1.22- Added ability to name tamed animals and npc using nametags, also npc will attack anyone who punches them apart from owner
|
||||||
|
1.21- Added some more error checking to reduce serialize.h error and added height checks for falling off cliffs (thanks cmdskp)
|
||||||
|
1.20- Error checking added to remove bad mobs, out of map limit mobs and stop serialize.h error
|
||||||
1.19- Chickens now drop egg items instead of placing the egg, also throwing eggs result in 1/8 chance of spawning chick
|
1.19- Chickens now drop egg items instead of placing the egg, also throwing eggs result in 1/8 chance of spawning chick
|
||||||
1.18- Added docile_by_day flag so that monsters will not attack automatically during daylight hours unless hit first
|
1.18- Added docile_by_day flag so that monsters will not attack automatically during daylight hours unless hit first
|
||||||
1.17- Added 'dogshoot' attack type, shoots when out of reach, melee attack when in reach, also api tweaks and self.reach added
|
1.17- Added 'dogshoot' attack type, shoots when out of reach, melee attack when in reach, also api tweaks and self.reach added
|
||||||
|
@ -57,4 +64,4 @@ beta- Npc mob added, kills monsters, attacks player when punched, right click wi
|
||||||
0.4 - Dungeon Masters and Mese Monsters have much better aim due to shoot_offset, also they can both shoot through nodes that aren't walkable (flowers, grass etc) plus new sheep sound :)
|
0.4 - Dungeon Masters and Mese Monsters have much better aim due to shoot_offset, also they can both shoot through nodes that aren't walkable (flowers, grass etc) plus new sheep sound :)
|
||||||
0.3 - Added LOTT's Spider mob, made Cobwebs, added KPavel's Bee with Honey and Beehives (made texture), Warthogs now have sound and can be tamed, taming of shaved sheep or milked cow with 8 wheat so it will not despawn, many bug fixes :)
|
0.3 - Added LOTT's Spider mob, made Cobwebs, added KPavel's Bee with Honey and Beehives (made texture), Warthogs now have sound and can be tamed, taming of shaved sheep or milked cow with 8 wheat so it will not despawn, many bug fixes :)
|
||||||
0.2 - Cooking bucket of milk into cheese now returns empty bucket
|
0.2 - Cooking bucket of milk into cheese now returns empty bucket
|
||||||
0.1 - Initial Release
|
0.1 - Initial Release
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
-- Mobs Api (2nd February 2016)
|
-- Mobs Api (8th February 2016)
|
||||||
mobs = {}
|
mobs = {}
|
||||||
mobs.mod = "redo"
|
mobs.mod = "redo"
|
||||||
|
|
||||||
|
@ -10,6 +10,11 @@ local creative = minetest.setting_getbool("creative_mode")
|
||||||
local spawn_protected = tonumber(minetest.setting_get("mobs_spawn_protected")) or 1
|
local spawn_protected = tonumber(minetest.setting_get("mobs_spawn_protected")) or 1
|
||||||
local remove_far = minetest.setting_getbool("remove_far_mobs")
|
local remove_far = minetest.setting_getbool("remove_far_mobs")
|
||||||
|
|
||||||
|
-- pathfinding settings
|
||||||
|
local enable_pathfinding = true
|
||||||
|
local stuck_timeout = 5 -- how long before mob gets stuck in place and starts searching
|
||||||
|
local stuck_path_timeout = 15 -- how long will mob follow path before giving up
|
||||||
|
|
||||||
-- internal functions
|
-- internal functions
|
||||||
|
|
||||||
local pi = math.pi
|
local pi = math.pi
|
||||||
|
@ -1453,6 +1458,32 @@ minetest.register_entity(name, {
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- rnd: new movement direction
|
||||||
|
if self.path.stuck
|
||||||
|
and self.path.way then
|
||||||
|
|
||||||
|
-- no paths longer than 50
|
||||||
|
if #self.path.way > 50 then
|
||||||
|
self.path.stuck = false
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local p1 = self.path.way[1]
|
||||||
|
|
||||||
|
if not p1 then
|
||||||
|
self.path.stuck = false
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if math.abs(p1.x-s.x) + math.abs(p1.z - s.z) < 0.75 then
|
||||||
|
-- reached waypoint, remove it from queue
|
||||||
|
table.remove(self.path.way, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set new temporary target
|
||||||
|
p = {x = p1.x, y = p1.y, z = p1.z}
|
||||||
|
end
|
||||||
|
|
||||||
local vec = {
|
local vec = {
|
||||||
x = p.x - s.x,
|
x = p.x - s.x,
|
||||||
y = p.y - s.y,
|
y = p.y - s.y,
|
||||||
|
@ -1474,6 +1505,86 @@ minetest.register_entity(name, {
|
||||||
-- move towards enemy if beyond mob reach
|
-- move towards enemy if beyond mob reach
|
||||||
if dist > self.reach then
|
if dist > self.reach then
|
||||||
|
|
||||||
|
-- PATH FINDING by rnd
|
||||||
|
if enable_pathfinding then
|
||||||
|
|
||||||
|
local s1 = self.path.lastpos
|
||||||
|
|
||||||
|
if math.abs(s1.x - s.x) + math.abs(s1.z - s.z) < 2 then
|
||||||
|
|
||||||
|
-- rnd: almost standing still, to do: insert path finding here
|
||||||
|
self.path.stuck_timer = self.path.stuck_timer + dtime
|
||||||
|
else
|
||||||
|
self.path.stuck_timer = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
self.path.lastpos = {x = s.x, y = s.y, z = s.z}
|
||||||
|
|
||||||
|
if (self.path.stuck_timer > stuck_timeout and not self.path.stuck)
|
||||||
|
or (self.path.stuck_timer > stuck_path_timeout and self.path.stuck) then
|
||||||
|
|
||||||
|
-- im stuck, search for path
|
||||||
|
self.path.stuck = true
|
||||||
|
|
||||||
|
local sheight = self.collisionbox[5] - self.collisionbox[2]
|
||||||
|
|
||||||
|
-- round position to center of node to avoid stuck in walls,
|
||||||
|
-- also adjust height for player models!
|
||||||
|
s.x = math.floor(s.x + 0.5)
|
||||||
|
s.y = math.floor(s.y + 0.5) - sheight
|
||||||
|
s.z = math.floor(s.z + 0.5)
|
||||||
|
|
||||||
|
local ssight, sground
|
||||||
|
|
||||||
|
ssight, sground = minetest.line_of_sight(s,
|
||||||
|
{x = s.x, y = s. y - 4, z = s.z}, 1)
|
||||||
|
|
||||||
|
-- determine node above ground
|
||||||
|
if not ssight then
|
||||||
|
s.y = sground.y + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
--minetest.chat_send_all("stuck at " .. s.x .." " .. s.y .. " " .. s.z .. ", calculating path")
|
||||||
|
|
||||||
|
local p1 = self.attack:getpos()
|
||||||
|
|
||||||
|
p1.x = math.floor(p1.x + 0.5)
|
||||||
|
p1.y = math.floor(p1.y + 0.5)
|
||||||
|
p1.z = math.floor(p1.z + 0.5)
|
||||||
|
|
||||||
|
--minetest.find_path(pos1, pos2, searchdistance, max_jump, max_drop, algorithm)
|
||||||
|
|
||||||
|
self.path.way = minetest.find_path(s, p1, 16, 2, 6, "A*_noprefetch")
|
||||||
|
|
||||||
|
if not self.path.way then
|
||||||
|
|
||||||
|
self.path.stuck = false
|
||||||
|
|
||||||
|
-- can't find path, play sound
|
||||||
|
if self.sounds.random then
|
||||||
|
minetest.sound_play(self.sounds.random, {
|
||||||
|
object = self.object,
|
||||||
|
max_hear_distance = self.sounds.distance
|
||||||
|
})
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- found path, play sound
|
||||||
|
if self.sounds.attack then
|
||||||
|
minetest.sound_play(self.sounds.attack, {
|
||||||
|
object = self.object,
|
||||||
|
max_hear_distance = self.sounds.distance
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
--minetest.chat_send_all("found path with length " .. #self.path.way);
|
||||||
|
end
|
||||||
|
|
||||||
|
self.path.stuck_timer = 0
|
||||||
|
|
||||||
|
end -- END if pathfinding enabled
|
||||||
|
end
|
||||||
|
-- END PATH FINDING
|
||||||
|
|
||||||
-- jump attack
|
-- jump attack
|
||||||
if (self.jump
|
if (self.jump
|
||||||
and get_velocity(self) <= 0.5
|
and get_velocity(self) <= 0.5
|
||||||
|
@ -1519,6 +1630,9 @@ minetest.register_entity(name, {
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- rnd: not stuck
|
||||||
|
self.path.stuck = false
|
||||||
|
|
||||||
-- punch player
|
-- punch player
|
||||||
self.attack:punch(self.object, 1.0, {
|
self.attack:punch(self.object, 1.0, {
|
||||||
full_punch_interval = 1.0,
|
full_punch_interval = 1.0,
|
||||||
|
@ -1650,10 +1764,16 @@ minetest.register_entity(name, {
|
||||||
local v = self.object:getvelocity()
|
local v = self.object:getvelocity()
|
||||||
local r = 1.4 - math.min(punch_interval, 1.4)
|
local r = 1.4 - math.min(punch_interval, 1.4)
|
||||||
local kb = r * 5
|
local kb = r * 5
|
||||||
|
local up = 2
|
||||||
|
|
||||||
|
-- if already in air then dont go up anymore when hit
|
||||||
|
if v.y > 0 then
|
||||||
|
up = 0
|
||||||
|
end
|
||||||
|
|
||||||
self.object:setvelocity({
|
self.object:setvelocity({
|
||||||
x = (dir.x or 0) * kb,
|
x = (dir.x or 0) * kb,
|
||||||
y = 2,
|
y = up,
|
||||||
z = (dir.z or 0) * kb
|
z = (dir.z or 0) * kb
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1689,15 +1809,16 @@ minetest.register_entity(name, {
|
||||||
self.following = nil
|
self.following = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- attack puncher and call other mobs for help
|
-- attack puncher and call other mobs for help
|
||||||
if self.passive == false
|
if self.passive == false
|
||||||
and self.child == false
|
and self.child == false
|
||||||
and hitter:get_player_name() ~= self.owner then
|
and hitter:get_player_name() ~= self.owner then
|
||||||
|
|
||||||
if self.state ~= "attack" then
|
--if self.state ~= "attack" then
|
||||||
|
-- attack whoever punched mob
|
||||||
|
self.state = ""
|
||||||
do_attack(self, hitter)
|
do_attack(self, hitter)
|
||||||
end
|
--end
|
||||||
|
|
||||||
-- alert others to the attack
|
-- alert others to the attack
|
||||||
local obj = nil
|
local obj = nil
|
||||||
|
@ -1791,6 +1912,14 @@ minetest.register_entity(name, {
|
||||||
self.health = math.random (self.hp_min, self.hp_max)
|
self.health = math.random (self.hp_min, self.hp_max)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- rnd: pathfinding init
|
||||||
|
self.path = {}
|
||||||
|
self.path.way = {} -- path to follow, table of positions
|
||||||
|
self.path.lastpos = {x = 0, y = 0, z = 0}
|
||||||
|
self.path.stuck = false
|
||||||
|
self.path.stuck_timer = 0 -- if stuck for too long search for path
|
||||||
|
-- end init
|
||||||
|
|
||||||
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.old_y = self.object:getpos().y
|
self.old_y = self.object:getpos().y
|
||||||
|
@ -2108,7 +2237,8 @@ function mobs:register_arrow(name, def)
|
||||||
|
|
||||||
local node = node_ok(pos).name
|
local node = node_ok(pos).name
|
||||||
|
|
||||||
if minetest.registered_nodes[node].walkable then
|
--if minetest.registered_nodes[node].walkable then
|
||||||
|
if node ~= "air" then
|
||||||
|
|
||||||
self.hit_node(self, pos, node)
|
self.hit_node(self, pos, node)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue