update mobs, readd cow replace with dung
@ -28,6 +28,7 @@ This mod contains the following additions:
|
||||
|
||||
Changelog:
|
||||
|
||||
1.27- Added new sheep, lava flan and spawn egg textures. New Lava Pick tool smelts what you dig. New atan checking function.
|
||||
1.26- Pathfinding feature added thanks to rnd, when monsters attack they become scary smart in finding you :) also, beehive produces honey now :)
|
||||
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,4 +1,4 @@
|
||||
-- Mobs Api (17th February 2016)
|
||||
-- Mobs Api (4th March 2016)
|
||||
mobs = {}
|
||||
mobs.mod = "redo"
|
||||
|
||||
@ -20,6 +20,16 @@ local stuck_path_timeout = 10 -- how long will mob follow path before giving up
|
||||
|
||||
local pi = math.pi
|
||||
local square = math.sqrt
|
||||
local atan = function(x)
|
||||
|
||||
if x ~= x then
|
||||
--error("atan bassed NaN")
|
||||
print ("atan based NaN")
|
||||
return 0
|
||||
else
|
||||
return math.atan(x)
|
||||
end
|
||||
end
|
||||
|
||||
do_attack = function(self, player)
|
||||
|
||||
@ -129,6 +139,34 @@ set_animation = function(self, type)
|
||||
end
|
||||
end
|
||||
|
||||
-- check line of sight for walkers and swimmers alike
|
||||
function line_of_sight_water(self, pos1, pos2, stepsize)
|
||||
|
||||
local s, pos_w = minetest.line_of_sight(pos1, pos2, stepsize)
|
||||
|
||||
-- normal walking and flying mobs can see you through air
|
||||
if s == true then
|
||||
return true
|
||||
end
|
||||
|
||||
-- swimming mobs can see you through water
|
||||
if s == false
|
||||
and self.fly
|
||||
and self.fly_in == "default:water_source" then
|
||||
|
||||
local nod = minetest.get_node(pos_w).name
|
||||
|
||||
if nod == "default:water_source"
|
||||
or nod == "default:water_flowing" then
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
-- particle effects
|
||||
function effect(pos, amount, texture, max_size)
|
||||
|
||||
@ -285,6 +323,24 @@ local function is_at_cliff(self)
|
||||
return false
|
||||
end
|
||||
|
||||
-- get node but use fallback for nil or unknown
|
||||
local 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
|
||||
|
||||
if minetest.registered_nodes[node.name] then
|
||||
return node
|
||||
end
|
||||
|
||||
return minetest.registered_nodes[fallback]
|
||||
end
|
||||
|
||||
-- environmental damage (water, lava, fire, light)
|
||||
do_env_damage = function(self)
|
||||
|
||||
@ -315,15 +371,16 @@ do_env_damage = function(self)
|
||||
effect(pos, 5, "tnt_smoke.png")
|
||||
end
|
||||
|
||||
-- what is mob standing in?
|
||||
pos.y = pos.y + self.collisionbox[2] + 0.1 -- foot level
|
||||
self.standing_in = node_ok(pos, "air").name
|
||||
--print ("standing in " .. self.standing_in)
|
||||
|
||||
if self.water_damage ~= 0
|
||||
or self.lava_damage ~= 0 then
|
||||
|
||||
pos.y = pos.y + self.collisionbox[2] + 0.1 -- foot level
|
||||
local nodef = minetest.registered_nodes[self.standing_in]
|
||||
|
||||
local nod = node_ok(pos, "air") ; --print ("standing in "..nod.name)
|
||||
local nodef = minetest.registered_nodes[nod.name]
|
||||
|
||||
if not nodef then return end --MFF fix crash
|
||||
pos.y = pos.y + 1
|
||||
|
||||
-- water
|
||||
@ -338,8 +395,8 @@ do_env_damage = function(self)
|
||||
-- lava or fire
|
||||
if self.lava_damage ~= 0
|
||||
and (nodef.groups.lava
|
||||
or nod.name == "fire:basic_flame"
|
||||
or nod.name == "fire:permanent_flame") then
|
||||
or self.standing_in == "fire:basic_flame"
|
||||
or self.standing_in == "fire:permanent_flame") then
|
||||
|
||||
self.object:set_hp(self.object:get_hp() - self.lava_damage)
|
||||
|
||||
@ -462,24 +519,6 @@ function entity_physics(pos, radius, self) --/MFF (Crabman|06/23/2015)add self t
|
||||
end
|
||||
end
|
||||
|
||||
-- get node but use fallback for nil or unknown
|
||||
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
|
||||
|
||||
if minetest.registered_nodes[node.name] then
|
||||
return node
|
||||
end
|
||||
|
||||
return minetest.registered_nodes[fallback]
|
||||
end
|
||||
|
||||
-- should mob follow what I'm holding ?
|
||||
function follow_holding(self, clicker)
|
||||
|
||||
@ -1117,7 +1156,8 @@ minetest.register_entity(name, {
|
||||
-- field of view check goes here
|
||||
|
||||
-- choose closest player to attack
|
||||
if minetest.line_of_sight(sp, p, 2) == true
|
||||
--if minetest.line_of_sight(sp, p, 2) == true
|
||||
if line_of_sight_water(self, sp, p, 2) == true
|
||||
and dist < min_dist then
|
||||
min_dist = dist
|
||||
min_player = player
|
||||
@ -1246,7 +1286,7 @@ minetest.register_entity(name, {
|
||||
if vec.x ~= 0
|
||||
and vec.z ~= 0 then
|
||||
|
||||
yaw = (math.atan(vec.z / vec.x) + pi / 2) - self.rotate
|
||||
yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate
|
||||
|
||||
if p.x > s.x then
|
||||
yaw = yaw + pi
|
||||
@ -1283,6 +1323,19 @@ minetest.register_entity(name, {
|
||||
end
|
||||
end
|
||||
|
||||
-- water swimmers flop when on land
|
||||
if self.fly
|
||||
and self.fly_in == "default:water_source"
|
||||
and self.standing_in ~= self.fly_in then
|
||||
|
||||
self.state = "flop"
|
||||
self.object:setvelocity({x = 0, y = -5, z = 0})
|
||||
|
||||
set_animation(self, "stand")
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if self.state == "stand" then
|
||||
|
||||
if math.random(1, 4) == 1 then
|
||||
@ -1315,7 +1368,7 @@ minetest.register_entity(name, {
|
||||
if vec.x ~= 0
|
||||
and vec.z ~= 0 then
|
||||
|
||||
yaw = (math.atan(vec.z / vec.x) + pi / 2) - self.rotate
|
||||
yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate
|
||||
|
||||
if lp.x > s.x then
|
||||
yaw = yaw + pi
|
||||
@ -1350,22 +1403,6 @@ minetest.register_entity(name, {
|
||||
local s = self.object:getpos()
|
||||
local lp = minetest.find_node_near(s, 1, {"group:water"})
|
||||
|
||||
-- water swimmers cannot move out of water
|
||||
if self.fly
|
||||
and self.fly_in == "default:water_source"
|
||||
and not lp then
|
||||
|
||||
--print ("out of water")
|
||||
|
||||
set_velocity(self, 0)
|
||||
|
||||
-- change to undefined state so nothing more happens
|
||||
self.state = "flop"
|
||||
set_animation(self, "stand")
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- if water nearby then turn away
|
||||
if lp then
|
||||
|
||||
@ -1378,7 +1415,7 @@ minetest.register_entity(name, {
|
||||
if vec.x ~= 0
|
||||
and vec.z ~= 0 then
|
||||
|
||||
yaw = math.atan(vec.z / vec.x) + 3 * pi / 2 - self.rotate
|
||||
yaw = atan(vec.z / vec.x) + 3 * pi / 2 - self.rotate
|
||||
|
||||
if lp.x > s.x then
|
||||
yaw = yaw + pi
|
||||
@ -1480,7 +1517,7 @@ minetest.register_entity(name, {
|
||||
if vec.x ~= 0
|
||||
and vec.z ~= 0 then
|
||||
|
||||
yaw = math.atan(vec.z / vec.x) + pi / 2 - self.rotate
|
||||
yaw = atan(vec.z / vec.x) + pi / 2 - self.rotate
|
||||
|
||||
if p.x > s.x then
|
||||
yaw = yaw + pi
|
||||
@ -1657,7 +1694,7 @@ minetest.register_entity(name, {
|
||||
if vec.x ~= 0
|
||||
and vec.z ~= 0 then
|
||||
|
||||
yaw = (math.atan(vec.z / vec.x) + pi / 2) - self.rotate
|
||||
yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate
|
||||
|
||||
if p.x > s.x then
|
||||
yaw = yaw + pi
|
||||
@ -1720,7 +1757,8 @@ minetest.register_entity(name, {
|
||||
p2.y = p2.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
|
||||
if line_of_sight_water(self, p2, s2) == true then
|
||||
|
||||
-- play attack sound
|
||||
if self.sounds.attack then
|
||||
@ -1756,7 +1794,7 @@ minetest.register_entity(name, {
|
||||
if vec.x ~= 0
|
||||
and vec.z ~= 0 then
|
||||
|
||||
yaw = (math.atan(vec.z / vec.x) + pi / 2) - self.rotate
|
||||
yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate
|
||||
|
||||
if p.x > s.x then
|
||||
yaw = yaw + pi
|
||||
@ -1868,7 +1906,8 @@ minetest.register_entity(name, {
|
||||
local up = 2
|
||||
|
||||
-- if already in air then dont go up anymore when hit
|
||||
if v.y > 0 then
|
||||
if v.y > 0
|
||||
or self.fly then
|
||||
up = 0
|
||||
end
|
||||
|
||||
@ -1896,7 +1935,7 @@ minetest.register_entity(name, {
|
||||
if vec.x ~= 0
|
||||
and vec.z ~= 0 then
|
||||
|
||||
local yaw = math.atan(vec.z / vec.x) + 3 * pi / 2 - self.rotate
|
||||
local yaw = atan(vec.z / vec.x) + 3 * pi / 2 - self.rotate
|
||||
|
||||
if lp.x > s.x then
|
||||
yaw = yaw + pi
|
||||
@ -1912,14 +1951,13 @@ minetest.register_entity(name, {
|
||||
|
||||
-- attack puncher and call other mobs for help
|
||||
if self.passive == false
|
||||
and self.state ~= "flop"
|
||||
and self.child == false
|
||||
and hitter:get_player_name() ~= self.owner then
|
||||
|
||||
--if self.state ~= "attack" then
|
||||
-- attack whoever punched mob
|
||||
self.state = ""
|
||||
do_attack(self, hitter)
|
||||
--end
|
||||
-- attack whoever punched mob
|
||||
self.state = ""
|
||||
do_attack(self, hitter)
|
||||
|
||||
-- alert others to the attack
|
||||
local obj = nil
|
||||
@ -2031,6 +2069,7 @@ minetest.register_entity(name, {
|
||||
self.mesh = mesh
|
||||
self.collisionbox = colbox
|
||||
self.visual_size = vis_size
|
||||
self.standing_in = ""
|
||||
|
||||
-- set anything changed above
|
||||
self.object:set_properties(self)
|
||||
@ -2266,6 +2305,11 @@ function mobs:explosion(pos, radius, fire, smoke, sound)
|
||||
and data[vi] ~= c_chest then
|
||||
|
||||
local n = node_ok(p).name
|
||||
local on_blast = minetest.registered_nodes[n].on_blast
|
||||
|
||||
if on_blast then
|
||||
return on_blast(p)
|
||||
end
|
||||
|
||||
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
|
||||
@ -2419,7 +2463,7 @@ function mobs:register_egg(mob, desc, background, addegg)
|
||||
local invimg = background
|
||||
|
||||
if addegg == 1 then
|
||||
invimg = invimg .. "^mobs_chicken_egg.png"
|
||||
invimg = invimg .. "^mobs_chicken_egg.png" -- MFF
|
||||
end
|
||||
|
||||
minetest.register_craftitem(mob, {
|
||||
|
@ -60,7 +60,7 @@ mobs:register_mob("mobs:cow", {
|
||||
view_range = 7,
|
||||
replace_rate = 10,
|
||||
replace_what = {"default:grass_3", "default:grass_4", "default:grass_5", "farming:wheat_8"},
|
||||
replace_with = "air",
|
||||
replace_with = "mobs:dung",
|
||||
fear_height = 2,
|
||||
on_rightclick = function(self, clicker)
|
||||
|
||||
|
@ -22,7 +22,6 @@ local all_colours = {
|
||||
for _, col in pairs(all_colours) do
|
||||
|
||||
mobs:register_mob("mobs:sheep_"..col[1], {
|
||||
|
||||
-- animal, monster, npc, barbarian
|
||||
type = "animal",
|
||||
-- not aggressive
|
||||
@ -36,7 +35,7 @@ for _, col in pairs(all_colours) do
|
||||
visual = "mesh",
|
||||
mesh = "mobs_sheep.b3d",
|
||||
textures = {
|
||||
{"mobs_sheep_wool.png^[colorize:" .. col[3] .. "^mobs_sheep_base.png"},
|
||||
{"mobs_sheep_base.png^(mobs_sheep_wool.png^[colorize:" .. col[3] .. ")"},
|
||||
},
|
||||
-- specific texture and mesh for gotten
|
||||
gotten_texture = {"mobs_sheep_shaved.png"},
|
||||
|
BIN
mods/mobs/textures/mobs_sheep_base.png
Executable file → Normal file
Before Width: | Height: | Size: 649 B After Width: | Height: | Size: 635 B |
BIN
mods/mobs/textures/mobs_sheep_shaved.png
Executable file → Normal file
Before Width: | Height: | Size: 927 B After Width: | Height: | Size: 983 B |
BIN
mods/mobs/textures/mobs_sheep_white.png
Executable file
After Width: | Height: | Size: 3.2 KiB |
BIN
mods/mobs/textures/mobs_sheep_wool.png
Executable file → Normal file
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |