catch and tame riverfish

This commit is contained in:
berengma 2019-11-30 13:01:47 +01:00
parent 7e7aa0fb7c
commit 3f9e8fd110
10 changed files with 645 additions and 535 deletions

21
api.lua
View File

@ -11,11 +11,18 @@ local sign = math.sign
local time = os.time
local abr = minetest.get_mapgen_setting('active_block_range') or 2
local abo = minetest.get_mapgen_setting('active_object_send_range_blocks') or 3
function water_life.handle_drops(self) -- drop on death what is definded in the entity table
-- throws a coin
function water_life.leftorright()
local rnd = math.random()
if rnd > 0.5 then return true else return false end
end
-- drop on death what is definded in the entity table
function water_life.handle_drops(self)
if not self.drops then return end
for _,item in ipairs(self.drops) do
@ -34,6 +41,7 @@ function water_life.handle_drops(self) -- drop on death what is definded in t
end
function water_life.register_shark_food(name)
table.insert(water_life.shark_food,name)
end
@ -44,6 +52,7 @@ function water_life.feed_shark()
return water_life.shark_food[index]
end
function water_life.aqua_radar_dumb(pos,yaw,range,reverse)
range = range or 4
@ -98,7 +107,7 @@ end
-- counts animals in specified radius or active_object_send_range_blocks, returns a table containing numbers
function water_life.count_objects(pos,radius)
if not radius then radius = abo * 16 end
if not radius then radius = water_life.abo * 16 end
local all_objects = minetest.get_objects_inside_radius(pos, radius)
local hasil = {}
@ -114,7 +123,7 @@ for _,obj in ipairs(all_objects) do
hasil.whales = hasil.whales +1
elseif entity and entity.name == "water_life:shark" then
hasil.sharks = hasil.sharks +1
elseif entity and entity.name == "water_life:fish" then
elseif entity and (entity.name == "water_life:fish" or entity.name == "water_life:fish_tamed") then
hasil.fish = hasil.fish +1
end
end
@ -217,7 +226,7 @@ function water_life.big_aqua_roam(self,prty,speed)
end
end
if mobkit.timer(self,10) then
if vector.distance(pos,center) > abo*16*0.5 then
if vector.distance(pos,center) > water_life.abo*16*0.5 then
tyaw = minetest.dir_to_yaw(vector.direction(pos,{x=center.x+random()*10-5,y=center.y,z=center.z+random()*10-5}))
else
if random(10)>=9 then tyaw=tyaw+random()*pi - pi*0.5 end

View File

@ -22,3 +22,30 @@ minetest.register_craft({
recipe = "water_life:meat_raw",
cooktime = 5
})
minetest.register_craftitem("water_life:riverfish", {
description = ("Riverfish"),
inventory_image = "water_life_riverfish_item.png",
wield_scale = {x = 0.5, y = 0.5, z = 0.5},
stack_max = 10,
liquids_pointable = false,
range = 10,
on_use = minetest.item_eat(3),
groups = {food_meat = 1, flammable = 2},
on_place = function(itemstack, placer, pointed_thing)
if placer and not placer:is_player() then return itemstack end
if not pointed_thing then return itemstack end
if not pointed_thing.type == "node" then return itemstack end
local pos = pointed_thing.above
local number = water_life.count_objects(pos)
if number.all > water_life.maxmobs or number.fish > 10 then return itemstack end
local name = placer:get_player_name()
local obj = minetest.add_entity(pos, "water_life:fish_tamed")
obj = obj:get_luaentity()
itemstack:take_item()
obj.owner = name
return itemstack
end,
})

View File

@ -1,2 +1,3 @@
default
mobkit
fireflies?

546
init.lua
View File

@ -1,6 +1,13 @@
water_life = {}
water_life.shark_food = {}
water_life.abr = minetest.get_mapgen_setting('active_block_range') or 2
water_life.abo = minetest.get_mapgen_setting('active_object_send_range_blocks') or 3
water_life.whale_spawn_rate = 30 -- chances in promille 30 promille = 3%
water_life.shark_spawn_rate = 100
water_life.fish_spawn_rate = 1000
water_life.maxwhales = 1
water_life.maxsharks = water_life.abo/2
water_life.maxmobs = 30
math.randomseed(os.time()) --init random seed
@ -9,11 +16,11 @@ local path = minetest.get_modpath(minetest.get_current_modname())
dofile(path.."/api.lua") -- load water_life api
dofile(path.."/crafts.lua") -- load crafts
dofile(path.."/spawn.lua") -- load spawn function
dofile(path.."/whale.lua") -- load whales
dofile(path.."/shark.lua") -- load sharks
dofile(path.."/riverfish.lua") -- load riverfish
if minetest.get_modpath("wildlife") then
water_life.register_shark_food("wildlife:deer")
water_life.register_shark_food("wildlife:wolf")
end
--remove old sharks
@ -29,531 +36,12 @@ minetest.register_entity(":zombiestrd:shark", {
end,
})
local abr = minetest.get_mapgen_setting('active_block_range') or 2
local abo = minetest.get_mapgen_setting('active_object_send_range_blocks') or 3
local nodename_water = minetest.registered_aliases.mapgen_water_source
local timer = 0
local abs = math.abs
local pi = math.pi
local floor = math.floor
local random = math.random
local sqrt = math.sqrt
local max = math.max
local min = math.min
local pow = math.pow
local sign = math.sign
local time = os.time
local whale_spawn_rate = 30
local shark_spawn_rate = 100
local fish_spawn_rate = 1000
local maxwhales = 1
local maxsharks = abo/2
local maxfish = 10
local maxmobs = 30
-- water_life.register_shark_food("water_life:fish") --fish is too small for sharks
-------------------
-- Helper Functions
-------------------
-- throws a coin
local function leftorright()
local rnd = math.random()
if rnd > 0.5 then return true else return false end
-- register shark food
water_life.register_shark_food("water_life:fish") --fish is too small for sharks
if minetest.get_modpath("wildlife") then
water_life.register_shark_food("wildlife:deer")
water_life.register_shark_food("wildlife:wolf")
end
-- this is whale specific, so keeping it local
local function chose_turn(self,pos,yaw)
local remember = mobkit.recall(self,"turn")
if not remember then
if leftorright() then
remember = "1"
mobkit.remember(self,"time", self.time_total)
mobkit.remember(self,"turn", "1")
else
remember = "0"
mobkit.remember(self,"time", self.time_total)
mobkit.remember(self,"turn", "0")
end
end
local clockpos = mobkit.pos_translate2d(pos,yaw+(pi/4),10)
local clockpos1 = mobkit.pos_shift(clockpos,{x=-3,y=-2,z=-3})
clockpos = mobkit.pos_shift(clockpos,{x=3,y=3,z=3})
local revpos = mobkit.pos_translate2d(pos,yaw-(pi/4),10)
local revpos1 = mobkit.pos_shift(revpos,{x=-3,y=-2,z=-3})
revpos = mobkit.pos_shift(revpos,{x=3,y=3,z=3})
local ccheck= minetest.find_nodes_in_area(clockpos,clockpos1, {"group:water","default:sand_with_kelp"})
local rcheck = minetest.find_nodes_in_area(revpos,revpos1, {"group:water","default:sand_with_kelp"})
--minetest.chat_send_all(dump(#rcheck).." : "..dump(#ccheck).." "..dump(remember).." --> "..dump(self.isonground))
local a = #ccheck
local b = #rcheck
if a > b+15 then
mobkit.remember(self,"turn", "1")
mobkit.remember(self,"time", self.time_total)
return false
elseif a < b-15 then
mobkit.remember(self,"turn","0")
mobkit.remember(self,"time", self.time_total)
return true
else
if remember == "0" then return true else return false end
end
end
-----------------
-- Spawn Function
-----------------
local function spawnstep(dtime)
timer = timer + dtime
if timer > 5 then
for _,plyr in ipairs(minetest.get_connected_players()) do
local coin = random(1000)
--minetest.chat_send_all(dump(coin))
if plyr then -- each player gets a spawn chance every 5s on average
local pos = plyr:get_pos()
local yaw = plyr:get_look_horizontal()
local chance = shark_spawn_rate
local animal = water_life.count_objects(pos)
--minetest.chat_send_all("yaw = "..dump(yaw).." mobs: "..dump(all_objects).." sharks: "..dump(ms).." whales: "..dump(mw))
if animal.all > maxmobs then break end
-- find a pos randomly in look direction of player
local radius = (abo * 12) - 1 -- 75% from 16 = 12 nodes
radius = math.random(7,radius)
local angel = math.random() * (pi/4) -- look for random angel 0 - 45 degrees
if leftorright() then yaw = yaw + angel else yaw = yaw - angel end -- add or substract to/from yaw
local pos2 = mobkit.pos_translate2d(pos,yaw,radius)
local height, liquidflag = mobkit.get_terrain_height(pos2,32)
--minetest.chat_send_all(dump(height).." "..dump(liquidflag))
if height and liquidflag then
local mobname = 'water_life:shark'
if shark_spawn_rate >= coin then
pos2.y = height+1.01
local a=pos2.x
local b=pos2.y
local c=pos2.z
local water = minetest.find_nodes_in_area({x=a-3, y=b-3, z=c-3}, {x=a+4, y=b+4, z=c+4}, {"default:water_source"})
if #water < 128 then break end -- sharks need water, much water
if animal.sharks > (maxsharks-1) then break end -- sharks are no sardines
local obj=minetest.add_entity(pos2,mobname) -- ok spawn it already damnit
end
local mobname = 'water_life:fish'
if fish_spawn_rate >= coin then
pos2.y = height+1.01
local a=pos2.x
local b=pos2.y
local c=pos2.z
local nearlife = water_life.count_objects(pos2,16)
local water = minetest.find_nodes_in_area({x=a-2, y=b-2, z=c-2}, {x=a+2, y=b+2, z=c+2}, {"default:river_water_source"})
if water and #water < 10 then break end -- little fish need little water
--minetest.chat_send_all("water ="..dump(#water).." mobs="..dump(all_objects))
if animal.all > (maxmobs-5) or nearlife.fish > 5 then break end
local obj=minetest.add_entity(pos2,mobname) -- ok spawn it already damnit
end
if whale_spawn_rate >= coin then
pos2.y = height+4.01
mobname = 'water_life:whale'
local a=pos2.x
local b=pos2.y
local c=pos2.z
local water = minetest.find_nodes_in_area({x=a-5, y=b-5, z=c-5}, {x=a+5, y=b+5, z=c+5}, {"default:water_source"})
if #water < 900 then break end -- whales need water, much water
if animal.whales > (maxwhales-1) then break end -- whales are no sardines
local obj=minetest.add_entity(pos2,mobname) -- ok spawn it already damnit
end
end
end
end
timer = 0
end
end
minetest.register_globalstep(spawnstep)
-------------
-- The Brains
-------------
local function whale_brain(self)
if self.hp <= 0 then
mobkit.clear_queue_high(self)
water_life.handle_drops(self)
mobkit.make_sound(self,"death")
mobkit.hq_die(self)
return
end
-- check every 2 seconds what is under whale's belly
if mobkit.timer(self,2) then
local stand = mobkit.get_stand_pos(self)
if stand then stand.y = stand.y - 1 end
local node = mobkit.nodeatpos(stand)
if node then
if node.name ~= "default:water_source" then
mobkit.hurt(self, 20)
end
end
end
-- big animals need to avoid obstacles
if mobkit.timer(self,1) then
local remember = mobkit.recall(self,"time")
if remember then
if self.time_total - remember > 59 then
mobkit.forget(self,"turn")
mobkit.forget(self,"time")
end
end
local yaw = self.object:get_yaw() + pi
local pos = mobkit.get_stand_pos(self)
local spos = mobkit.pos_translate2d(pos,yaw,15)
local hpos = mobkit.pos_translate2d(pos,yaw,6)
local head = mobkit.pos_shift(hpos,{y=4})
local node = minetest.get_node(head)
local left = mobkit.pos_shift(spos,{x=-3,y=3,z=-3})
local right = mobkit.pos_shift(spos,{x=3,y=3,z=3})
local up = mobkit.pos_shift(spos,{x=-1,y=3,z=-1})
local down = mobkit.pos_shift(spos,{x=1,y=-2,z=1})
yaw = yaw - pi
if node then -- anything above head ? dive.
if node.name ~= "default:water_source" and node.name ~= "air" then
local hvel = vector.multiply(vector.normalize({x=head.x,y=0,z=head.z}),4)
self.object:set_velocity({x=hvel.x,y=-1,z=hvel.z})
end
end
local vcheck= minetest.find_nodes_in_area(up,down, {"default:water_source"})
local hcheck = minetest.find_nodes_in_area(left,right, {"default:water_source"})
--minetest.chat_send_all(dump(#vcheck).." - "..dump(#hcheck))
if #vcheck < 54 or #hcheck < 49 then
--mobkit.clear_queue_high(self)
if chose_turn(self,pos,yaw) then
water_life.big_hq_aqua_turn(self,30,yaw+(pi/24),-0.5)
else
water_life.big_hq_aqua_turn(self,30,yaw-(pi/24),-0.5)
end
end
end
if mobkit.is_queue_empty_high(self) then water_life.big_aqua_roam(self,20,-1) end
end
local function shark_brain(self)
if self.hp <= 0 then
mobkit.clear_queue_high(self)
water_life.handle_drops(self)
mobkit.hq_die(self)
return
end
if mobkit.timer(self,1) then
local whale = mobkit.get_closest_entity(self,"water_life:whale")
if whale then
local spos = self.object:get_pos()
local wpos = whale:get_pos()
local distance = math.floor(vector.distance(spos,wpos))
if distance < 15 then
local yaw = self.object:get_yaw()
mobkit.clear_queue_high(self)
mobkit.hq_aqua_turn(self,40,yaw+(pi/2),5)
end
end
local prty = mobkit.get_queue_priority(self)
if prty < 20 then
local target = mobkit.get_nearby_player(self)
local foodname = water_life.feed_shark()
local food = mobkit.get_nearby_entity(self,foodname)
if target and mobkit.is_alive(target) and mobkit.is_in_deep(target) and target:get_attach() == nil then
mobkit.hq_aqua_attack(self,20,target,9)
end
if food and mobkit.is_in_deep(food) then
mobkit.clear_queue_high(self)
mobkit.hq_aqua_attack(self,30,food,7)
end
end
end
if mobkit.is_queue_empty_high(self) then mobkit.hq_aqua_roam(self,10,5) end
end
local function fish_brain(self)
if self.hp <= 0 then
mobkit.clear_queue_high(self)
water_life.handle_drops(self)
mobkit.hq_die(self)
return
end
if mobkit.timer(self,1) then
local plyr = mobkit.get_nearby_player(self)
if plyr then
water_life.hq_swimfrom(self,50,plyr,3)
end
if mobkit.is_queue_empty_high(self) then mobkit.hq_aqua_roam(self,10,1) end
end
end
---------------
-- the Entities
---------------
minetest.register_entity("water_life:whale",{
-- common props
physical = true,
stepheight = 0.1, --EVIL!
weight = 250,
collide_with_objects = false,
collisionbox = {-3, -2, -3, 3, 2, 3},
visual = "mesh",
mesh = "water_life_whale.b3d",
textures = {"water_life_whale.png"},
visual_size = {x = 3.5, y = 3.5},
drops = {
{name = "default:diamond", chance = 5, min = 10, max = 50,},
{name = "water_life:meat_raw", chance = 1, min = 15, max = 65,},
},
static_save = false,
makes_footstep_sound = true,
on_step = mobkit.stepfunc, -- required
on_activate = mobkit.actfunc, -- required
get_staticdata = mobkit.statfunc,
-- api props
springiness=0,
buoyancy = 0.98, -- portion of hitbox submerged
max_speed = -1,
jump_height = 1.26,
view_range = 32,
-- lung_capacity = 0, -- seconds
max_hp = 500,
timeout=300,
attack={range=4.5,damage_groups={fleshy=15}},
sounds = {
random = "water_life_whale.ogg",
death = "water_life_whale.ogg",
distance = 10,
},
animation = {
def={range={x=1,y=59},speed=5,loop=true},
fast={range={x=1,y=59},speed=20,loop=true},
back={range={x=15,y=1},speed=7,loop=false},
},
brainfunc = whale_brain,
on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if mobkit.is_alive(self) then
local obj = self.object
local hvel = vector.multiply(vector.normalize({x=dir.x,y=0,z=dir.z}),4)
self.object:set_velocity({x=hvel.x,y=2,z=hvel.z})
self.object:add_velocity({x=0,y=-5, z=0})
if time_from_last_punch > 2 then
mobkit.hurt(self,tool_capabilities.damage_groups.fleshy or 1)
else
if puncher:is_player() then
minetest.chat_send_player(puncher:get_player_name(),">>> You missed <<<")
end
end
obj:set_nametag_attributes({
color = '#ff7373',
text = ">>> "..tostring(math.floor(self.hp/5)).."% <<<",
})
end
end,
})
minetest.register_entity("water_life:shark",{
-- common props
physical = true,
stepheight = 0.1, --EVIL!
collide_with_objects = false,
collisionbox = {-0.5, -0.3, -0.5, 0.5, 0.3, 0.5},
visual = "mesh",
mesh = "water_life_shark.b3d",
textures = {"water_life_shark3tex.png"},
visual_size = {x = 1.5, y = 1.5},
static_save = false,
makes_footstep_sound = true,
on_step = mobkit.stepfunc, -- required
on_activate = mobkit.actfunc, -- required
get_staticdata = mobkit.statfunc,
-- api props
springiness=0,
buoyancy = 0.98, -- portion of hitbox submerged
max_speed = 9,
jump_height = 1.26,
view_range = abo * 12,
-- lung_capacity = 0, -- seconds
max_hp = 50,
timeout=60,
drops = {
{name = "default:diamond", chance = 5, min = 1, max = 5,},
{name = "water_life:meat_raw", chance = 2, min = 1, max = 5,},
},
attack={range=0.8,damage_groups={fleshy=7}},
--sounds = {
-- attack='water_life_sharkattack',
-- },
animation = {
def={range={x=1,y=59},speed=40,loop=true},
fast={range={x=1,y=59},speed=80,loop=true},
back={range={x=15,y=1},speed=-15,loop=false},
},
brainfunc = shark_brain,
on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if mobkit.is_alive(self) then
local hvel = vector.multiply(vector.normalize({x=dir.x,y=0,z=dir.z}),4)
self.object:set_velocity({x=hvel.x,y=2,z=hvel.z})
mobkit.hurt(self,tool_capabilities.damage_groups.fleshy or 1)
if type(puncher)=='userdata' and puncher:is_player() then -- if hit by a player
mobkit.clear_queue_high(self) -- abandon whatever they've been doing
mobkit.hq_aqua_attack(self,20,puncher,6) -- get revenge
end
end
end,
})
minetest.register_entity("water_life:fish",{
-- common props
physical = true,
stepheight = 0.1, --EVIL!
collide_with_objects = false,
collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
visual = "mesh",
mesh = "water_life_riverfish.b3d",
textures = {"water_life_riverfish.png"},
visual_size = {x = 2.5, y = 2.5},
static_save = false,
makes_footstep_sound = true,
on_step = mobkit.stepfunc, -- required
on_activate = mobkit.actfunc, -- required
get_staticdata = mobkit.statfunc,
-- api props
springiness=0,
buoyancy = 1.07, -- portion of hitbox submerged
max_speed = 3, -- negative speed as long as model is not rotatet in head direction
jump_height = 0.5,
view_range = 4,
-- lung_capacity = 0, -- seconds
max_hp = 10,
timeout=60,
drops = {
{name = "default:diamond", chance = 20, min = 1, max = 1,},
{name = "water_life:meat_raw", chance = 2, min = 1, max = 1,},
},
animation = {
def={range={x=1,y=35},speed=40,loop=true},
fast={range={x=1,y=35},speed=80,loop=true},
idle={range={x=36,y=75},speed=20,loop=true},
},
brainfunc = fish_brain,
on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if mobkit.is_alive(self) then
mobkit.hurt(self,tool_capabilities.damage_groups.fleshy or 1)
end
end,
})

145
riverfish.lua Normal file
View File

@ -0,0 +1,145 @@
local function fish_brain(self)
if self.hp <= 0 then
mobkit.clear_queue_high(self)
water_life.handle_drops(self)
mobkit.hq_die(self)
return
end
if mobkit.timer(self,1) then
local plyr = mobkit.get_nearby_player(self)
if plyr and self.wild then
water_life.hq_swimfrom(self,50,plyr,3)
end
if mobkit.is_queue_empty_high(self) then mobkit.hq_aqua_roam(self,10,1) end
end
end
---------------
-- the Entities
---------------
minetest.register_entity("water_life:fish",{
-- common props
physical = true,
stepheight = 0.3,
collide_with_objects = false,
collisionbox = {-0.15, -0.15, -0.15, 0.15, 0.15, 0.15},
visual = "mesh",
mesh = "water_life_riverfish.b3d",
textures = {"water_life_riverfish.png"},
visual_size = {x = 2.5, y = 2.5},
static_save = false,
makes_footstep_sound = true,
on_step = mobkit.stepfunc, -- required
on_activate = mobkit.actfunc, -- required
get_staticdata = mobkit.statfunc,
-- api props
springiness=0,
buoyancy = 1.07, -- portion of hitbox submerged
max_speed = 3,
jump_height = 0.5,
view_range = 4,
-- lung_capacity = 0, -- seconds
max_hp = 10,
timeout=60,
wild = true,
drops = {
{name = "default:diamond", chance = 20, min = 1, max = 1,},
{name = "water_life:meat_raw", chance = 2, min = 1, max = 1,},
},
animation = {
def={range={x=1,y=35},speed=40,loop=true},
fast={range={x=1,y=35},speed=80,loop=true},
idle={range={x=36,y=75},speed=20,loop=true},
},
brainfunc = fish_brain,
on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if mobkit.is_alive(self) then
mobkit.hurt(self,tool_capabilities.damage_groups.fleshy or 1)
end
end,
on_rightclick = function(self, clicker)
if not clicker or not clicker:is_player() then return end
local inv = clicker:get_inventory()
local item = clicker:get_wielded_item()
if not item or item:get_name() ~= "fireflies:bug_net" then return end
if not inv:room_for_item("main", "water_life:fish") then return end
inv:add_item("main", "water_life:riverfish")
self.object:remove()
end,
})
minetest.register_entity("water_life:fish_tamed",{
-- common props
physical = true,
stepheight = 0.3,
collide_with_objects = false,
collisionbox = {-0.15, -0.15, -0.15, 0.15, 0.15, 0.15},
visual = "mesh",
mesh = "water_life_riverfish.b3d",
textures = {"water_life_riverfish_tamed.png"},
visual_size = {x = 2.5, y = 2.5},
static_save = true,
makes_footstep_sound = true,
on_step = mobkit.stepfunc, -- required
on_activate = mobkit.actfunc, -- required
get_staticdata = mobkit.statfunc,
-- api props
springiness=0,
buoyancy = 1.07, -- portion of hitbox submerged
max_speed = 3,
jump_height = 0.5,
view_range = 4,
-- lung_capacity = 0, -- seconds
max_hp = 10,
timeout=60,
wild = false,
owner = "",
drops = {
{name = "default:diamond", chance = 20, min = 1, max = 1,},
{name = "water_life:meat_raw", chance = 2, min = 1, max = 1,},
},
animation = {
def={range={x=1,y=35},speed=40,loop=true},
fast={range={x=1,y=35},speed=80,loop=true},
idle={range={x=36,y=75},speed=20,loop=true},
},
brainfunc = fish_brain,
on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if mobkit.is_alive(self) then
if self.owner and self.owner ~= puncher:get_player_name() and self.owner ~= "" then return end
if not puncher or not puncher:is_player() then return end
mobkit.hurt(self,tool_capabilities.damage_groups.fleshy or 1)
end
end,
on_rightclick = function(self, clicker)
if not clicker or not clicker:is_player() then return end
local inv = clicker:get_inventory()
local item = clicker:get_wielded_item()
if not item or item:get_name() ~= "fireflies:bug_net" then return end
if not inv:room_for_item("main", "water_life:fish") then return end
if self.owner and self.owner ~= clicker:get_player_name() and self.owner ~= "" then return end
inv:add_item("main", "water_life:riverfish")
self.object:remove()
end,
})

109
shark.lua Normal file
View File

@ -0,0 +1,109 @@
local abs = math.abs
local pi = math.pi
local floor = math.floor
local random = math.random
local sqrt = math.sqrt
local max = math.max
local min = math.min
local pow = math.pow
local sign = math.sign
local function shark_brain(self)
if self.hp <= 0 then
mobkit.clear_queue_high(self)
water_life.handle_drops(self)
mobkit.hq_die(self)
return
end
if mobkit.timer(self,1) then
local whale = mobkit.get_closest_entity(self,"water_life:whale")
if whale then
local spos = self.object:get_pos()
local wpos = whale:get_pos()
local distance = math.floor(vector.distance(spos,wpos))
if distance < 15 then
local yaw = self.object:get_yaw()
mobkit.clear_queue_high(self)
mobkit.hq_aqua_turn(self,40,yaw+(pi/2),5)
end
end
local prty = mobkit.get_queue_priority(self)
if prty < 20 then
local target = mobkit.get_nearby_player(self)
local foodname = water_life.feed_shark()
local food = mobkit.get_nearby_entity(self,foodname)
if target and mobkit.is_alive(target) and mobkit.is_in_deep(target) and target:get_attach() == nil then
mobkit.hq_aqua_attack(self,20,target,9)
end
if food and mobkit.is_in_deep(food) then
mobkit.clear_queue_high(self)
mobkit.hq_aqua_attack(self,30,food,7)
end
end
end
if mobkit.is_queue_empty_high(self) then mobkit.hq_aqua_roam(self,10,5) end
end
minetest.register_entity("water_life:shark",{
-- common props
physical = true,
stepheight = 0.1, --EVIL!
collide_with_objects = false,
collisionbox = {-0.5, -0.3, -0.5, 0.5, 0.3, 0.5},
visual = "mesh",
mesh = "water_life_shark.b3d",
textures = {"water_life_shark3tex.png"},
visual_size = {x = 1.5, y = 1.5},
static_save = false,
makes_footstep_sound = true,
on_step = mobkit.stepfunc, -- required
on_activate = mobkit.actfunc, -- required
get_staticdata = mobkit.statfunc,
-- api props
springiness=0,
buoyancy = 0.98, -- portion of hitbox submerged
max_speed = 9,
jump_height = 1.26,
view_range = water_life.abo * 12,
-- lung_capacity = 0, -- seconds
max_hp = 50,
timeout=60,
drops = {
{name = "default:diamond", chance = 5, min = 1, max = 5,},
{name = "water_life:meat_raw", chance = 2, min = 1, max = 5,},
},
attack={range=0.8,damage_groups={fleshy=7}},
--sounds = {
-- attack='water_life_sharkattack',
-- },
animation = {
def={range={x=1,y=59},speed=40,loop=true},
fast={range={x=1,y=59},speed=80,loop=true},
back={range={x=15,y=1},speed=-15,loop=false},
},
brainfunc = shark_brain,
on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if mobkit.is_alive(self) then
local hvel = vector.multiply(vector.normalize({x=dir.x,y=0,z=dir.z}),4)
self.object:set_velocity({x=hvel.x,y=2,z=hvel.z})
mobkit.hurt(self,tool_capabilities.damage_groups.fleshy or 1)
if type(puncher)=='userdata' and puncher:is_player() then -- if hit by a player
mobkit.clear_queue_high(self) -- abandon whatever they've been doing
mobkit.hq_aqua_attack(self,20,puncher,6) -- get revenge
end
end
end,
})

108
spawn.lua Normal file
View File

@ -0,0 +1,108 @@
local timer = 0
local pi = math.pi
local function spawnstep(dtime)
timer = timer + dtime
if timer > 5 then
for _,plyr in ipairs(minetest.get_connected_players()) do
local coin = math.random(1000)
--minetest.chat_send_all(dump(coin))
if plyr then -- each player gets a spawn chance every 5s on average
local pos = plyr:get_pos()
local yaw = plyr:get_look_horizontal()
local animal = water_life.count_objects(pos)
--minetest.chat_send_all("yaw = "..dump(yaw).." mobs: "..dump(all_objects).." sharks: "..dump(ms).." whales: "..dump(mw))
if animal.all > water_life.maxmobs then break end
-- find a pos randomly in look direction of player
local radius = (water_life.abo * 12) - 1 -- 75% from 16 = 12 nodes
radius = math.random(7,radius)
local angel = math.random() * (pi/4) -- look for random angel 0 - 45 degrees
if water_life.leftorright() then yaw = yaw + angel else yaw = yaw - angel end -- add or substract to/from yaw
local pos2 = mobkit.pos_translate2d(pos,yaw,radius)
local height, liquidflag = mobkit.get_terrain_height(pos2,32)
--minetest.chat_send_all(dump(height).." "..dump(liquidflag))
if height and liquidflag then
local mobname = 'water_life:shark'
if water_life.shark_spawn_rate >= coin then
pos2.y = height+1.01
local a=pos2.x
local b=pos2.y
local c=pos2.z
local water = minetest.find_nodes_in_area({x=a-3, y=b-3, z=c-3}, {x=a+4, y=b+4, z=c+4}, {"default:water_source"})
if #water < 128 then break end -- sharks need water, much water
if animal.sharks > (water_life.maxsharks-1) then break end -- sharks are no sardines
local obj=minetest.add_entity(pos2,mobname) -- ok spawn it already damnit
end
local mobname = 'water_life:fish'
if water_life.fish_spawn_rate >= coin then
pos2.y = height+1.01
local a=pos2.x
local b=pos2.y
local c=pos2.z
local nearlife = water_life.count_objects(pos2,16)
local water = minetest.find_nodes_in_area({x=a-2, y=b-2, z=c-2}, {x=a+2, y=b+2, z=c+2}, {"default:river_water_source"})
if water and #water < 10 then break end -- little fish need little water
--minetest.chat_send_all("water ="..dump(#water).." mobs="..dump(all_objects))
if animal.all > (water_life.maxmobs-5) or nearlife.fish > 5 then break end
local obj=minetest.add_entity(pos2,mobname) -- ok spawn it already damnit
end
if water_life.whale_spawn_rate >= coin then
pos2.y = height+4.01
mobname = 'water_life:whale'
local a=pos2.x
local b=pos2.y
local c=pos2.z
local water = minetest.find_nodes_in_area({x=a-5, y=b-5, z=c-5}, {x=a+5, y=b+5, z=c+5}, {"default:water_source"})
if #water < 900 then break end -- whales need water, much water
if animal.whales > (water_life.maxwhales-1) then break end -- whales are no sardines
local obj=minetest.add_entity(pos2,mobname) -- ok spawn it already damnit
end
end
end
end
timer = 0
end
end
minetest.register_globalstep(spawnstep)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

223
whale.lua Normal file
View File

@ -0,0 +1,223 @@
local abs = math.abs
local pi = math.pi
local floor = math.floor
local random = math.random
local sqrt = math.sqrt
local max = math.max
local min = math.min
local pow = math.pow
local sign = math.sign
-- this is whale specific, so keeping it local
local function chose_turn(self,pos,yaw)
local remember = mobkit.recall(self,"turn")
if not remember then
if water_life.leftorright() then
remember = "1"
mobkit.remember(self,"time", self.time_total)
mobkit.remember(self,"turn", "1")
else
remember = "0"
mobkit.remember(self,"time", self.time_total)
mobkit.remember(self,"turn", "0")
end
end
local clockpos = mobkit.pos_translate2d(pos,yaw+(pi/4),10)
local clockpos1 = mobkit.pos_shift(clockpos,{x=-3,y=-2,z=-3})
clockpos = mobkit.pos_shift(clockpos,{x=3,y=3,z=3})
local revpos = mobkit.pos_translate2d(pos,yaw-(pi/4),10)
local revpos1 = mobkit.pos_shift(revpos,{x=-3,y=-2,z=-3})
revpos = mobkit.pos_shift(revpos,{x=3,y=3,z=3})
local ccheck= minetest.find_nodes_in_area(clockpos,clockpos1, {"group:water","default:sand_with_kelp"})
local rcheck = minetest.find_nodes_in_area(revpos,revpos1, {"group:water","default:sand_with_kelp"})
--minetest.chat_send_all(dump(#rcheck).." : "..dump(#ccheck).." "..dump(remember).." --> "..dump(self.isonground))
local a = #ccheck
local b = #rcheck
if a > b+15 then
mobkit.remember(self,"turn", "1")
mobkit.remember(self,"time", self.time_total)
return false
elseif a < b-15 then
mobkit.remember(self,"turn","0")
mobkit.remember(self,"time", self.time_total)
return true
else
if remember == "0" then return true else return false end
end
end
-- The Brain !
local function whale_brain(self)
if self.hp <= 0 then
mobkit.clear_queue_high(self)
water_life.handle_drops(self)
mobkit.make_sound(self,"death")
mobkit.hq_die(self)
return
end
-- check every 2 seconds what is under whale's belly
if mobkit.timer(self,2) then
local stand = mobkit.get_stand_pos(self)
if stand then stand.y = stand.y - 1 end
local node = mobkit.nodeatpos(stand)
if node then
if node.name ~= "default:water_source" then
mobkit.hurt(self, 20)
end
end
end
-- big animals need to avoid obstacles
if mobkit.timer(self,1) then
local remember = mobkit.recall(self,"time")
if remember then
if self.time_total - remember > 59 then
mobkit.forget(self,"turn")
mobkit.forget(self,"time")
end
end
local yaw = self.object:get_yaw() + pi
local pos = mobkit.get_stand_pos(self)
local spos = mobkit.pos_translate2d(pos,yaw,15)
local hpos = mobkit.pos_translate2d(pos,yaw,6)
local head = mobkit.pos_shift(hpos,{y=4})
local node = minetest.get_node(head)
local left = mobkit.pos_shift(spos,{x=-3,y=3,z=-3})
local right = mobkit.pos_shift(spos,{x=3,y=3,z=3})
local up = mobkit.pos_shift(spos,{x=-1,y=3,z=-1})
local down = mobkit.pos_shift(spos,{x=1,y=-2,z=1})
yaw = yaw - pi
if node then -- anything above head ? dive.
if node.name ~= "default:water_source" and node.name ~= "air" then
local hvel = vector.multiply(vector.normalize({x=head.x,y=0,z=head.z}),4)
self.object:set_velocity({x=hvel.x,y=-1,z=hvel.z})
end
end
local vcheck= minetest.find_nodes_in_area(up,down, {"default:water_source"})
local hcheck = minetest.find_nodes_in_area(left,right, {"default:water_source"})
--minetest.chat_send_all(dump(#vcheck).." - "..dump(#hcheck))
if #vcheck < 54 or #hcheck < 49 then
--mobkit.clear_queue_high(self)
if chose_turn(self,pos,yaw) then
water_life.big_hq_aqua_turn(self,30,yaw+(pi/24),-0.5)
else
water_life.big_hq_aqua_turn(self,30,yaw-(pi/24),-0.5)
end
end
end
if mobkit.is_queue_empty_high(self) then water_life.big_aqua_roam(self,20,-1) end
end
minetest.register_entity("water_life:whale",{
-- common props
physical = true,
stepheight = 0.1, --EVIL!
weight = 250,
collide_with_objects = false,
collisionbox = {-3, -2, -3, 3, 2, 3},
visual = "mesh",
mesh = "water_life_whale.b3d",
textures = {"water_life_whale.png"},
visual_size = {x = 3.5, y = 3.5},
drops = {
{name = "default:diamond", chance = 5, min = 10, max = 50,},
{name = "water_life:meat_raw", chance = 1, min = 15, max = 65,},
},
static_save = false,
makes_footstep_sound = true,
on_step = mobkit.stepfunc, -- required
on_activate = mobkit.actfunc, -- required
get_staticdata = mobkit.statfunc,
-- api props
springiness=0,
buoyancy = 0.98, -- portion of hitbox submerged
max_speed = -1,
jump_height = 1.26,
view_range = 32,
-- lung_capacity = 0, -- seconds
max_hp = 500,
timeout=300,
attack={range=4.5,damage_groups={fleshy=15}},
sounds = {
random = "water_life_whale.ogg",
death = "water_life_whale.ogg",
distance = 10,
},
animation = {
def={range={x=1,y=59},speed=5,loop=true},
fast={range={x=1,y=59},speed=20,loop=true},
back={range={x=15,y=1},speed=7,loop=false},
},
brainfunc = whale_brain,
on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if mobkit.is_alive(self) then
local obj = self.object
local hvel = vector.multiply(vector.normalize({x=dir.x,y=0,z=dir.z}),4)
self.object:set_velocity({x=hvel.x,y=2,z=hvel.z})
self.object:add_velocity({x=0,y=-5, z=0})
if time_from_last_punch > 2 then
mobkit.hurt(self,tool_capabilities.damage_groups.fleshy or 1)
else
if puncher:is_player() then
minetest.chat_send_player(puncher:get_player_name(),">>> You missed <<<")
end
end
obj:set_nametag_attributes({
color = '#ff7373',
text = ">>> "..tostring(math.floor(self.hp/5)).."% <<<",
})
end
end,
})